Claim Submission
This guide explains how to model your FHIR resources for the Candid Health integration to submit professional medical claims.
Overview
The Candid Health integration allows you to submit professional medical claims via the $candid-submit-claim custom operation on the Claim resource. On success, the operation returns a ClaimResponse saved to Medplum with Candid's encounter and claim identifiers written back for recordkeeping. Please contact the Medplum team to get access to this integration.
Creating the Claim
The following diagram shows the resources involved in submitting a claim to Candid Health.
Claim
| Field | Description | Required |
|---|---|---|
patient | Reference to the Patient | Yes |
provider | Reference to the rendering Practitioner | Yes |
billablePeriod.start | Preferred date of service when service lines carry no individual servicedDate | No |
created | Fallback date of service when billablePeriod.start is also absent | No |
insurance[0].coverage | Reference to the Coverage resource | Yes |
diagnosis | Array of ICD-10-CM diagnoses with sequence (1-based) and diagnosisCodeableConcept | Yes |
item | Array of service lines (see below) | Yes |
Each Claim.item (service line) requires:
| Field | Description | Required |
|---|---|---|
productOrService | CPT code (system: http://www.ama-assn.org/go/cpt) | Yes |
servicedDate | Date of service for this line. Falls back to Claim.billablePeriod.start, then Claim.created | No |
unitPrice | Charge amount in USD | Yes |
quantity | Number of units | Yes |
locationCodeableConcept | Place of service code (system: https://www.cms.gov/Medicare/Coding/place-of-service-codes). If omitted, the encounter defaults to 11 (Office). | No |
encounter | Reference to the Encounter resource | Yes |
diagnosisSequence | Array of 1-based indices into Claim.diagnosis (up to 4) | Yes |
modifier | CPT modifier codes | No |
Patient
| Field | Description | Required |
|---|---|---|
name.family | Last name | Yes |
name.given | First name | Yes |
birthDate | Date of birth | Yes |
gender | male, female, other, or unknown | Yes |
address | Home address with line, city, state, postalCode | Yes |
Practitioner (Rendering Provider)
| Field | Description | Required |
|---|---|---|
identifier | System must be http://hl7.org/fhir/sid/us-npi | Yes |
name | Provider name | Yes |
qualification[0].code | NUCC taxonomy code (system: http://nucc.org/provider-taxonomy, e.g. 207Q00000X for Family Medicine) | Yes |
Organization (Billing Provider)
The billing provider Organization is linked to the Practitioner via a PractitionerRole resource.
| Field | Description | Required |
|---|---|---|
identifier | NPI identifier (system: http://hl7.org/fhir/sid/us-npi) | Yes |
identifier | EIN/Tax ID (system: http://hl7.org/fhir/sid/us-ein) | Yes |
name | Organization name | Yes |
address | Organization address | Yes |
Organization (Payer)
The bot resolves the payer in Candid's directory using these identifiers in priority order:
| Priority | Identifier | System | Behavior |
|---|---|---|---|
| 1 | Candid payer UUID | https://www.joincandidhealth.com/payer-uuid | Direct lookup — skips name search entirely |
| 2 | CMS payer ID | https://www.cms.gov/payer-id | Name search filtered by ID |
| 3 | CHC payer ID | https://www.joincandidhealth.com/chc-payerid | Name search filtered by ID |
At least one identifier is required. name is also required (used in the name search for options 2 and 3). The bot hard-fails if no match is found in Candid's directory.
Coverage (Insured)
For insured claims, use the CandidCoverage profile. Coverage.payor must reference a payer Organization.
| Field | Description | Required |
|---|---|---|
status | Should be active | Yes |
subscriber | Reference to the subscriber Patient | Yes |
beneficiary | Reference to the beneficiary Patient | Yes |
subscriberId | Insurance member ID | Yes |
payor | Reference to the payer Organization | Yes |
relationship | Patient's relationship to the subscriber (system: http://terminology.hl7.org/CodeSystem/subscriber-relationship, e.g. self, spouse, child) | Yes |
class | Group number (type: group) and plan info | No |
period | Coverage effective dates | No |
Coverage (Self-Pay)
For self-pay claims, set Coverage.payor to reference the Patient directly. Do not apply the CandidCoverage profile to self-pay Coverage resources. No subscriberId is required.
{
"resourceType": "Coverage",
"status": "active",
"beneficiary": { "reference": "Patient/{id}" },
"payor": [{ "reference": "Patient/{id}" }]
}
The bot detects self-pay when payor references a Patient or RelatedPerson, skips payer lookup, and submits the claim to Candid with responsibleParty: SELF_PAY.
Encounter
| Field | Description | Required |
|---|---|---|
identifier | Unique encounter identifier (used as Candid's externalId) | Yes |
status | Encounter status (e.g. finished) | Yes |
subject | Reference to the Patient | Yes |
participant[0].individual | Reference to the rendering Practitioner | Yes |
period.start | Encounter start date/time | Yes |
period.end | Encounter end date/time | No |
Submitting the Claim
The $candid-submit-claim custom operation on Claim submits the claim to Candid Health's API and returns a ClaimResponse. Invoke it in either of these ways:
- Instance level — on a stored Claim:
POST {base}/fhir/R4/Claim/{id}/$candid-submit-claim - Type level — with a
Claimin the request body:POST {base}/fhir/R4/Claim/$candid-submit-claim
Instance level (after the Claim has been created and stored):
const claimResponse = await medplum.post(
medplum.fhirUrl('Claim', claim.id, '$candid-submit-claim')
);
Or via the FHIR REST API:
POST {base}/fhir/R4/Claim/{id}/$candid-submit-claim
On success, the operation returns a ClaimResponse resource saved to Medplum. The Candid encounter and claim IDs are written back onto both the ClaimResponse and the original Claim as identifiers:
{
"resourceType": "ClaimResponse",
"status": "active",
"outcome": "complete",
"request": { "reference": "Claim/{id}" },
"insurer": { "reference": "Organization/{payer-id}" },
"identifier": [
{ "system": "https://candidhealth.com/claim-id", "value": "..." },
{ "system": "https://candidhealth.com/encounter-id", "value": "..." }
],
"total": [
{
"category": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/adjudication", "code": "submitted" }] },
"amount": { "value": 175.00, "currency": "USD" }
}
]
}
The operation is idempotent. If an active ClaimResponse already exists for the Claim, the bot returns it immediately without re-submitting to Candid.
Example transaction Bundle
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "urn:uuid:billing-org",
"resource": {
"resourceType": "Organization",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-billing-organization"]
},
"identifier": [
{ "system": "http://hl7.org/fhir/sid/us-npi", "value": "1234567890" },
{ "system": "http://hl7.org/fhir/sid/us-ein", "value": "12-3456789" }
],
"name": "Test Medical Practice LLC",
"type": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/organization-type", "code": "prov", "display": "Healthcare Provider" }] }],
"address": [{ "use": "work", "line": ["456 Medical Center Drive", "Suite 100"], "city": "Boston", "state": "MA", "postalCode": "02101" }]
},
"request": { "method": "POST", "url": "Organization", "ifNoneExist": "identifier=http://hl7.org/fhir/sid/us-npi|1234567890" }
},
{
"fullUrl": "urn:uuid:patient",
"resource": {
"resourceType": "Patient",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-patient"]
},
"identifier": [{ "system": "http://hospital.example.org/patients", "value": "PAT-TEST-001" }],
"name": [{ "use": "official", "family": "TestPatient", "given": ["Jane", "Marie"] }],
"gender": "female",
"birthDate": "1990-07-22",
"address": [{ "use": "home", "line": ["789 Oak Avenue", "Apt 2A"], "city": "Cambridge", "state": "MA", "postalCode": "02139" }]
},
"request": { "method": "POST", "url": "Patient" }
},
{
"fullUrl": "urn:uuid:practitioner",
"resource": {
"resourceType": "Practitioner",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-practitioner"]
},
"identifier": [{ "system": "http://hl7.org/fhir/sid/us-npi", "value": "1234567890" }],
"name": [{ "use": "official", "family": "Johnson", "given": ["Sarah", "M"], "prefix": ["Dr."] }],
"qualification": [
{
"code": {
"coding": [{ "system": "http://nucc.org/provider-taxonomy", "code": "207Q00000X", "display": "Family Medicine" }]
}
}
]
},
"request": { "method": "POST", "url": "Practitioner", "ifNoneExist": "identifier=http://hl7.org/fhir/sid/us-npi|1234567890" }
},
{
"fullUrl": "urn:uuid:practitioner-role",
"resource": {
"resourceType": "PractitionerRole",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-practitioner-role"]
},
"practitioner": { "reference": "urn:uuid:practitioner" },
"organization": { "reference": "urn:uuid:billing-org" }
},
"request": { "method": "POST", "url": "PractitionerRole" }
},
{
"fullUrl": "urn:uuid:payer-org",
"resource": {
"resourceType": "Organization",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-payer-organization"]
},
"identifier": [{ "system": "https://www.cms.gov/payer-id", "value": "13162" }],
"name": "1199SEIU Family of Funds",
"type": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/organization-type", "code": "ins", "display": "Insurance Company" }] }]
},
"request": { "method": "POST", "url": "Organization", "ifNoneExist": "identifier=https://www.cms.gov/payer-id|13162" }
},
{
"fullUrl": "urn:uuid:coverage",
"resource": {
"resourceType": "Coverage",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-coverage"]
},
"status": "active",
"type": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "HIP", "display": "Health Insurance Plan Policy" }] },
"subscriber": { "reference": "urn:uuid:patient" },
"subscriberId": "MEM-TEST-001",
"beneficiary": { "reference": "urn:uuid:patient" },
"relationship": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/subscriber-relationship", "code": "self", "display": "Self" }] },
"payor": [{ "reference": "urn:uuid:payer-org" }],
"class": [{ "type": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/coverage-class", "code": "group" }] }, "value": "GRP-TEST-123", "name": "Test Employer Group" }]
},
"request": { "method": "POST", "url": "Coverage" }
},
{
"fullUrl": "urn:uuid:encounter",
"resource": {
"resourceType": "Encounter",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-encounter"]
},
"identifier": [{ "system": "http://hospital.example.org/encounters", "value": "ENC-TEST-001" }],
"status": "finished",
"class": { "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "AMB", "display": "ambulatory" },
"type": [{ "coding": [{ "system": "http://snomed.info/sct", "code": "185349003", "display": "Office visit" }] }],
"subject": { "reference": "urn:uuid:patient" },
"participant": [{ "individual": { "reference": "urn:uuid:practitioner" } }],
"period": { "start": "2025-01-15", "end": "2025-01-15" }
},
"request": { "method": "POST", "url": "Encounter" }
},
{
"fullUrl": "urn:uuid:claim",
"resource": {
"resourceType": "Claim",
"meta": {
"profile": ["https://medplum.com/profiles/integrations/candid-health/StructureDefinition/candid-claim"]
},
"status": "active",
"use": "claim",
"type": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/claim-type", "code": "professional", "display": "Professional" }] },
"patient": { "reference": "urn:uuid:patient" },
"created": "2025-01-15T10:00:00Z",
"provider": { "reference": "urn:uuid:practitioner" },
"priority": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/processpriority", "code": "normal" }] },
"insurance": [{ "sequence": 1, "focal": true, "coverage": { "reference": "urn:uuid:coverage" } }],
"diagnosis": [
{
"sequence": 1,
"diagnosisCodeableConcept": { "coding": [{ "system": "http://hl7.org/fhir/sid/icd-10-cm", "code": "J06.9", "display": "Acute upper respiratory infection, unspecified" }] },
"type": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/ex-diagnosistype", "code": "principal" }] }]
},
{
"sequence": 2,
"diagnosisCodeableConcept": { "coding": [{ "system": "http://hl7.org/fhir/sid/icd-10-cm", "code": "R05.9", "display": "Cough, unspecified" }] }
}
],
"item": [
{
"sequence": 1,
"diagnosisSequence": [1, 2],
"productOrService": { "coding": [{ "system": "http://www.ama-assn.org/go/cpt", "code": "99213", "display": "Office visit, established patient, low complexity" }] },
"servicedDate": "2025-01-15",
"locationCodeableConcept": { "coding": [{ "system": "https://www.cms.gov/Medicare/Coding/place-of-service-codes", "code": "11", "display": "Office" }] },
"quantity": { "value": 1 },
"unitPrice": { "value": 125.00, "currency": "USD" },
"net": { "value": 125.00, "currency": "USD" },
"encounter": [{ "reference": "urn:uuid:encounter" }]
}
],
"total": { "value": 125.00, "currency": "USD" }
},
"request": { "method": "POST", "url": "Claim" }
}
]
}
Candid Health Workflow
Once the operation is invoked, the bot runs the following steps:
- Encounter Creation — The bot creates a Candid encounter with patient demographics, provider info, and all diagnoses. Candid returns an
encounterIdandclaimId. On transient failures the bot retries up to 3 times; if the encounter already exists in Candid (identified by the FHIREncounter.idas the external ID) it is fetched instead of re-created. - Service Line Creation — For each
Claim.item, the bot creates a Candid service line with the CPT code, charge amount, and diagnosis pointers. This step is skipped if the encounter was recovered rather than freshly created to avoid duplicating service lines. - ClaimResponse Creation — The bot saves a
ClaimResponseto Medplum withoutcome: completeand writes the Candidclaim-idandencounter-idback onto both theClaimResponseand the originalClaimas identifiers. - Debug Documents — The bot stores the outgoing Candid encounter request and the raw Candid response as
DocumentReferenceresources for troubleshooting. Each document is linked to the originating Claim (viacontext.related) and Patient (viasubject). Query them with:GET {base}/fhir/R4/DocumentReference?type=https://candidhealth.com/document-type|encounter-requestGET {base}/fhir/R4/DocumentReference?type=https://candidhealth.com/document-type|encounter-response
Common Claim Status Values
| Status | Description |
|---|---|
coded | Claim has been coded and is ready for biller review |
biller_received | Claim received by the biller |
waiting_for_provider | Claim has blocking tasks requiring provider action (usually a contracting issue) |