Skip to main content

Claims Service — API Contracts

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: SERVICE_OVERVIEW · Service Template · 02 DDD

Base URL

/api/v1/claims-service

All routes require:

  • Authorization: Bearer <JWT> (Keycloak tenant realm)
  • X-Tenant-ID: <tenantId> header (validated against JWT tenant_id claim)
  • Module entitlement ehr.claims — write operations return 403 MODULE_NOT_LICENSED if absent

Claims

POST /api/v1/claims

Assemble and submit a new claim from encounter charges.

Request body:

{
"encounterId": "enc_01HXY...",
"coverageId": "cov_01HXY...",
"chargeIds": ["chg_01HXY...", "chg_01HXY2..."],
"billProviderId": "prov_01HXY...",
"renderingProviderId": "prov_01HXY2...",
"serviceDate": { "from": "2026-03-01", "to": "2026-03-01" },
"diagnosisCodes": ["J06.9"],
"autoSubmit": true
}

Response 201:

{
"claimId": "clm_01HXY...",
"status": "submitted",
"clearinghouseRef": "CHX-2026-00123",
"totalBilled": { "amount": 275.00, "currency": "USD" }
}

GET /api/v1/claims

List claims with filtering.

Query parameters:

ParameterTypeDescription
patientIdstringFilter by patient
encounterIdstringFilter by encounter
statusstringClaim status filter
fromDatedateService date range start
toDatedateService date range end
pagenumberPage number (default 1)
pageSizenumberMax 100 (default 20)

Response 200:

{
"data": [{ "claimId": "clm_...", "status": "paid", "totalBilled": {...}, "serviceDate": {...} }],
"meta": { "total": 142, "page": 1, "pageSize": 20 }
}

GET /api/v1/claims/:claimId

Retrieve full claim detail.

Response 200:

{
"claimId": "clm_01HXY...",
"patientId": "pat_...",
"encounterId": "enc_...",
"coverageId": "cov_...",
"status": "accepted",
"payerClaimNumber": "PAY-2026-99999",
"diagnosisCodes": ["J06.9"],
"lineItems": [...],
"totalBilled": { "amount": 275.00, "currency": "USD" },
"denial": null,
"createdAt": "2026-03-01T10:00:00Z",
"updatedAt": "2026-03-02T14:30:00Z"
}

POST /api/v1/claims/:claimId/submit

Manually trigger submission for a ready claim (if autoSubmit: false).

Response 200: { "status": "submitted", "clearinghouseRef": "..." }


POST /api/v1/claims/:claimId/appeal

File an appeal for a denied claim.

Request body:

{
"denialId": "dnl_01HXY...",
"appealNotes": "Medical necessity documentation attached."
}

Response 200: { "appealStatus": "filed", "appealDeadline": "2026-05-01" }


POST /api/v1/claims/:claimId/resubmit

Create a corrected replacement claim.

Request body: (same shape as POST /api/v1/claims, with corrected fields)

Response 201: { "claimId": "clm_NEW...", "status": "submitted", "replacesClaimId": "clm_OLD..." }


Coverages

POST /api/v1/coverages

Add an insurance coverage record for a patient.

Request body:

{
"patientId": "pat_01HXY...",
"payerId": "pyr_01HXY...",
"subscriberId": "MBR-123456",
"groupNumber": "GRP-789",
"planName": "Blue Shield PPO",
"priority": "primary",
"relationship": "self",
"effectiveFrom": "2026-01-01",
"effectiveTo": null
}

Response 201: { "coverageId": "cov_01HXY...", "status": "active" }


GET /api/v1/coverages

Query: patientId (required), priority, status

Response 200: Paginated list of coverage records ordered by priority.


GET /api/v1/coverages/:coverageId

Full coverage detail.


PATCH /api/v1/coverages/:coverageId

Update coverage fields (effectiveTo, planName, copay, etc.).


POST /api/v1/coverages/:coverageId/eligibility-checks

Trigger real-time eligibility verification.

Response 201:

{
"eligibilityId": "elig_01HXY...",
"status": "active",
"deductibleMet": { "amount": 250.00, "currency": "USD" },
"oopMet": { "amount": 500.00, "currency": "USD" },
"coinsurance": 20,
"expiresAt": "2026-04-19T00:00:00Z"
}

GET /api/v1/coverages/:coverageId/eligibility-checks

List eligibility check history for a coverage.


Prior Authorizations

POST /api/v1/authorizations

Request a prior authorization.

Request body:

{
"coverageId": "cov_01HXY...",
"patientId": "pat_01HXY...",
"procedureCode": { "system": "CPT", "code": "27447" },
"diagnosisCodes": ["M17.11"],
"requestedUnits": 1
}

Response 201: { "authorizationId": "auth_01HXY...", "status": "pending" }


GET /api/v1/authorizations/:authorizationId

Authorization detail including decision.


PATCH /api/v1/authorizations/:authorizationId

Update authorization (record external decision, extend validity).


Remittances

POST /api/v1/remittances/ingest

Ingest an ERA payload (called by the EDI ingest worker).

Request body: { "channel": "x12_835", "rawPayload": "<X12 835 content>" }

Response 202: { "remittanceId": "rem_01HXY...", "processingStatus": "queued" }


GET /api/v1/remittances/:remittanceId

Remittance summary with per-claim allocation detail.


FHIR R4 Read Surface

The following FHIR R4 endpoints are available for read/search. Write operations use the REST API above.

FHIR ResourceEndpointNotes
CoverageGET /fhir/R4/Coverage/{id}Single record
CoverageGET /fhir/R4/Coverage?patient={patientId}Patient coverages
ClaimGET /fhir/R4/Claim/{id}Single claim
ClaimGET /fhir/R4/Claim?patient={patientId}&status={status}Filtered claims
ClaimResponseGET /fhir/R4/ClaimResponse/{id}Claim response/acknowledgement
ClaimResponseGET /fhir/R4/ClaimResponse?request={claimId}Response for specific claim
CoverageEligibilityRequestGET /fhir/R4/CoverageEligibilityRequest/{id}Eligibility request
CoverageEligibilityResponseGET /fhir/R4/CoverageEligibilityResponse/{id}Eligibility response
ExplanationOfBenefitGET /fhir/R4/ExplanationOfBenefit/{id}Single EOB
ExplanationOfBenefitGET /fhir/R4/ExplanationOfBenefit?patient={patientId}Patient EOBs

Common Error Codes

CodeHTTPMeaning
CLAIM_NOT_FOUND404Claim does not exist for this tenant
CLAIM_INVALID_STATE409Transition not permitted in current state
CLAIM_VALIDATION_FAILED422Pre-submission scrub errors
COVERAGE_NOT_FOUND404Coverage not found
COVERAGE_INACTIVE422Coverage expired or cancelled
CODING_INVALID422ICD-10/CPT code invalid per terminology-service
SUBMISSION_FAILED502Payer/clearinghouse unavailable
MODULE_NOT_LICENSED403Tenant missing ehr.claims entitlement
UNAUTHORIZED401Missing or invalid JWT
FORBIDDEN403Insufficient RBAC role