Hospital at home, days at home & wounds
For hospitals: open and close hospital-at-home episodes (the admission attestations are your clinician's, recorded as such), read contacts against your own protocol, escalations and the NEWS2 observation timeline, with a webhook on each escalation. A patient's observed days at home from recorded care events, only inside a recorded ascertainment period (no period, no number), and the wound log: each wound's location and assessment dates (never its measurements, which are image-based estimates, never the wound model's type, stage, severity, trajectory or tissue percentages, and never the photographs). Hospitals only.
- Who calls it
- Core for Hospitals and health systems; useful for Older adults & caregiving programmes
- Before production
- A BAA on file; days at home and wounds also follow the patient's sharing switches.
- Sandbox
- Build against synthetic members first. What each sandbox holds
- Standards
- NEWS2
Markets that use this family
- Hospitals and health systems (core)
- Older adults & caregiving programmes (useful)
Scopes
| Scope | Allows |
|---|---|
hospital.days_at_home.read | Read a patient's observed days at home from recorded care events, only inside a recorded ascertainment period (no period, no number) (hospitals only, with a BAA on file; the patient must share their medical history with you). |
hospital.wounds.read | Read a patient's wound log: each wound's location, whether it is a wound or a burn, and its assessment dates; never the measurements (image-based estimates) or the photographs (hospitals only, with a BAA on file; the patient must share their skin scans with you). |
hospital_at_home.read | Read your hospital-at-home episodes: contacts against your own protocol, escalations, and the NEWS2 observation timeline (hospitals only, with a BAA on file). |
hospital_at_home.write | Open and close hospital-at-home episodes for your patients; the admission attestations are your clinician's, recorded as such (hospitals only, with a BAA on file). |
Endpoints
Your hospital-at-home episodes
Episodes of patients still linked to your hospital, newest admission first, with contact counts (completed / missed / unrecorded: a contact with no completion and no missed reason is unrecorded, never missed) and today's completed contacts. Norvya determines no eligibility and does not grade a programme against its own schedule.
Parameters
active | ended | all
All responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s "https://norvya.fly.dev/v1/hospital-at-home/episodes" \
-H "Authorization: Bearer $TOKEN"import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
resp = requests.get(
BASE + "/v1/hospital-at-home/episodes",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const url = new URL(`${BASE}/v1/hospital-at-home/episodes`);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"total": 0,
"items": [
{
"episode_ref": "string",
"member_ref": "string",
"external_id": "string",
"status": "string",
"program_name": "string",
"admission_source": "string",
"admitted_on": "string",
"ended_on": "string",
"end_reason": "string",
"primary_problem_text": "string",
"attestations": {},
"protocol": {},
"escalation_plan_text": "string",
"contact_counts": {},
"completed_today": 0,
"in_person_today": 0
}
],
"reference_protocol": {},
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
Open a hospital-at-home episode
Opens the episode exactly as the staff screen does: admission from the emergency department or an inpatient bed only, all three attestations (your admitting clinician's, recorded as such; Norvya determines none of them) true, one open episode per patient (409 episode_already_open), not dated in the future. The patient must be actively linked to your hospital (404 member_not_found). Mirrored into days at home as zero days away.
EMR vendors also pass vendor (the practice) with a vendor-issued token. EMR vendor tokens
Request body
Content type: application/json (required)
emergency_department | inpatient_bed
Your admitting clinician attests inpatient-level care is necessary. All three attestations must be true.
Errors specific to this call
409episode_already_open404member_not_foundAll responses
201Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s -X POST "https://norvya.fly.dev/v1/hospital-at-home/episodes" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"member_ref": "string",
"admission_source": "string",
"admitted_on": "string",
"program_name": "string",
"primary_problem_text": "string",
"inpatient_level_attested": false,
"home_environment_assessed": false,
"patient_consented": false,
"protocol_in_person_visits_per_day": 0,
"protocol_clinician_eval_per_day": 0,
"escalation_plan_text": "string"
}'import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
resp = requests.post(
BASE + "/v1/hospital-at-home/episodes",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"member_ref": "string",
"admission_source": "string",
"admitted_on": "string",
"program_name": "string",
"primary_problem_text": "string",
"inpatient_level_attested": False,
"home_environment_assessed": False,
"patient_consented": False,
"protocol_in_person_visits_per_day": 0,
"protocol_clinician_eval_per_day": 0,
"escalation_plan_text": "string",
},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const url = new URL(`${BASE}/v1/hospital-at-home/episodes`);
const res = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"member_ref": "string",
"admission_source": "string",
"admitted_on": "string",
"program_name": "string",
"primary_problem_text": "string",
"inpatient_level_attested": false,
"home_environment_assessed": false,
"patient_consented": false,
"protocol_in_person_visits_per_day": 0,
"protocol_clinician_eval_per_day": 0,
"escalation_plan_text": "string"
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"episode_ref": "string",
"member_ref": "string",
"external_id": "string",
"status": "string",
"program_name": "string",
"admission_source": "string",
"admitted_on": "string",
"ended_on": "string",
"end_reason": "string",
"primary_problem_text": "string",
"attestations": {},
"protocol": {},
"escalation_plan_text": "string",
"contact_counts": {},
"completed_today": 0,
"in_person_today": 0,
"days": 0,
"contacts": [
{}
],
"daily": [
{}
],
"escalations": [
{}
],
"reference_protocol": {},
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
One hospital-at-home episode: contacts, daily rollup, escalations
The episode with every contact (scheduled / completed / missed / unrecorded), one row per day against the protocol your programme recorded (meets_protocol null when none was recorded), and the escalations with their response times. 404 episode_not_found for an episode that is not yours or whose patient's link is no longer live (one answer for both).
Parameters
Errors specific to this call
404episode_not_foundAll responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s "https://norvya.fly.dev/v1/hospital-at-home/episodes/$EPISODE_REF" \
-H "Authorization: Bearer $TOKEN"import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
episode_ref = os.environ["EPISODE_REF"]
resp = requests.get(
f"{BASE}/v1/hospital-at-home/episodes/{episode_ref}",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const episode_ref = process.env.EPISODE_REF;
const url = new URL(`${BASE}/v1/hospital-at-home/episodes/${encodeURIComponent(episode_ref)}`);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"episode_ref": "string",
"member_ref": "string",
"external_id": "string",
"status": "string",
"program_name": "string",
"admission_source": "string",
"admitted_on": "string",
"ended_on": "string",
"end_reason": "string",
"primary_problem_text": "string",
"attestations": {},
"protocol": {},
"escalation_plan_text": "string",
"contact_counts": {},
"completed_today": 0,
"in_person_today": 0,
"days": 0,
"contacts": [
{}
],
"daily": [
{}
],
"escalations": [
{}
],
"reference_protocol": {},
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
The episode's NEWS2 observation timeline
Every observation round, newest first (at most 50): the vital signs as recorded, the NEWS2 score and band, or why the round could not be scored (incomplete, stale, age or pregnancy exclusion: stored, never scored as zero); the latest round re-scored against now (a fresh round goes stale after max_age_minutes); the trend; and the alert level the care team was given. NEWS2 is a trigger for clinical review, not a diagnosis.
Parameters
All responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s "https://norvya.fly.dev/v1/hospital-at-home/episodes/$EPISODE_REF/news2" \
-H "Authorization: Bearer $TOKEN"import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
episode_ref = os.environ["EPISODE_REF"]
resp = requests.get(
f"{BASE}/v1/hospital-at-home/episodes/{episode_ref}/news2",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const episode_ref = process.env.EPISODE_REF;
const url = new URL(`${BASE}/v1/hospital-at-home/episodes/${encodeURIComponent(episode_ref)}/news2`);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"episode_ref": "string",
"member_ref": "string",
"eligibility": {},
"latest": {},
"trend": {},
"alert_level": "string",
"rounds": [
{}
],
"max_age_minutes": 0,
"required": [
"string"
],
"attribution": "string",
"attribution_url": "string",
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
Close a hospital-at-home episode
Ends the episode (409 episode_already_ended; 422 invalid_end_reason, date_in_future, end_before_start). died is mirrored into days at home as a death event, exactly as the staff screen does.
Parameters
Request body
Content type: application/json (required)
discharged_home | escalated_to_facility | died | withdrew | transferred
Errors specific to this call
409episode_already_ended422invalid_end_reasonAll responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s -X POST "https://norvya.fly.dev/v1/hospital-at-home/episodes/$EPISODE_REF/close" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"end_reason": "string",
"ended_on": "string"
}'import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
episode_ref = os.environ["EPISODE_REF"]
resp = requests.post(
f"{BASE}/v1/hospital-at-home/episodes/{episode_ref}/close",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"end_reason": "string",
"ended_on": "string",
},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const episode_ref = process.env.EPISODE_REF;
const url = new URL(`${BASE}/v1/hospital-at-home/episodes/${encodeURIComponent(episode_ref)}/close`);
const res = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"end_reason": "string",
"ended_on": "string"
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"episode_ref": "string",
"member_ref": "string",
"external_id": "string",
"status": "string",
"program_name": "string",
"admission_source": "string",
"admitted_on": "string",
"ended_on": "string",
"end_reason": "string",
"primary_problem_text": "string",
"attestations": {},
"protocol": {},
"escalation_plan_text": "string",
"contact_counts": {},
"completed_today": 0,
"in_person_today": 0,
"days": 0,
"contacts": [
{}
],
"daily": [
{}
],
"escalations": [
{}
],
"reference_protocol": {},
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
Observed days at home (no ascertainment, no number)
Days at home over the window ending today, from recorded care events, counted only over the days a recorded ascertainment period covers (partial coverage is never extrapolated). With no ascertainment period days_at_home is null with reason no_ascertainment_period: no recorded admission does not mean none happened. A same-day ED visit and a hospital-at-home episode are not days away. Never a projection. The patient must share their medical history with you (403 consent_not_granted).
Parameters
EMR vendors also pass vendor (the practice) with a vendor-issued token. EMR vendor tokens
Errors specific to this call
403consent_not_grantedAll responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s "https://norvya.fly.dev/v1/patients/$MEMBER_REF/days-at-home" \
-H "Authorization: Bearer $TOKEN"import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
member_ref = os.environ["MEMBER_REF"]
resp = requests.get(
f"{BASE}/v1/patients/{member_ref}/days-at-home",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const member_ref = process.env.MEMBER_REF;
const url = new URL(`${BASE}/v1/patients/${encodeURIComponent(member_ref)}/days-at-home`);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"member_ref": "string",
"external_id": "string",
"window": {},
"days_at_home": 0,
"reason": "string",
"observed": {},
"disclaimer": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
A patient's wound log: the record and its assessment dates
Each tracked wound (or burn): location, first and last assessment, the assessment count and the date of each assessment. No measurements: the wound tracker's measurements are image-based estimates, not a clinician's measurement, and are not shared with partners. The wound model's classification (wound type, stage, severity, healing trajectory, tissue percentages) is not returned. Photographs are not available through the API. The patient must share their skin scans with you (403 consent_not_granted).
Parameters
EMR vendors also pass vendor (the practice) with a vendor-issued token. EMR vendor tokens
Errors specific to this call
403consent_not_grantedAll responses
200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service UnavailableCodes every call can return are in Errors & limits.
curl -s "https://norvya.fly.dev/v1/patients/$MEMBER_REF/wounds" \
-H "Authorization: Bearer $TOKEN"import os
import requests
BASE = "https://norvya.fly.dev"
TOKEN = os.environ["TOKEN"]
member_ref = os.environ["MEMBER_REF"]
resp = requests.get(
f"{BASE}/v1/patients/{member_ref}/wounds",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
resp.raise_for_status()
print(resp.json())// Node.js 18+ (ES module). Keep production credentials on your server.
const BASE = "https://norvya.fly.dev";
const member_ref = process.env.MEMBER_REF;
const url = new URL(`${BASE}/v1/patients/${encodeURIComponent(member_ref)}/wounds`);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());{
"member_ref": "string",
"external_id": "string",
"count": 0,
"wounds": [
{
"wound_ref": "string",
"body_location": "string",
"case_type": "string",
"first_assessed": "string",
"last_assessed": "string",
"assessments": 0,
"series": [
{}
],
"images_available": false
}
],
"images_available": false,
"note": "string"
}The response is the shape from the schema, not live data.
Try it in your sandbox
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
| Event | Scope | When |
|---|---|---|
hospital_at_home.escalation | hospital_at_home.read | An observation round on a hospital-at-home episode scored at or above NEWS2's urgent-response threshold. |
Generated from the Partner API router and developers_catalog.py. The router docstring is the source of each description.