Norvya Developers
Get a sandbox
API reference · Data in

Data in

Built — gated4 endpoints · 2 webhook events · OpenAPI tag data_in

Send your panel (a FHIR Bulk Data export, or a spreadsheet with a saved column mapping). You get a dry run first; patients are created only after commit, under a practice-of-record basis with a BAA on file.

Who calls it
Core for Concierge doctors, Independent practices, EMR vendors, Federal (via primes), State & local government, Hospitals and health systems; useful for Insurers (incl. Medicaid managed care), Practice management & billing, Specialty care
Before production
No gate of its own; your market's “Before production” applies.
Sandbox
Build against synthetic members first. What each sandbox holds
Standards
FHIR Bulk Data (panel import)

Markets that use this family

Scopes

ScopeAllows
panel.import.writeStage, review, commit and discard practice panel imports (FHIR Bulk Data, or a spreadsheet with a saved mapping profile; medical practices with a BAA on file only).

Endpoints

Stage a panel import and get its dry run

POST/v1/panel/importspanel.import.write

Parses and stages the file (held encrypted; nothing reaches a live table) and returns the dry run. Identity is the MRN only — never a name or birth date match. A spreadsheet is accepted ONLY when every sheet matches a mapping profile saved by your practice's admin in Norvya (no interactive mapping over the API): 422 panel_import_mapping_profile_required otherwise. Medical practice with a BAA on file only (409 not_a_medical_practice / panel_import_baa_required).

Request body

Content type: multipart/form-data (required)

filesarray of filerequired

A FHIR Bulk Data export (one or more .ndjson files, or a .zip of them), a FHIR Bundle (.json), or a spreadsheet (.xlsx / .csv) your practice has a saved mapping profile for.

identifier_systemstring | null

FHIR: the Patient identifier system that holds your MRN (default: the identifier typed MR).

Errors specific to this call

422panel_import_mapping_profile_required409not_a_medical_practice

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/panel/imports" \
  -H "Authorization: Bearer $TOKEN" \
  -F files=@your_file \
  -F identifier_system="$IDENTIFIER_SYSTEM"
Response 201
{
  "id": 0,
  "status": "string",
  "file_format": "string",
  "filename": "string",
  "file_sha256": "string",
  "file_bytes": 0,
  "created_at": "string",
  "committed_at": "string",
  "discarded_at": "string",
  "error_code": "string",
  "patients_in_file": 0,
  "records": 0,
  "rejected": 0,
  "progress": {},
  "can_commit": false,
  "blocking": [
    "string"
  ],
  "summary": {},
  "result": {},
  "data_quality": {},
  "changes": {}
}

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

One panel import: dry run, progress, result

GET/v1/panel/imports/{import_id}panel.import.write

Imports made through the API by your practice only (404 panel_import_not_found otherwise).

Parameters

import_idpath · integerrequired

Errors specific to this call

404panel_import_not_found

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/panel/imports/$IMPORT_ID" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "id": 0,
  "status": "string",
  "file_format": "string",
  "filename": "string",
  "file_sha256": "string",
  "file_bytes": 0,
  "created_at": "string",
  "committed_at": "string",
  "discarded_at": "string",
  "error_code": "string",
  "patients_in_file": 0,
  "records": 0,
  "rejected": 0,
  "progress": {},
  "can_commit": false,
  "blocking": [
    "string"
  ],
  "summary": {},
  "result": {},
  "data_quality": {},
  "changes": {}
}

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

Commit a staged import

POST/v1/panel/imports/{import_id}/commitpanel.import.write

Writes the import in the background (poll GET, or subscribe to import.completed / import.failed). New MRNs become managed, login-disabled patient records under the practice-of-record basis. Refused (409) with the dry run's first blocking code (e.g. panel_import_date_format_unconfirmed, panel_import_nothing_to_import), panel_import_baa_required when no BAA is on file NOW, panel_import_not_staged, panel_import_commit_in_progress. The BAA is checked again by the worker before the first write.

Parameters

import_idpath · integerrequired

Request body

Content type: application/json

All responses

202Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s -X POST "https://norvya.fly.dev/v1/panel/imports/$IMPORT_ID/commit" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "run_worklist": false,
    "create_possible_duplicates": false
  }'
Response 202
{
  "id": 0,
  "status": "string",
  "file_format": "string",
  "filename": "string",
  "file_sha256": "string",
  "file_bytes": 0,
  "created_at": "string",
  "committed_at": "string",
  "discarded_at": "string",
  "error_code": "string",
  "patients_in_file": 0,
  "records": 0,
  "rejected": 0,
  "progress": {},
  "can_commit": false,
  "blocking": [
    "string"
  ],
  "summary": {},
  "result": {},
  "data_quality": {},
  "changes": {}
}

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

Discard a staged import

POST/v1/panel/imports/{import_id}/discardpanel.import.write

Deletes the held file; the manifest (counts, reasons, hash) stays.

Parameters

import_idpath · integerrequired

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/panel/imports/$IMPORT_ID/discard" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "id": 0,
  "status": "string",
  "file_format": "string",
  "filename": "string",
  "file_sha256": "string",
  "file_bytes": 0,
  "created_at": "string",
  "committed_at": "string",
  "discarded_at": "string",
  "error_code": "string",
  "patients_in_file": 0,
  "records": 0,
  "rejected": 0,
  "progress": {},
  "can_commit": false,
  "blocking": [
    "string"
  ],
  "summary": {},
  "result": {},
  "data_quality": {},
  "changes": {}
}

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
import.completedpanel.import.writeA panel import made through the API committed.
import.failedpanel.import.writeA panel import made through the API failed.

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

↑ ↓ to moveEnter to open