Norvya Developers
Get a sandbox
API reference · Population & programmes

Public-health reporting

Built — gated21 endpoints · 2 webhook events · OpenAPI tag public_health

Report from your own system to the state, one explicit call at a time. Immunization registry: readiness of your connection, the patient's record with a reference per dose, a preview of what the HL7 v2 VXU would contain, the submission itself with the registry's acknowledgement and retry state, and history queries (Z34 / Z44) whose returned doses land on the record. Electronic case reporting: match a patient against the CSTE / CDC / APHL trigger codes (a match is never a statement that a case is reportable), confirm or dismiss, build the FHIR eICR, transmit it, and read or file the Reportability Response. Syndromic surveillance (NSSP): record an emergency or urgent-care visit with its chief complaint and send its HL7 v2 ADT message. Webhooks for registry acknowledgements and Reportability Responses. Treating practices and hospitals only; every transmission is audited before it leaves.

Who calls it
Core for State & local government; useful for Independent practices, Hospitals and health systems
Before production
A signed data-exchange agreement with each jurisdiction (immunization registry, eCR on the AIMS platform, NSSP onboarding), and the feature switched on for your organisation. Until then each call answers a not-active code. A sandbox simulates every transmission and never reaches a state.
Sandbox
Build against synthetic members first. What each sandbox holds
Standards
HL7 v2 VXU and ADT; FHIR eICR; CSTE / CDC / APHL trigger codes

Markets that use this family

Scopes

ScopeAllows
public_health.case_reports.readRead electronic case reporting readiness, candidates, reports and the Reportability Responses public health sent back (treating practices and hospitals).
public_health.case_reports.writeElectronic case reporting: match a patient against the loaded trigger codes, confirm or dismiss a candidate, build the eICR, transmit it, and file a Reportability Response (treating practices and hospitals; refused unless case reporting is active for you).
public_health.immunizations.readRead your registry connection's readiness, the patient's immunization record, your submissions and their acknowledgements, and query the registry for a patient's history (treating practices and hospitals; the patient must share their medical history with you).
public_health.immunizations.writeReport a patient's immunization to your state immunization registry (HL7 v2 VXU) and preview what would be sent; an explicit act, audited, refused unless your registry connection is active under a signed state agreement (treating practices and hospitals).
public_health.syndromic.readRead your syndromic surveillance readiness and what was sent where (no patient data in the message list).
public_health.syndromic.writeSyndromic surveillance (NSSP): record an emergency or urgent-care visit and send its HL7 v2 ADT message, one explicit send at a time (registered reporting facilities only).

Endpoints

Your immunization registry connection: readiness, never credentials

GET/v1/public-health/iispublic_health.immunizations.read

Whether a dose report or history query would be transmitted right now, and if not, why: the connection's status, the state, whether an administrator attested to the state's data-exchange agreement, and the onboarding steps still missing. Never the endpoint, the user name, the password or the facility id. Activation itself is done by your organisation's administrator in Norvya, not through the API.

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/public-health/iis" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "configured": false,
  "active": false,
  "status": "active",
  "jurisdiction": "MN",
  "registry": "Minnesota Immunization Information Connection (MIIC)",
  "agreement_attested": false,
  "agreement_attested_at": "string",
  "onboarding": [
    {
      "step": "agreement_signed",
      "status": "complete",
      "mandatory": false
    }
  ],
  "missing": [
    "string"
  ],
  "attention": {},
  "query_profiles": {},
  "retry_policy": {},
  "standard": "string",
  "simulated": false,
  "posture": "string"
}

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

Your registry submissions and their acknowledgements

GET/v1/public-health/iis/submissionspublic_health.immunizations.read

Newest first: dose reports (VXU) and history queries (QBP) your organisation sent — through the API or from Norvya's own screens — with the registry's ACK code, Norvya's retry state (5 min, 30 min, 2 h, 12 h, 24 h; then failed_permanent) and the review queue (needs_review: a data problem the registry reported, never retried automatically). Patients no longer linked to you are left out.

Parameters

statusquery · string | null

Filter by status, e.g. needs_review.

message_typequery · string | null

VXU | QBP

