Norvya Developers
Get a sandbox
API reference · Data in

Claims in

Built — gated7 endpoints · 1 webhook event · OpenAPI tag claims

Attach claims you already hold to your members: CMS CCLF files (Parts A, B and D) or a plan's claims in the documented generic shape. A dry run first (counts, match rate, rejections by code and row number, never a value), then an asynchronous commit and a claims.import_completed webhook. Claims match on your member reference, the member's MBI or plan member id (fingerprinted in memory, never stored), never on name or birth date; unmatched claims are dropped. Per member: a claims summary (settings, diagnoses, prescription fills) alongside what the member connected through Blue Button, and the member's record connections. Risk scores are refused unless an official CMS-HCC model is loaded. Claims never rewrite the member's own condition or medication list. Risk-adjustment audit evidence per member: the diagnosis codes in your imported claims with the dated claims documenting each, grouped into CMS-HCC categories only when an official model is loaded, never a risk score.

Who calls it
Core for Federal (via primes), State & local government, Insurers (incl. Medicaid managed care); useful for Independent practices
Before production
A BAA on file (claims_baa_required otherwise), and an organisation that may hold covered lives.
Sandbox
Build against synthetic members first. What each sandbox holds
Standards
CMS CCLF (Parts A, B, D); CMS-HCC only when an official model is loaded

Markets that use this family

Scopes

ScopeAllows
claims.import.writeSend claims files (CMS CCLF Part A / B / D, or your plan's claims as CSV / NDJSON in the documented shape): staged with a dry run (match rate, row errors by code), then committed or discarded. MBIs and plan member ids are fingerprinted and never stored (treating practices and programme organisations with a BAA on file).
claims.readRead a member's claims summary (counts by part and setting, dates, top diagnosis categories, CMS-HCC categories only when an official model is loaded) from your imported claims and, when the member shares their medical history with you, their own Medicare Blue Button summary; and whether they connected Blue Button or VA records (read-only).
claims.risk_adjustment.readRead risk-adjustment audit evidence for a member: the diagnosis codes in the claims you imported with the dated claims documenting each, grouped into CMS-HCC categories only when an official model is loaded; never a risk score (treating practices and programme organisations with a BAA on file).

Endpoints

Stage a claims import (CCLF or plan claims) and get its dry run

POST/v1/claims/importsclaims.import.write

Parses the file(s) in the request, matches each claim to exactly one of your active members (member_ref, or the MBI / plan member id against the coverage recorded for the member, by fingerprint; never by name or birth date) and stages the matched claims. Nothing is attached until commit. MBIs, plan member ids and claim numbers are never stored. Treating practices and programme organisations with a BAA on file (409 not_a_medical_practice / claims_baa_required).

Request body

One claims file as the body (text/csv or text/plain for a pipe / comma / tab delimited CCLF or plan CSV, application/x-ndjson for plan NDJSON; ?filename= names it), or multipart/form-data with one or more `files` parts (e.g. CCLF1 + CCLF4 together). Generic plan shape: claim_id, member_ref | member_id | mbi, service_from, service_thru, dx_codes, procedure_codes, ndc_codes, place_of_service, part, setting, claim_type_code, paid_amount. At most 50 MB.

Content type: text/csv, text/plain, application/x-ndjson, multipart/form-data (required)

filesarray of filerequired

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/claims/imports" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: text/csv" \
  --data-binary @your_body_file
Response 201
{
  "claims_import_ref": "cli_8a1f0c3e5b7d9a2c4e6f8b0d",
  "status": "staged",
  "file_kinds": [
    "cclf1",
    "cclf4"
  ],
  "file_sha256": "string",
  "file_bytes": 0,
  "dry_run": {
    "files": [
      {
        "filename": "CCLF1.psv",
        "kind": "cclf1"
      }
    ],
    "rows_read": 0,
    "claims_parsed": 0,
    "claims_matched": 0,
    "claims_unmatched": 0,
    "claims_ambiguous": 0,
    "members_matched": 0,
    "match_rate": 0.92,
    "match_basis": {
      "mbi": 120
    },
    "diagnosis_rows_attached": 0,
    "by_part": {
      "A": 12,
      "B": 98,
      "D": 10
    },
    "by_setting": {},
    "service_from_min": "string",
    "service_thru_max": "string",
    "rejected": 0,
    "rejections_by_code": {},
    "rejections": [
      {
        "file": "CCLF5.psv",
        "row": 17,
        "code": "malformed_mbi"
      }
    ],
    "unmatched_rows": [
      {
        "file": "string",
        "row": 0
      }
    ],
    "can_commit": false,
    "blocking": [
      "claims_import_nothing_to_commit"
    ],
    "raw_identifiers_stored": false
  },
  "result": {
    "care_events_written": 9,
    "claims_committed": 110,
    "claims_replaced": 0,
    "diagnosis_rows_merged": 12,
    "dropped_link_ended_or_header_missing": 0,
    "members": 41,
    "profile_changed": false
  },
  "error_code": "string",
  "created_at": "string",
  "commit_started_at": "string",
  "committed_at": "string",
  "discarded_at": "string"
}

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

One claims import: dry run, progress, result

GET/v1/claims/imports/{claims_import_ref}claims.import.write

Imports YOUR client sent only (404 claims_import_not_found otherwise). Counts and row numbers only; no identifier or claim content.

Parameters

claims_import_refpath · stringrequired

Errors specific to this call

404claims_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/claims/imports/$CLAIMS_IMPORT_REF" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "claims_import_ref": "cli_8a1f0c3e5b7d9a2c4e6f8b0d",
  "status": "staged",
  "file_kinds": [
    "cclf1",
    "cclf4"
  ],
  "file_sha256": "string",
  "file_bytes": 0,
  "dry_run": {
    "files": [
      {
        "filename": "CCLF1.psv",
        "kind": "cclf1"
      }
    ],
    "rows_read": 0,
    "claims_parsed": 0,
    "claims_matched": 0,
    "claims_unmatched": 0,
    "claims_ambiguous": 0,
    "members_matched": 0,
    "match_rate": 0.92,
    "match_basis": {
      "mbi": 120
    },
    "diagnosis_rows_attached": 0,
    "by_part": {
      "A": 12,
      "B": 98,
      "D": 10
    },
    "by_setting": {},
    "service_from_min": "string",
    "service_thru_max": "string",
    "rejected": 0,
    "rejections_by_code": {},
    "rejections": [
      {
        "file": "CCLF5.psv",
        "row": 17,
        "code": "malformed_mbi"
      }
    ],
    "unmatched_rows": [
      {
        "file": "string",
        "row": 0
      }
    ],
    "can_commit": false,
    "blocking": [
      "claims_import_nothing_to_commit"
    ],
    "raw_identifiers_stored": false
  },
  "result": {
    "care_events_written": 9,
    "claims_committed": 110,
    "claims_replaced": 0,
    "diagnosis_rows_merged": 12,
    "dropped_link_ended_or_header_missing": 0,
    "members": 41,
    "profile_changed": false
  },
  "error_code": "string",
  "created_at": "string",
  "commit_started_at": "string",
  "committed_at": "string",
  "discarded_at": "string"
}

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

