Norvya Developers
Get a sandbox
API reference · Operations

Care transitions

Built — gated10 endpoints · 5 webhook events · OpenAPI tag transitions

For hospitals: send your HL7 v2 admission/discharge (ADT) feed and get counts back (never names or record numbers); a discharge opens the patient's 30-day follow-up. Run the follow-up from your own care-management system: the worklist (day N of 30, the 48-72 hour call, the 7-day visit, medicine reconciliation, red flags from the patient's check-ins with their MedlinePlus or CDC source), LACE and HOSPITAL scores only when every input is recorded, write-back of calls, visits, closes and returns, and operational outcomes with small cells withheld (not risk-adjusted HRRP measures; days at home only where ascertained). For practices on the receiving side: the admissions, discharges and ED visits Norvya received for your patients, with the Transitional Care Management clock, plus webhooks for each.

Who calls it
Core for Hospitals and health systems; useful for Concierge doctors, Independent practices, Federal (via primes)
Before production
A BAA, plus an ADT feed per hospital (or per practice for its own notices); the patient must be linked to the organisation and, for feed notices at a practice, share their medical history.
Sandbox
Build against synthetic members first. What each sandbox holds
Standards
HL7 v2 ADT; LACE and HOSPITAL scores only when every input is recorded

Markets that use this family

Scopes

ScopeAllows
transitions.adt.writeSend HL7 v2 ADT messages (A01 / A02 / A03 / A04) from your feed; matched only to your own linked patients on MRN + date of birth, counts returned, nothing echoed (treating practices and hospitals with a BAA on file).
transitions.notices.readRead the hospital admissions, discharges and ED visits Norvya received for a patient of your practice, with the Transitional Care Management windows (treating practices and hospitals; each patient's sharing choices apply).
transitions.readRead your hospital's post-discharge worklist, episode detail and operational outcomes (hospitals only, BAA on file).
transitions.writeEnrol post-discharge episodes and record calls, follow-up visits, closes and returns from your care-management system (hospitals only, BAA on file).

Endpoints

Send an HL7 v2 ADT batch from your feed

POST/v1/transitions/adttransitions.adt.write

A01 admit, A02 transfer, A03 discharge, A04 ED registration (patient class E). Each message is matched only to YOUR organisation's actively linked patients: a PID-3 identifier equal to the MRN Norvya holds for the patient AND the PID-7 birth date, or the full name AND birth date, on exactly one patient; anything else is held unmatched for your staff's review in Norvya, never guessed. Idempotent on MSH-10. At a hospital, an inpatient A03 opens the patient's 30-day post-discharge episode, and a later admission or ED visit inside the 30 days is recorded as a return. The response is counts only: names, identifiers and dates are never echoed. Same rules as Norvya's own feed endpoint: a treating practice or hospital (409 not_a_medical_practice) with a BAA on file (409 transitions_baa_required); each patient's sharing choices decide what your organisation then sees. 413 adt_batch_too_large over 5 MB (refused before the body is read whole); 415 unsupported_media_type.

Request body

One or more HL7 v2 ADT messages (MLLP framing or CR / LF segment ends), or JSON {"messages": "<the same text>"}. At most 5 MB.

Content type: text/plain, x-application/hl7-v2+er7, application/json (required)

messagesstringrequired

Errors specific to this call

409not_a_medical_practice413adt_batch_too_large415unsupported_media_type

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/adt" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: text/plain" \
  --data-binary @your_body_file
Response 200
{
  "received": 3,
  "parsed": 3,
  "recorded": 3,
  "matched": 2,
  "unmatched": 1,
  "duplicates": 0,
  "ignored": 0,
  "episodes_enrolled": 1,
  "returns_recorded": 0,
  "errors": [
    {
      "message": 3,
      "code": "invalid_date"
    }
  ],
  "posture": "string"
}

The response is the shape from the schema, not live data.

Enrol a discharged patient in 30-day post-discharge follow-up

POST/v1/transitions/episodestransitions.write

Opens the patient's episode exactly as a navigator does in Norvya (same validation, same duplicate rule: one episode per patient per discharge date, 409 episode_exists) and sends the patient Norvya's generic "your care team added a check-in" notice. The patient must be actively linked to your hospital (404 member_not_found). Validation errors are machine codes (422 discharge_date_required, discharge_date_too_old, discharge_date_in_future, admit_after_discharge, condition_invalid, disposition_invalid ...). Hospitals only (409 not_a_hospital) with a BAA on file (409 transitions_baa_required).

Parameters

tzquery · string | null

IANA zone for 'today' and the due times (default UTC).

EMR vendors also pass vendor (the practice) with a vendor-issued token. EMR vendor tokens

Request body

Content type: application/json (required)

member_refstringrequired

mr_... or ext:<your id>.

discharge_datestringrequired

YYYY-MM-DD; up to 30 days back, not after tomorrow.

admit_datestring | null

YYYY-MM-DD; needed for length of stay (risk scores).

conditionstring | null

heart_failure | copd | ami | pneumonia | hip_knee_replacement | sepsis | other (default other).

One of: heart_failure copd ami pneumonia hip_knee_replacement sepsis other
dispositionstring | null
One of: home home_health snf irf ltch hospice other
discharge_unitstring | null
discharge_servicestring | null
pcp_namestring | null
pcp_phonestring | null

Errors specific to this call

409episode_exists404member_not_found422discharge_date_required409not_a_hospital409transitions_baa_required

All responses

201Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/episodes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "admit_date": "2026-10-09",
    "condition": "heart_failure",
    "discharge_date": "2026-10-14",
    "discharge_unit": "4 West",
    "disposition": "home",
    "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
    "pcp_name": "Dr. Rivera"
  }'