limitquery · 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/public-health/iis/submissions" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "items": [
    {
      "submission_ref": "iis_9a2b4c6d8e0f1a3b5c7d9e1f",
      "message_type": "VXU",
      "query_profile": null,
      "member_ref": "string",
      "immunization_ref": "string",
      "status": "accepted",
      "accepted": false,
      "ack_code": "AA",
      "error_code": null,
      "registry_error_code": "string",
      "attempt_count": 0,
      "max_attempts": 0,
      "next_attempt_at": "string",
      "created_at": "string",
      "sent_at": "string",
      "simulated": false
    }
  ],
  "posture": "string"
}

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

One registry submission

GET/v1/public-health/iis/submissions/{submission_ref}public_health.immunizations.read

Status, ACK code and retry state of one submission. Another organisation's submission and an unknown ref are the same 404 iis_submission_not_found.

Parameters

submission_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/public-health/iis/submissions/$SUBMISSION_REF" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "submission_ref": "iis_9a2b4c6d8e0f1a3b5c7d9e1f",
  "message_type": "VXU",
  "query_profile": null,
  "member_ref": "string",
  "immunization_ref": "string",
  "status": "accepted",
  "accepted": false,
  "ack_code": "AA",
  "error_code": null,
  "registry_error_code": "string",
  "attempt_count": 0,
  "max_attempts": 0,
  "next_attempt_at": "string",
  "created_at": "string",
  "sent_at": "string",
  "simulated": false
}

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

A patient's immunization record (with refs to report)

GET/v1/patients/{member_ref}/immunizationspublic_health.immunizations.read

Completed doses on the patient's Norvya record, newest first, each with the immunization_ref you report it by, plus Norvya's adult forecast. The patient must share their medical history with your organisation (403 medical_history_not_shared).

Parameters

member_refpath · stringrequired

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

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/immunizations" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "string",
  "items": [
    {
      "immunization_ref": "imz_3f9c1a0b7d2e4c6a8b1d0e2f",
      "vaccine_key": "tdap",
      "group": "tdap_td",
      "cvx": "115",
      "display": "Tdap (tetanus, diphtheria, whooping cough)",
      "occurrence_date": "2026-09-30",
      "dose_number": 0,
      "lot_number": "string",
      "source": "clinic",
      "verification": "staff_recorded"
    }
  ],
  "forecast": {}
}

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

What a registry report of one dose would contain

GET/v1/patients/{member_ref}/immunizations/{immunization_ref}/iis-previewpublic_health.immunizations.write

Builds the HL7 v2.5.1 VXU^V04 with the same builder a submission uses (your state's published local rules applied) and returns a summary: the segments, the vaccine, whether it reports a new administration (00) or a historical dose (01), and whether the VFC eligibility observation is included. Not the HL7 text. A dose the builder cannot report truthfully is refused with its reason (422 iis_uncoded_dose, iis_patient_incomplete, iis_vfc_eligibility_unknown ...). Needs a configured connection (409 iis_not_configured); nothing is sent.

Parameters

member_refpath · stringrequired
immunization_refpath · stringrequired

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

Errors specific to this call

422iis_uncoded_dose

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/immunizations/$IMMUNIZATION_REF/iis-preview" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "string",
  "immunization_ref": "string",
  "message_type": "VXU^V04",
  "profile": "Z22",
  "segments": [
    "MSH",
    "PID",
    "ORC",
    "RXA",
    "OBX"
  ],
  "vaccine": {},
  "information_source": "00",
  "vfc_eligibility_included": false,
  "jurisdiction": "string",
  "would_transmit": false,
  "simulated": false,
  "standard": "string",
  "note": "string"
}

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

Report one dose to your state immunization registry

POST/v1/patients/{member_ref}/immunizations/{immunization_ref}/iis-submissionspublic_health.immunizations.write

An explicit act: builds the VXU and sends it over the CDC IIS web service to your registry, reads the ACK and answers with the submission. A transport failure or an application reject (AR / CR) is retried on the backoff ladder; an application error (AE / CE) or a dose Norvya cannot report truthfully waits in needs_review for your staff. Refused unless the connection is active under an attested state agreement (409 iis_not_active, nothing recorded). The disclosure is audited before it leaves and refused when the audit log is down. Subscribe to public_health.iis_ack_received for ACKs that arrive on a retry.

