Norvya Developers
Get a sandbox
API reference · Operations

Pharmacy

Built — gated23 endpoints · 2 webhook events · OpenAPI tag pharmacy

For pharmacies: the patient roster with dose-log adherence (an unrecorded dose is not a missed dose, and never a PDC), medication reviews to completion, discharge follow-up episodes with day-3 and day-30 checks, packing verification, deliveries, the medication sync plan (estimates from fills, never an order), monitoring and refills due. Webhooks for refills due and discharge episodes. Pharmacies only; a patient must share their medicines with the pharmacy. The assisted-living, group-home and nursing-home sites a pharmacy runs are in Care sites.

Who calls it
Core for Pharmacies
Before production
Pharmacies with a BAA on file (or a sandbox).
Sandbox
Build against synthetic members first. What each sandbox holds

Markets that use this family

Scopes

ScopeAllows
pharmacy.adherence.readRead a patient's dose log and adherence summary: taken, skipped and unrecorded kept apart (an unrecorded dose is never counted as missed) and never a proportion of days covered (pharmacies only; the patient must share medications with you).
pharmacy.delivery.writeRecord a verified pack (the four-item checklist, all confirmed) and a delivery confirmed at the door (pharmacies only).
pharmacy.episodes.writeOpen a discharge follow-up episode and record the day-3 / day-30 contacts, how each medication difference was resolved, the 30-day outcome and closing (pharmacies only).
pharmacy.patients.readRead your pharmacy's patients (medicines-sharing status, pack cycle, open discharge follow-up), discharge follow-up episodes, medication reviews, the packing queue and deliveries, the monitoring-due list (a consensus schedule, not an order) and refills due (pharmacies only, BAA on file).
pharmacy.reviews.writeStart a medication review, add the pharmacist's recommendations and the prescriber's answer, and complete it (pharmacies only).

Endpoints

Your pharmacy's patients

GET/v1/pharmacy/patientspharmacy.patients.read

Every active member: whether they share medications with you and, when they do, the pack cycle, the open discharge follow-up episode with its next due contact, and the care site they live at (one of yours). With pharmacy.adherence.read also the last 7 days' dose counts (taken, skipped and unrecorded kept apart; an unrecorded dose is never missed). A member who has not shared medications is listed with every field withheld.

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients" \
  -H "Authorization: Bearer $TOKEN"

A patient's dose log and adherence summary

GET/v1/pharmacy/patients/{member_ref}/adherencepharmacy.adherence.read

rx_doses.adherence_summary: confirmed_rate = taken / all due slots (a floor), recorded_rate = taken / (taken + skipped), an estimate over the recorded doses only; unrecorded doses are counted apart and never as missed. Not a proportion of days covered (that needs fill claims). Plus every dose recorded in the window, with who recorded it (patient, caregiver or staff).

Parameters

member_refpath · stringrequired
daysquery · integer

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/adherence" \
  -H "Authorization: Bearer $TOKEN"

A patient's medication reviews and whether one is due

GET/v1/pharmacy/patients/{member_ref}/medication-reviewspharmacy.patients.read

Parameters

member_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/medication-reviews" \
  -H "Authorization: Bearer $TOKEN"

Start a medication review (or return the open draft)

POST/v1/pharmacy/patients/{member_ref}/medication-reviewspharmacy.reviews.write

med_review.start_review: the patient's current medicines and the automatic flags (prompts for the pharmacist, not orders). One draft per patient: an open draft is refreshed and returned.

Parameters

member_refpath · stringrequired

All responses

201Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/medication-reviews" \
  -H "Authorization: Bearer $TOKEN"

One medication review

GET/v1/pharmacy/medication-reviews/{review_ref}pharmacy.patients.read

Parameters

review_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/medication-reviews/$REVIEW_REF" \
  -H "Authorization: Bearer $TOKEN"

Add a recommendation to a draft review

POST/v1/pharmacy/medication-reviews/{review_ref}/recommendationspharmacy.reviews.write

med_review.add_recommendation (409 review_completed; 404 finding_not_found; 422 invalid_intervention_kind / description_required / invalid_prescriber_response).

Parameters

review_refpath · stringrequired

Request body

Content type: application/json (required)

kindstringrequired

discrepancy_resolved | prescriber_contacted | dose_change_recommended | therapy_change_recommended | education | adherence_packaging | refill_sync | prior_authorization | cost_saving | other

descriptionstringrequired
finding_keystring | null

A finding of this review the recommendation addresses.

prescriber_responsestring

pending | accepted | declined | not_applicable

Errors specific to this call