Response 201
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Your post-discharge worklist: who to call, what is due, who is at risk

GET/v1/transitions/worklisttransitions.read

One row per episode, in the transitions team's order (an open red flag first, then an overdue call, then readmission-risk band, then a due call): day N of 30, what is due (the 48-72 hour call, the 7-day follow-up visit, medicine reconciliation, red-flag review) with due times, the open issues, and the LACE / HOSPITAL scores with citation ONLY when every input was recorded by staff (never imputed). Only patients whose link with your hospital is live. Hospitals only.

Parameters

duequery · string

all | today | overdue

conditionquery · string | null

heart_failure | copd | ami | pneumonia | hip_knee_replacement | sepsis | other

statusquery · string

active | completed | readmitted | withdrawn | all

tzquery · string | null

IANA zone (default UTC).

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/transitions/worklist" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "generated_at": "string",
  "tz": "America/New_York",
  "due_filter": "all",
  "due_rules": "string",
  "total": 0,
  "withheld_link_inactive": 0,
  "items": [
    {
      "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
      "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
      "external_id": "string",
      "status": "active",
      "source": "manual",
      "condition": "heart_failure",
      "disposition": "home",
      "admit_date": "2026-10-09",
      "discharge_date": "2026-10-14",
      "discharge_at": "string",
      "day": 2,
      "window_days": 30,
      "readmitted_on": "string",
      "readmission_source": "string",
      "ed_return_on": "string",
      "ed_return_source": "string",
      "issues": [
        "contact_due"
      ],
      "due": [
        {}
      ],
      "risk": {
        "audience": "string",
        "band": "high",
        "lace": {},
        "hospital": {},
        "not_scored": {
          "hospital": [
            "hemoglobin_g_dl",
            "sodium_mmol_l"
          ]
        },
        "note": "string"
      }
    }
  ],
  "posture": "string"
}

The response is the shape from the schema, not live data.

One post-discharge episode: contacts, follow-up, check-ins, medicines, tasks

GET/v1/transitions/episodes/{episode_id}transitions.read

The episode's state and record: calls made, the follow-up visit, every check-in with what the patient answered and each red flag as its source's wording and citation (MedlinePlus / CDC), medicine reconciliation per medicine (staff-confirmed or not, the patient's answer), open and resolved tasks, and the readmission-risk scores when recorded. 404 episode_not_found for an id that is not an episode of your hospital or whose patient's link is no longer live (one answer for both).

Parameters

episode_idpath · stringrequired
tzquery · string | null

IANA zone (default UTC).

Errors specific to this call

404episode_not_found

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/transitions/episodes/$EPISODE_ID" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Record a call to the patient

POST/v1/transitions/episodes/{episode_id}/contactstransitions.write

A call attempt from your care-management system: outcome (reached stops the 48-72 hour clock), optional note, optional time WITH an offset (422 contact_at_needs_offset, contact_in_future). Returns the episode.

Parameters

episode_idpath · stringrequired
tzquery · string | null

Request body

Content type: application/json (required)

outcomestringrequired
One of: reached no_answer left_message wrong_number declined
notestring | null
contact_atstring | null

ISO 8601 WITH an offset (default now).

Errors specific to this call

422contact_at_needs_offset

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/episodes/$EPISODE_ID/contacts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_at": "2026-10-15T15:30:00Z",
    "note": "Weighing daily, has scale.",
    "outcome": "reached"
  }'
Response 200
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Record the booked follow-up visit