Parameters

member_refpath · stringrequired
immunization_refpath · stringrequired

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

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/patients/$MEMBER_REF/immunizations/$IMMUNIZATION_REF/iis-submissions" \
  -H "Authorization: Bearer $TOKEN"
Response 201
{
  "submission_ref": "iis_9a2b4c6d8e0f1a3b5c7d9e1f",
  "message_type": "VXU",
  "query_profile": null,
  "member_ref": "string",
  "immunization_ref": "string",
  "status": "accepted",
  "accepted": false,
  "ack_code": "AA",
  "error_code": null,
  "registry_error_code": "string",
  "attempt_count": 0,
  "max_attempts": 0,
  "next_attempt_at": "string",
  "created_at": "string",
  "sent_at": "string",
  "simulated": false
}

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

Ask your registry for a patient's immunization history

POST/v1/patients/{member_ref}/iis-queriespublic_health.immunizations.read

QBP^Q11 (Z34 history, or Z44 evaluated history and forecast) for one patient. Doses the registry returns are added to the patient's record (source iis, document reviewed; duplicates skipped) and the record comes back with Norvya's adult forecast. A candidate list, no match or a protected record is reported in query_status and nothing is imported. The query sends the patient's identity to the state, so it is audited as a disclosure first (fail closed), and the answer as a read. Needs an active connection (409 iis_not_active). A registry outage is retried in the background and reported here as 502 iis_unreachable.

Parameters

member_refpath · stringrequired

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

Request body

Content type: application/json

Errors specific to this call

409iis_not_active502iis_unreachable

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/patients/$MEMBER_REF/iis-queries" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "profile": "Z44"
  }'
Response 200
{
  "member_ref": "string",
  "submission": {
    "submission_ref": "iis_9a2b4c6d8e0f1a3b5c7d9e1f",
    "message_type": "VXU",
    "query_profile": null,
    "member_ref": "string",
    "immunization_ref": "string",
    "status": "accepted",
    "accepted": false,
    "ack_code": "AA",
    "error_code": null,
    "registry_error_code": "string",
    "attempt_count": 0,
    "max_attempts": 0,
    "next_attempt_at": "string",
    "created_at": "string",
    "sent_at": "string",
    "simulated": false
  },
  "query_status": "OK",
  "patients_returned": 0,
  "imported": {},
  "history": [
    {
      "immunization_ref": "imz_3f9c1a0b7d2e4c6a8b1d0e2f",
      "vaccine_key": "tdap",
      "group": "tdap_td",
      "cvx": "115",
      "display": "Tdap (tetanus, diphtheria, whooping cough)",
      "occurrence_date": "2026-09-30",
      "dose_number": 0,
      "lot_number": "string",
      "source": "clinic",
      "verification": "staff_recorded"
    }
  ],
  "forecast": {},
  "registry_forecast": {},
  "simulated": false
}

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

Electronic case reporting readiness

GET/v1/public-health/case-reportingpublic_health.case_reports.read

Whether case reporting is active for your organisation and, if not, what is missing; the trigger-code release Norvya matches against (the CSTE / CDC / APHL eRSD; Norvya ships no condition list of its own); what trigger matching can and cannot see; and what is not claimed.

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/public-health/case-reporting" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "active": false,
  "missing": [
    "case_reporting_not_enabled"
  ],
  "jurisdiction": "string",
  "adapter": "direct",
  "ersd": {},
  "respect_sharing_flags": false,
  "coverage": {},
  "reportability_determined_by": "string",
  "not_claimed": [
    "string"
  ],
  "ig_version": "string",
  "simulated": false,
  "posture": "string"
}

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

Match a patient's record against the reportable-condition trigger codes

POST/v1/patients/{member_ref}/case-reports/evaluatepublic_health.case_reports.write

Matches the patient's coded conditions, labs and immunizations against the active eRSD release and raises a candidate per matched condition (already-known ones come back too). A match is NOT a statement that the case is reportable: only the Reportability Response decides. An empty list is not a statement that there is nothing to report (see coverage). 409 case_reporting_not_active; 409 no_ersd_release.

Parameters

member_refpath · stringrequired

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

Errors specific to this call