Commit a staged claims import

POST/v1/claims/imports/{claims_import_ref}/commitclaims.import.write

Attaches the staged claims in the background (poll GET, or subscribe to claims.import_completed). Members whose link ended since the dry run are dropped; a claim you sent before (same claim number) is replaced. Claims never change a member's self-reported conditions or medications. 409 claims_import_not_staged / claims_import_commit_in_progress / claims_import_nothing_to_commit / claims_baa_required (re-checked by the worker before the first write).

Parameters

claims_import_refpath · stringrequired

Errors specific to this call

409claims_import_not_staged

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/claims/imports/$CLAIMS_IMPORT_REF/commit" \
  -H "Authorization: Bearer $TOKEN"
Response 202
{
  "claims_import_ref": "cli_8a1f0c3e5b7d9a2c4e6f8b0d",
  "status": "staged",
  "file_kinds": [
    "cclf1",
    "cclf4"
  ],
  "file_sha256": "string",
  "file_bytes": 0,
  "dry_run": {
    "files": [
      {
        "filename": "CCLF1.psv",
        "kind": "cclf1"
      }
    ],
    "rows_read": 0,
    "claims_parsed": 0,
    "claims_matched": 0,
    "claims_unmatched": 0,
    "claims_ambiguous": 0,
    "members_matched": 0,
    "match_rate": 0.92,
    "match_basis": {
      "mbi": 120
    },
    "diagnosis_rows_attached": 0,
    "by_part": {
      "A": 12,
      "B": 98,
      "D": 10
    },
    "by_setting": {},
    "service_from_min": "string",
    "service_thru_max": "string",
    "rejected": 0,
    "rejections_by_code": {},
    "rejections": [
      {
        "file": "CCLF5.psv",
        "row": 17,
        "code": "malformed_mbi"
      }
    ],
    "unmatched_rows": [
      {
        "file": "string",
        "row": 0
      }
    ],
    "can_commit": false,
    "blocking": [
      "claims_import_nothing_to_commit"
    ],
    "raw_identifiers_stored": false
  },
  "result": {
    "care_events_written": 9,
    "claims_committed": 110,
    "claims_replaced": 0,
    "diagnosis_rows_merged": 12,
    "dropped_link_ended_or_header_missing": 0,
    "members": 41,
    "profile_changed": false
  },
  "error_code": "string",
  "created_at": "string",
  "commit_started_at": "string",
  "committed_at": "string",
  "discarded_at": "string"
}

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

Discard a staged claims import

POST/v1/claims/imports/{claims_import_ref}/discardclaims.import.write

Deletes the staged claims; the manifest (counts, codes, hash) stays.

Parameters