POST/v1/transitions/episodes/{episode_id}/followuptransitions.write

The visit date and who it is with (422 followup_date_required, followup_before_discharge, followup_with_required); resolves an open "no follow-up" task. Within 7 days of discharge counts toward the follow-up measure.

Parameters

episode_idpath · stringrequired
tzquery · string | null

Request body

Content type: application/json (required)

datestringrequired

YYYY-MM-DD of the booked visit (not before discharge).

withstringrequired

Who the visit is with.

Errors specific to this call

422followup_date_required

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/episodes/$EPISODE_ID/followup" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "date": "2026-10-20",
    "with": "Dr. Rivera, Riverside FM"
  }'
Response 200
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Close the episode

POST/v1/transitions/episodes/{episode_id}/closetransitions.write

completed, readmitted (needs readmitted_on inside the 30 days) or withdrawn (needs a reason). 409 episode_closed when it already is.

Parameters

episode_idpath · stringrequired
tzquery · string | null

Request body

Content type: application/json (required)

outcomestringrequired
One of: completed readmitted withdrawn
reasonstring | null

Required for withdrawn.

readmitted_onstring | null

YYYY-MM-DD; required for readmitted (within 30 days).

Errors specific to this call

409episode_closed

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/episodes/$EPISODE_ID/close" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "outcome": "completed"
  }'
Response 200
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Record a readmission or ED return

POST/v1/transitions/episodes/{episode_id}/returnstransitions.write

A readmission (closes an active episode as readmitted) or an ED return, dated after discharge and within the 30 days (422 return_outside_window). Recorded with source staff, the same as a navigator's entry, and as a care event days-at-home reads.

Parameters

episode_idpath · stringrequired
tzquery · string | null

Request body

Content type: application/json (required)

kindstringrequired
One of: readmission ed_return
datestringrequired

YYYY-MM-DD, after discharge and within 30 days.

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/transitions/episodes/$EPISODE_ID/returns" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "date": "2026-10-18",
    "kind": "ed_return"
  }'