409no_ersd_release

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/patients/$MEMBER_REF/case-reports/evaluate" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "string",
  "candidates": [
    {
      "candidate_ref": "ecc_1b3d5f7a9c0e2a4c6e8a0b2d",
      "member_ref": "string",
      "status": "candidate",
      "trigger": {},
      "condition": {},
      "source": {},
      "sharing_blocked": false,
      "override_recorded": false,
      "detected_at": "string",
      "reviewed_at": "string",
      "reportability": "string"
    }
  ],
  "coverage": {}
}

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

Case-report candidates waiting for review, and their history

GET/v1/public-health/case-reports/candidatespublic_health.case_reports.read

Parameters

statusquery · string | null

candidate | confirmed | dismissed | sent | failed

limitquery · 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/public-health/case-reports/candidates" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "items": [
    {
      "candidate_ref": "ecc_1b3d5f7a9c0e2a4c6e8a0b2d",
      "member_ref": "string",
      "status": "candidate",
      "trigger": {},
      "condition": {},
      "source": {},
      "sharing_blocked": false,
      "override_recorded": false,
      "detected_at": "string",
      "reviewed_at": "string",
      "reportability": "string"
    }
  ]
}

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

Confirm or dismiss a case-report candidate

POST/v1/public-health/case-reports/candidates/{candidate_ref}/reviewpublic_health.case_reports.write

Your clinician's decision, recorded from your system. A candidate whose trigger data the patient keeps closed (sharing_blocked) cannot be confirmed here: overriding a patient's sharing choice needs a clinician's recorded reason inside Norvya (409 override_requires_clinician). A sent candidate cannot be changed (409 already_sent).

Parameters

candidate_refpath · stringrequired

Request body

Content type: application/json (required)

actionstringrequired

confirm | dismiss

notestring | null

Errors specific to this call

409override_requires_clinician409already_sent

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/public-health/case-reports/candidates/$CANDIDATE_REF/review" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "confirm",
    "note": "string"
  }'
Response 200
{
  "candidate_ref": "ecc_1b3d5f7a9c0e2a4c6e8a0b2d",
  "member_ref": "string",
  "status": "candidate",
  "trigger": {},
  "condition": {},
  "source": {},
  "sharing_blocked": false,
  "override_recorded": false,
  "detected_at": "string",
  "reviewed_at": "string",
  "reportability": "string"
}

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

Build the eICR for a confirmed candidate

POST/v1/public-health/case-reports/candidates/{candidate_ref}/buildpublic_health.case_reports.write

Builds the FHIR eICR (hl7.fhir.us.ecr 2.1.2) from the patient's record through Norvya's one FHIR builder and stores it encrypted, ready to transmit. 42 CFR Part 2 records are always withheld; clinical detail behind a closed sharing flag is withheld unless a clinician recorded an override. The document itself is not returned. Audited as a disclosure (fail closed). 409 candidate_not_confirmed.

Parameters

candidate_refpath · stringrequired

Errors specific to this call

409candidate_not_confirmed

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/public-health/case-reports/candidates/$CANDIDATE_REF/build" \
  -H "Authorization: Bearer $TOKEN"
Response 201
{
  "report": {
    "report_ref": "ecr_7c9e1a3b5d7f9a1c3e5a7b9d",
    "candidate_ref": "string",
    "member_ref": "string",
    "format": "fhir_eicr",
    "set_id": "string",
    "version": 0,
    "status": "sent",
    "transmitted_at": "string",
    "part2_withheld": 0,
    "error_code": "string",
    "created_at": "string",
    "reportability_response": {},
    "rr_received_at": "string",
    "simulated": false
  },
  "build": {}
}

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

Your eICRs and the Reportability Responses that came back

GET/v1/public-health/case-reportspublic_health.case_reports.read

Parameters

limitquery · 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/public-health/case-reports" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "items": [
    {
      "report_ref": "ecr_7c9e1a3b5d7f9a1c3e5a7b9d",
      "candidate_ref": "string",
      "member_ref": "string",
      "format": "fhir_eicr",
      "set_id": "string",
      "version": 0,
      "status": "sent",
      "transmitted_at": "string",
      "part2_withheld": 0,
      "error_code": "string",
      "created_at": "string",
      "reportability_response": {},
      "rr_received_at": "string",
      "simulated": false
    }
  ]
}

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