claims_import_refpath · stringrequired

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/claims/imports/$CLAIMS_IMPORT_REF/discard" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "claims_import_ref": "cli_8a1f0c3e5b7d9a2c4e6f8b0d",
  "status": "staged",
  "file_kinds": [
    "cclf1",
    "cclf4"
  ],
  "file_sha256": "string",
  "file_bytes": 0,
  "dry_run": {
    "files": [
      {
        "filename": "CCLF1.psv",
        "kind": "cclf1"
      }
    ],
    "rows_read": 0,
    "claims_parsed": 0,
    "claims_matched": 0,
    "claims_unmatched": 0,
    "claims_ambiguous": 0,
    "members_matched": 0,
    "match_rate": 0.92,
    "match_basis": {
      "mbi": 120
    },
    "diagnosis_rows_attached": 0,
    "by_part": {
      "A": 12,
      "B": 98,
      "D": 10
    },
    "by_setting": {},
    "service_from_min": "string",
    "service_thru_max": "string",
    "rejected": 0,
    "rejections_by_code": {},
    "rejections": [
      {
        "file": "CCLF5.psv",
        "row": 17,
        "code": "malformed_mbi"
      }
    ],
    "unmatched_rows": [
      {
        "file": "string",
        "row": 0
      }
    ],
    "can_commit": false,
    "blocking": [
      "claims_import_nothing_to_commit"
    ],
    "raw_identifiers_stored": false
  },
  "result": {
    "care_events_written": 9,
    "claims_committed": 110,
    "claims_replaced": 0,
    "diagnosis_rows_merged": 12,
    "dropped_link_ended_or_header_missing": 0,
    "members": 41,
    "profile_changed": false
  },
  "error_code": "string",
  "created_at": "string",
  "commit_started_at": "string",
  "committed_at": "string",
  "discarded_at": "string"
}

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

A member's claims summary (your imports + their Blue Button)

GET/v1/patients/{member_ref}/claims-summaryclaims.read

Counts by part and setting, service-date span, the top ICD-10 categories and CMS-HCC condition categories (only when an official CMS model is loaded; never a guessed mapping and never a risk score) from the claims you imported (BAA gate), plus the member's own Medicare Blue Button summary when they share their medical history with you.

Parameters

member_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/patients/$MEMBER_REF/claims-summary" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "mr_3f9c1a0b7d2e4c6a8b1d0e2f",
  "claims_total": 0,
  "first_service_date": "string",
  "last_service_date": "string",
  "sources": {},
  "top_diagnosis_categories": [
    {
      "category": "E11",
      "claims": 0
    }
  ],
  "hcc": {
    "available": false,
    "reason": "string",
    "note": "string",
    "condition_categories": [
      "string"
    ],
    "suppressed_by_hierarchy": [
      "string"
    ],
    "icd_codes_unmapped": 0,
    "icd_mapped_rate": 0.0,
    "model": {},
    "supports_interactions": false,
    "risk_score": 0.0,
    "risk_score_withheld": "string"
  },
  "profile_merged": false,
  "paid_amount_note": "string"
}

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

Whether a member connected Medicare Blue Button or VA records

GET/v1/patients/{member_ref}/connectionsclaims.read

Status, connected and last-sync times only, and only when the member shares their medical history with you (shared false and an empty list otherwise). Read-only: connecting is the member's act in the app.

Parameters

member_refpath · stringrequired

All responses

200Successful Response401Unauthorized403Forbidden404Not Found409Conflict422Unprocessable Entity429Too Many Requests503Service Unavailable

Codes every call can return are in Errors & limits.

curl -s "https://norvya.fly.dev/v1/patients/$MEMBER_REF/connections" \
  -H "Authorization: Bearer $TOKEN"
Response 200
{
  "member_ref": "string",
  "shared": false,
  "connections": [
    {
      "provider": "medicare_blue_button",
      "status": "connected",
      "environment": "production",
      "connected_at": "string",
      "last_sync_at": "string",
      "has_summary": false,
      "synthetic": false
    }
  ],
  "connect_in_app_only": false
}

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

HCC audit evidence for a member (never a score)

GET/v1/patients/{member_ref}/risk-adjustment-evidenceclaims.risk_adjustment.read

Every ICD-10-CM code in the claims YOU imported for the member, each with the dated claims that document it (claim_ref, part, setting, place of service, procedure codes present, service dates). When an official CMS-HCC model is loaded the codes are grouped into condition categories after the hierarchy (suppressed categories listed, unmapped codes kept); otherwise condition_categories is null with reason hcc_model_not_loaded: Norvya never ships or guesses a mapping. risk_score is always null. The claims are not filtered for risk-adjustment-eligible encounter types (CMS's filtering logic is not implemented). 409 claims_baa_required.

Parameters

member_refpath · stringrequired
yearquery · integer | null

Service year; default all.

Errors specific to this call

409claims_baa_required

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/risk-adjustment-evidence" \
  -H "Authorization: Bearer $TOKEN"

Webhook events

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

EventScopeWhen
claims.import_completedclaims.import.writeA claims import you sent finished committing (sent to that client only).

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

↑ ↓ to moveEnter to open