Response 200
{
  "episode_id": "pde_7c1e0b9a4d2f6e8a1b3c5d70",
  "member_ref": "mr_3f9a0c1d2e4b5a6978c0d1e2",
  "external_id": "string",
  "status": "active",
  "source": "manual",
  "condition": "heart_failure",
  "disposition": "home",
  "admit_date": "2026-10-09",
  "discharge_date": "2026-10-14",
  "discharge_at": "string",
  "day": 2,
  "window_days": 30,
  "readmitted_on": "string",
  "readmission_source": "string",
  "ed_return_on": "string",
  "ed_return_source": "string",
  "issues": [
    "contact_due"
  ],
  "due": [
    {
      "task": "contact_48_72h",
      "state": "due",
      "due_at": "2026-10-16T14:00:00Z",
      "overdue_at": "2026-10-17T14:00:00Z",
      "detail": {}
    }
  ],
  "risk": {
    "audience": "string",
    "band": "high",
    "lace": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "hospital": {
      "score": 11,
      "max": 19,
      "band": "higher",
      "points": {
        "A": 3,
        "C": 2,
        "E": 2,
        "L": 4
      },
      "citation": "string",
      "url": "string",
      "population": "string",
      "band_note": "string"
    },
    "not_scored": {
      "hospital": [
        "hemoglobin_g_dl",
        "sodium_mmol_l"
      ]
    },
    "note": "string"
  },
  "discharge_unit": "string",
  "discharge_service": "string",
  "pcp_name": "string",
  "closed_at": "string",
  "close_reason": "string",
  "med_reconciliation": {
    "staff_complete": false,
    "completed_at": "string",
    "count": 0,
    "unconfirmed_scan_rows": 0,
    "patient_answered": 0,
    "patient_pending": 0,
    "open_questions": 0
  },
  "checkins": [
    {
      "local_date": "2026-10-15",
      "answers": {
        "breathless": "worse",
        "chest_pain": "no",
        "orthopnea": "no",
        "swelling": "same"
      },
      "red_flags": [
        {}
      ],
      "weight_kg": 0.0
    }
  ],
  "meds": [
    {
      "name": "Furosemide",
      "dosage": "40 mg",
      "frequency": "daily",
      "change": "new",
      "entered_via": "string",
      "staff_confirmed": false,
      "patient_answer": "taking_it",
      "patient_note": "string",
      "answered_at": "string"
    }
  ],
  "tasks": [
    {
      "kin
  …

The response is the shape from the schema, not live data.

Operational post-discharge outcomes, small cells suppressed (not HRRP measures)

GET/v1/transitions/outcomestransitions.read

Counts for episodes discharged in the range: by condition, 30-day readmissions and ED returns known to Norvya (from your ADT feed or recorded by staff: no record does not mean no return), follow-up booked within 7 days, reached within 72 hours, check-in engagement, and days at home ONLY for episodes whose full 30 days fall inside an ascertainment period (no ascertainment, no number). Operational counts for your team, NOT risk-adjusted HRRP measures and not comparable to CMS's published rates. Small cells are withheld, with complementary suppression (the `suppression` field says how). Counts only, no ids.

Parameters

startquery · string | null

YYYY-MM-DD discharge dates from (default: 89 days before end).

endquery · string | null

YYYY-MM-DD (default today); at most 366 days after start.

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict413Request Entity Too Large415Unsupported Media Type422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/transitions/outcomes" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "generated_at": "string",
  "range": {
    "end": "2026-10-15",
    "start": "2026-07-18"
  },
  "label": "string",
  "risk_adjusted": false,
  "min_cell": 5,
  "suppression": "string",
  "episodes": {
    "count": 12,
    "suppressed": false
  },
  "by_condition": {},
  "window_complete": {
    "count": 12,
    "suppressed": false
  },
  "readmissions_30d": {
    "count": 12,
    "suppressed": false
  },
  "readmissions_by_source": {},
  "ed_returns_30d": {
    "count": 12,
    "suppressed": false
  },
  "ed_returns_by_source": {},
  "followup_within_7_days": {
    "count": 12,
    "suppressed": false
  },
  "contacted_within_72h": {
    "count": 12,
    "suppressed": false
  },
  "episodes_with_checkin": {
    "count": 12,
    "suppressed": false
  },
  "checkin_days": {
    "done": {
      "count": 12,
      "suppressed": false
    },
    "expected": {
      "count": 12,
      "suppressed": false
    }
  },
  "days_at_home": {
    "episodes_ascertained": {
      "count": 12,
      "suppressed": false
    },
    "episodes_without_ascertainment": {
      "count": 12,
      "suppressed": false
    },
    "mean_days_at_home": 0.0,
    "window_days": 0
  },
  "notes": [
    "string"
  ]
}

The response is the shape from the schema, not live data.

Hospital admissions, discharges and ED visits Norvya received for one patient

GET/v1/patients/{member_ref}/encounterstransitions.notices.read

Every notice your practice may see for this patient, newest first: from a hospital / HIE ADT feed (yours, or a hospital's through Norvya) or sent by the patient. A feed notice is visible while the patient shares their medical history with your practice, or under a practice-of-record relationship with a BAA on file; a notice the patient sent is always visible to the practices they sent it to (and gone once they withdraw it). A discharge carries its Transitional Care Management clock: contact by the 2nd business day, face-to-face by day 14 (moderate complexity) or 7 (high), the 30-day period. A notice is what was reported; no notice does not mean no hospital use. Treating practices and hospitals only (409 not_a_medical_practice).

Parameters

member_refpath · stringrequired
daysquery · integer

How far back (event date).

EMR vendors also pass vendor (the practice) with a vendor-issued token. EMR vendor tokens

Errors specific to this call

409not_a_medical_practice

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/patients/$MEMBER_REF/encounters" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "string",
  "external_id": "string",
  "days": 90,
  "posture": "string",
  "items": [
    {
      "notice_id": "oen_2b7d9f0a1c3e5b7d9f0a1c3e",
      "event": "discharge",
      "facility": "General Hospital",
      "start_date": "2026-10-14",
      "end_date": "string",
      "event_at": "string",
      "source": "adt_feed",
      "received_at": "string",
      "acknowledged": false,
      "tcm": {
        "discharge_date": "2026-10-14",
        "contact_by": "2026-10-16",
        "face_to_face_by": {
          "high_complexity": "2026-10-21",
          "moderate_complexity": "2026-10-28"
        },
        "period_end": "2026-11-12",
        "basis": "string"
      }
    }
  ]
}

The response is the shape from the schema, not live data.

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
patient.admittedtransitions.notices.readAn admission matched to one of the practice's patients and visible to it.
patient.dischargedtransitions.notices.readA discharge matched to one of the practice's patients and visible to it.
patient.ed_visittransitions.notices.readAn ED visit matched to one of the practice's patients and visible to it.
transition.episode_enrolledtransitions.readA post-discharge episode opened at the hospital (staff desk, Partner API or an ADT A03).
transition.red_flagtransitions.readA patient's check-in tripped a new red flag.

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

↑ ↓ to moveEnter to open