One eICR and its Reportability Response

GET/v1/public-health/case-reports/{report_ref}public_health.case_reports.read

Parameters

report_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/public-health/case-reports/$REPORT_REF" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "report_ref": "ecr_7c9e1a3b5d7f9a1c3e5a7b9d",
  "candidate_ref": "string",
  "member_ref": "string",
  "format": "fhir_eicr",
  "set_id": "string",
  "version": 0,
  "status": "sent",
  "transmitted_at": "string",
  "part2_withheld": 0,
  "error_code": "string",
  "created_at": "string",
  "reportability_response": {},
  "rr_received_at": "string",
  "simulated": false
}

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

Transmit a built eICR to public health

POST/v1/public-health/case-reports/{report_ref}/transmitpublic_health.case_reports.write

Hands the stored eICR to your organisation's configured adapter (Direct to the AIMS platform, or a drop directory your bridge collects). An explicit act, audited before it leaves and refused when the audit log is down. 409 already_sent; 409 document_not_stored; a failed hand-off marks the report failed and answers 503 with the adapter's code.

Parameters

report_refpath · stringrequired

Errors specific to this call

409already_sent409document_not_stored503with

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/public-health/case-reports/$REPORT_REF/transmit" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "report_ref": "ecr_7c9e1a3b5d7f9a1c3e5a7b9d",
  "candidate_ref": "string",
  "member_ref": "string",
  "format": "fhir_eicr",
  "set_id": "string",
  "version": 0,
  "status": "sent",
  "transmitted_at": "string",
  "part2_withheld": 0,
  "error_code": "string",
  "created_at": "string",
  "reportability_response": {},
  "rr_received_at": "string",
  "simulated": false
}

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

File the Reportability Response public health sent

POST/v1/public-health/case-reports/{report_ref}/responsepublic_health.case_reports.write

For organisations whose own system receives the RR. A FHIR RR is read for its determinations; a CDA RR is stored and marked not parsed. 413 file_too_large; 415 unsupported_media_type; 422 unreadable_response.

Parameters

report_refpath · stringrequired

Request body

The Reportability Response document as public health sent it: a FHIR Bundle (JSON) or a CDA document (XML, stored but not parsed). At most 20 MB.

Content type: application/fhir+json, application/json, application/xml, text/xml, application/hl7-cda+xml (required)

Errors specific to this call

415unsupported_media_type422unreadable_response

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/public-health/case-reports/$REPORT_REF/response" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/fhir+json" \
  --data-binary @your_body_file
Response 200
{
  "report_ref": "ecr_7c9e1a3b5d7f9a1c3e5a7b9d",
  "candidate_ref": "string",
  "member_ref": "string",
  "format": "fhir_eicr",
  "set_id": "string",
  "version": 0,
  "status": "sent",
  "transmitted_at": "string",
  "part2_withheld": 0,
  "error_code": "string",
  "created_at": "string",
  "reportability_response": {},
  "rr_received_at": "string",
  "simulated": false
}

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

Syndromic surveillance readiness

GET/v1/public-health/syndromic/statuspublic_health.syndromic.read

What is configured and what is missing before your organisation can send: the facility registration and its NSSP onboarding attestation, the jurisdiction, the syndromic endpoint. Built against the PHIN Messaging Guide R1.1 + 2012 addendum and not NIST-validated (see not_claimed).

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/public-health/syndromic/status" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "ready": false,
  "missing": [
    "facility_not_registered"
  ],
  "facility": {},
  "jurisdiction": "string",
  "messages_sent": 0,
  "triggers": [
    "string"
  ],
  "settings": [
    "string"
  ],
  "profile_built_against": "string",
  "source": {},
  "not_claimed": [
    "string"
  ],
  "simulated": false,
  "posture": "string"
}

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

Record an emergency or urgent-care visit

POST/v1/public-health/syndromic/visitspublic_health.syndromic.write

The encounter as your facility records it, keyed on your visit number (recording the same number again updates it). Chief complaint in the patient's own words: Norvya never derives one, and a visit without it is never sent. Nothing is sent by recording. 409 syndromic_not_onboarded; 409 visit_number_in_use (that number belongs to another patient).

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