409review_completed422invalid_intervention_kind

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/medication-reviews/$REVIEW_REF/recommendations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "string",
    "description": "string",
    "finding_key": "string",
    "prescriber_response": "string"
  }'

Complete a medication review

POST/v1/pharmacy/medication-reviews/{review_ref}/completepharmacy.reviews.write

Parameters

review_refpath · stringrequired

Request body

Content type: application/json

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/medication-reviews/$REVIEW_REF/complete" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "summary": "string"
  }'

Your discharge follow-up episodes

GET/v1/pharmacy/discharge-episodespharmacy.patients.read

The day-3 and day-30 contacts (due / overdue / done), the medication comparison counts and the 30-day outcome. An outcome that is null is "not known", never "no". Patients no longer linked or no longer sharing medications drop out.

Parameters

statusquery · string | null

open | closed

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/discharge-episodes" \
  -H "Authorization: Bearer $TOKEN"

Open a discharge follow-up episode

POST/v1/pharmacy/discharge-episodespharmacy.episodes.write

pharmacy_care.create_episode: the medication comparison is computed by med_reconcile.compare; pre_admission_meds defaults to the patient's list on file (422 invalid_discharged_from, date_out_of_range, medication_list_invalid).

Request body

Content type: application/json (required)

member_refstringrequired
discharge_datestringrequired

YYYY-MM-DD, not in the future.

discharged_fromstring

snf | hospital | rehab | other

facility_labelstring | null
discharge_medsarray of any | null

Medication list on discharge: strings or {name, dosage, frequency} objects.

pre_admission_medsarray of any | null

Default: the patient's medication list on file in Norvya.

Errors specific to this call

422invalid_discharged_from

All responses

201Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/discharge-episodes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "member_ref": "mr_3f9c1a0b7d2e4c6a8b1d0e2f",
    "discharge_date": "2026-10-12",
    "discharged_from": "string",
    "facility_label": "string",
    "discharge_meds": [
      null
    ],
    "pre_admission_meds": [
      null
    ]
  }'

One discharge follow-up episode

GET/v1/pharmacy/discharge-episodes/{episode_ref}pharmacy.patients.read

Parameters

episode_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF" \
  -H "Authorization: Bearer $TOKEN"

Replace the episode's medication lists (the comparison is recomputed)

PUT/v1/pharmacy/discharge-episodes/{episode_ref}/medicationspharmacy.episodes.write

Parameters

episode_refpath · stringrequired

Request body

Content type: application/json (required)

discharge_medsarray of any | null
pre_admission_medsarray of any | null

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X PUT "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF/medications" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "discharge_meds": [
      null
    ],
    "pre_admission_meds": [
      null
    ]
  }'

Record how one medication difference was resolved

POST/v1/pharmacy/discharge-episodes/{episode_ref}/resolutionspharmacy.episodes.write

Parameters

episode_refpath · stringrequired

Request body

Content type: application/json (required)

item_keystringrequired

One of the episode's reconciliation.review_keys.

statusstringrequired

confirmed_intentional | prescriber_contacted | corrected | not_applicable

notestring | null

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF/resolutions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "item_key": "string",
    "status": "string",
    "note": "string"
  }'

Record a day-3 or day-30 contact attempt

POST/v1/pharmacy/discharge-episodes/{episode_ref}/checks/{which}pharmacy.episodes.write

reached or declined completes the check with the items you confirmed; any other result is recorded as an attempt (422 invalid_check / invalid_contact_result).

Parameters

episode_refpath · stringrequired
whichpath · stringrequired

Request body

Content type: application/json (required)

contact_resultstringrequired

reached | no_answer | left_message | declined | wrong_number

itemsobject | null

The check's item_keys you confirmed (reached / declined complete the check).

notestring | null

Errors specific to this call

422invalid_check

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF/checks/$WHICH" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_result": "string",
    "items": {},
    "note": "string"
  }'

Record the 30-day outcome

POST/v1/pharmacy/discharge-episodes/{episode_ref}/outcomepharmacy.episodes.write

A readmission or ED visit needs its date inside the 30-day window (422 event_date_required / outside_30_day_window / invalid_outcome_source); a recorded event is mirrored once into the care events every consumer reads.

Parameters

episode_refpath · stringrequired

Request body

Content type: application/json (required)

readmittedboolean | null

null = not known (never read as no).

readmit_datestring | null
ed_visitboolean | null
ed_datestring | null
sourcestringrequired

patient_call | caregiver_call | prescriber | facility | hospital_notification | other

notestring | null

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF/outcome" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "readmitted": false,
    "readmit_date": "string",
    "ed_visit": false,
    "ed_date": "string",
    "source": "string",
    "note": "string"
  }'