Request body

Content type: application/json (required)

member_refstringrequired
visit_numberstringrequired
arrived_atstringrequired

ISO 8601 date-time, UTC.

patient_classstringrequired

E emergency | I inpatient | O outpatient

chief_complaintstring | null

In the patient's own words; a visit without one is never sent.

dispositionstring | null
discharged_atstring | null
age_yearsinteger | null
diagnosesarray of object | null

Errors specific to this call

409syndromic_not_onboarded409visit_number_in_use

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/public-health/syndromic/visits" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "member_ref": "string",
    "visit_number": "ED-2026-000123",
    "arrived_at": "2026-10-15T14:05:00Z",
    "patient_class": "E",
    "chief_complaint": "cough and fever 3 days",
    "disposition": "string",
    "discharged_at": "string",
    "age_years": 0,
    "diagnoses": [
      {
        "code": "J06.9",
        "system": "I10",
        "text": "string"
      }
    ]
  }'
Response 201
{
  "visit_ref": "ssv_2c4e6a8b0d2f4a6c8e0a2b4d",
  "member_ref": "string",
  "visit_number": "string",
  "arrived_at": "string",
  "discharged_at": "string",
  "patient_class": "string",
  "chief_complaint_recorded": false,
  "disposition": "string",
  "age_years": 0,
  "diagnoses": [
    {}
  ],
  "reportable": false,
  "not_reportable_reason": "string"
}

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

Visits on file

GET/v1/public-health/syndromic/visitspublic_health.syndromic.read

Parameters

limitquery · 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/public-health/syndromic/visits" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "items": [
    {
      "visit_ref": "ssv_2c4e6a8b0d2f4a6c8e0a2b4d",
      "member_ref": "string",
      "visit_number": "string",
      "arrived_at": "string",
      "discharged_at": "string",
      "patient_class": "string",
      "chief_complaint_recorded": false,
      "disposition": "string",
      "age_years": 0,
      "diagnoses": [
        {}
      ],
      "reportable": false,
      "not_reportable_reason": "string"
    }
  ]
}

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

Send one visit's syndromic ADT message

POST/v1/public-health/syndromic/visits/{visit_ref}/sendpublic_health.syndromic.write

Builds the HL7 v2.5.1 ADT (A01 / A03 / A04 / A08) and hands it to your endpoint's adapter — one explicit send; Norvya never transmits on its own. The same content for the same visit and trigger is refused (409 duplicate_message: double counting inflates a surveillance signal); 409 chief_complaint_missing. Audited before it leaves, refused when the audit log is down.

Parameters

visit_refpath · stringrequired

Request body

Content type: application/json (required)

triggerstringrequired

A01 | A03 | A04 | A08

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/public-health/syndromic/visits/$VISIT_REF/send" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "A04"
  }'
Response 200
{
  "message_ref": "ssm_5e7a9c1b3d5f7a9c1e3a5b7d",
  "visit_ref": "string",
  "trigger": "string",
  "control_id": "string",
  "jurisdiction": "string",
  "status": "string",
  "sent_at": "string",
  "warnings": [
    "string"
  ],
  "simulated": false
}

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

What was sent where (no patient data)

GET/v1/public-health/syndromic/messagespublic_health.syndromic.read

Each message: trigger, control id, jurisdiction, status, time, any warnings (age_not_recorded, disposition_not_recorded). No patient reference beyond the visit_ref you already hold.

Parameters

limitquery · 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/public-health/syndromic/messages" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "items": [
    {
      "message_ref": "ssm_5e7a9c1b3d5f7a9c1e3a5b7d",
      "visit_ref": "string",
      "trigger": "string",
      "control_id": "string",
      "jurisdiction": "string",
      "status": "string",
      "sent_at": "string",
      "warnings": [
        "string"
      ],
      "simulated": false
    }
  ]
}

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
public_health.case_report_responsepublic_health.case_reports.readA Reportability Response was filed for one of the practice's eICRs.
public_health.iis_ack_receivedpublic_health.immunizations.readA state immunization registry acknowledged a dose report of the practice.

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

↑ ↓ to moveEnter to open