Close (or reopen) an episode

POST/v1/pharmacy/discharge-episodes/{episode_ref}/closepharmacy.episodes.write

Parameters

episode_refpath · stringrequired

Request body

Content type: application/json

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/discharge-episodes/$EPISODE_REF/close" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reopen": false
  }'

The packing queue

GET/v1/pharmacy/packingpharmacy.patients.read

pharmacy_ops.packing_queue: active pack cycles due within `days` (overdue first), each with the change count against the last verified pack (the first pack has no baseline and says so).

Parameters

daysquery · integer

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/packing" \
  -H "Authorization: Bearer $TOKEN"

A patient's pack change report

GET/v1/pharmacy/patients/{member_ref}/packingpharmacy.patients.read

Parameters

member_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/packing" \
  -H "Authorization: Bearer $TOKEN"

Record a verified pack

POST/v1/pharmacy/patients/{member_ref}/packing/verifypharmacy.delivery.write

pharmacy_ops.verify_pack: every checklist item must be true (422 checklist_incomplete); the current list becomes the next baseline; mark_filled moves the pack cycle (404 cycle_not_found without one).

Parameters

member_refpath · stringrequired

Request body

Content type: application/json (required)

checklistobjectrequired

All four must be true: changes_reviewed, packed_to_current_list, labels_checked, second_check_done.

notestring | null
mark_filledboolean
fill_datestring | null

YYYY-MM-DD (default today) when mark_filled.

Errors specific to this call

404cycle_not_found

All responses

201Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/packing/verify" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "checklist": {},
    "note": "string",
    "mark_filled": false,
    "fill_date": "string"
  }'

A patient's confirmed deliveries

GET/v1/pharmacy/patients/{member_ref}/deliveriespharmacy.patients.read

Parameters

member_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/deliveries" \
  -H "Authorization: Bearer $TOKEN"

Confirm a delivery at the door

POST/v1/pharmacy/patients/{member_ref}/deliveriespharmacy.delivery.write

pharmacy_ops.record_delivery without a photo (422 recipient_required; 404 cycle_not_found when mark_filled and no cycle).

Parameters

member_refpath · stringrequired

Request body

Content type: application/json (required)

recipient_namestringrequired
notestring | null
mark_filledboolean
notify_familyboolean

Norvya's generic notice to family members the patient chose to share medications with.

Errors specific to this call

422recipient_required404cycle_not_found

All responses

201Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/deliveries" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_name": "string",
    "note": "string",
    "mark_filled": false,
    "notify_family": false
  }'

A refill-sync plan from your own fill records

GET/v1/pharmacy/patients/{member_ref}/sync-planpharmacy.patients.read

pharmacy_ops.sync_plan: when each medicine runs out and the short fill that reaches one sync date. Quantities assume steady use; estimates for the pharmacist, never an order.

Parameters

member_refpath · stringrequired
sync_datequery · string | null

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/patients/$MEMBER_REF/sync-plan" \
  -H "Authorization: Bearer $TOKEN"

Monitoring due across your patients

GET/v1/pharmacy/monitoring-duepharmacy.patients.read

care_sites.monitoring_due for every patient who shares medications: a consensus monitoring schedule (antipsychotics, lithium, valproate, carbamazepine, clozapine ANC, oral terbinafine) overridden per check by an active prescriber order you recorded. It lists what has not been RECORDED in Norvya, never that something was not done; the prescriber's orders win.

Parameters

statequery · string | null

Comma list of overdue | never_recorded | due_soon | ok | not_needed.

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/monitoring-due" \
  -H "Authorization: Bearer $TOKEN"

Pack refills due soon or overdue

GET/v1/pharmacy/refills-duepharmacy.patients.read

Your active pack cycles whose next fill is within `days` (overdue included), from rx_doses.pack_cycle_dict: next fill = last fill + cycle days; an overdue cycle is reported overdue, never rolled forward.

Parameters

daysquery · integer
member_refquery · string | null

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/pharmacy/refills-due" \
  -H "Authorization: Bearer $TOKEN"

Webhook events

Payloads carry no health data, only a reference to fetch with your token. Each event needs its scope as well as webhooks.manage. Signing and retries

EventScopeWhen
pharmacy.discharge_episode_openedpharmacy.patients.readA discharge follow-up episode opened.
pharmacy.refill_duepharmacy.patients.readA pack cycle of the pharmacy became due soon or overdue.

Generated from the Partner API router and developers_catalog.py. The router docstring is the source of each description.

↑ ↓ to moveEnter to open