Skip to the page
Chapters

Eligibility

Check eligibility

POST/api/v1/eligibility

Asks the payer about a subscriber's (or a dependent patient's) dental coverage and returns the check: the coverage status, plan, maximums, deductibles, coverage by category and the detail for the procedure codes asked about. Needs an Idempotency-Key header: repeating a request with the same key returns the first answer. Add Cache-Control: no-cache to skip a recent identical answer. When the payer rejects the check, answers that it is unavailable, or the network fails, the reply is an error that carries the check (see the check field of the error). In test mode the member ID chooses a sandbox scenario.

Needs a key with submit permission.

Request

Headers

Headers
NameTypeRequiredDescription
Idempotency-KeystringrequiredMakes the request safe to repeat: a request with the same key and body returns the first answer (the reply has an idempotent-replayed header), and the same key with a different request is refused. 1 to 255 printable characters; a UUID is a good choice.At least 1 character.At most 255 characters.Matches `^[\x21-\x7e]{1,255}$`.
Cache-ControlstringoptionalSend no-cache to skip a recent identical answer and ask the payer again. Without it, an identical request made recently is answered from the saved check (cache.state is hit).One of: `no-cache`.

Body

Body
NameTypeRequiredDescription
office_idstringrequiredThe office the check is for (off_...), from GET /offices. Its mode must match the key.
payer_idstringrequiredThe payer: a Claim House payer ID (pyr_...), a payer ID or an alias from the payer directory.
subscriberobjectrequiredThe plan holder.
subscriber.first_namestringrequiredThe subscriber's first name.At most 120 characters.
subscriber.last_namestringrequiredThe subscriber's last name.At most 120 characters.
subscriber.date_of_birthstring (date)requiredYYYY-MM-DD.
subscriber.member_idstringrequiredThe subscriber's member ID. In test mode it chooses the sandbox scenario.At most 80 characters.
subscriber.group_numberstring or nulloptionalThe plan group number.At most 80 characters.
patientobject or nulloptionalThe patient, when a dependent is being checked. Leave it out when the subscriber is the person being checked.
patient.first_namestringrequiredThe patient's first name.At most 120 characters.
patient.last_namestringrequiredThe patient's last name.At most 120 characters.
patient.date_of_birthstring (date)requiredYYYY-MM-DD.
patient.relationshipstringrequiredHow the patient relates to the subscriber: spouse, child, other.One of: `spouse`, `child`, `other`.
service_datestring (date) or nulloptionalYYYY-MM-DD, within 12 months of today. Default: today, in the office's time zone.
procedure_codesarray of string or nulloptionalUp to 10 CDT codes (D followed by 4 digits) to get coverage detail for.At most 10 items.Each item matches `^D\d{4}$`.
detail_levelstring or nulloptionalOne of standard, enhanced. Default: standard.One of: `standard`, `enhanced`.
tenant_referencestring or nulloptionalYour own reference for the check, returned with it. Up to 255 characters.At most 255 characters.
parent_idvalueoptionalThe rejected check this one corrects (elg_...), when resending it with the fixes.

Response

The check, when the payer answered it (active or inactive coverage). Status 200.

Response fields
NameTypeDescription
idstringAn ID that starts with elg_.
objectstringAlways `eligibility_check`.
office_idstringAn ID that starts with off_.
patient_idstring or nullThe patient this is about (pat_...) in the patient directory: the dependent when there is one, else the subscriber. Set by Claim House when a check completes or a claim's patient is written; null while a check is pending, and when the patient has no date of birth or a name with no letters or digits to compare.
payerobject
payer.idstringAn ID that starts with pyr_.
payer.payer_idstringThe payer's own payer ID.
payer.namestring
statestringOne of: `pending`, `completed`.
outcomestring or nullHow the check ended; null while pending.One of: `answered`, `rejected`, `payer_unavailable`, `error`.
statusstring or nullThe coverage status: active, inactive or unknown; null when there is no answer.One of: `active`, `inactive`, `unknown`.
billingobject or nullNull while the check is pending: it has no usage record yet.
billing.chargedboolean
billing.statestringOne of: `billable`, `not_billable`.
billing.reasonstringOne of: `test_mode`, `answered`, `payer_rejected`, `payer_side_rejection`, `payer_unavailable`, `network_error`, `internal_error`, `cache_hit`.
billing.labelstringWhy the check was or was not charged, in a sentence.
cacheobject
cache.statestringOne of: `fresh`, `hit`.
cache.source_idstring or nullAn ID that starts with elg_.
parent_idstring or nullThe rejected check this one corrects.
request_idstring or nullThe API request that made the check (the x-request-id of its response); null for a check made in the dashboard.
idempotency_keyvalueThe Idempotency-Key the check was sent with.
sourceobject or null
source.networkvalue
source.latency_msinteger or nullAt least -9007199254740991.
source.completed_atstring (date-time)
tenant_referencevalueYour own reference, sent with the check.
created_atstring (date-time)
requestobject
request.subscriberobject
request.subscriber.first_namestring
request.subscriber.last_namestring
request.subscriber.date_of_birthstring (date)
request.subscriber.member_idstring
request.subscriber.group_numbervalue
request.patientobject or null
request.patient.first_namestring
request.patient.last_namestring
request.patient.date_of_birthstring (date)
request.patient.relationshipstringOne of: `spouse`, `child`, `other`.
request.service_datestring (date)
request.procedure_codesarray of string
request.detail_levelstringThe level of detail asked for.One of: `standard`, `enhanced`.
request.office_npistringThe NPI of the office when the check was made.
rejectionobject or null
rejection.kindstringOne of: `fix_and_resend`, `payer_unavailable`, `rejected`.
rejection.payer_codestringThe payer's own rejection code.
rejection.reasonsarray of object
rejection.reasons[].codestringOne of: `MEMBER_NOT_FOUND`, `PATIENT_IS_DEPENDENT`, `DATE_OF_BIRTH_MISMATCH`, `MEMBER_ID_INVALID`, `MEMBER_ID_DUPLICATE`, `NAME_MISMATCH`, `SERVICE_DATE_INVALID`, `REQUEST_INVALID`, `REQUEST_NOT_ACCEPTED`, `PROVIDER_NOT_ON_FILE`, `PROVIDER_NOT_ELIGIBLE`, `PATIENT_NOT_ELIGIBLE`, `PATIENT_DETAILS_REQUIRED`, `PAYER_NOT_ANSWERING`, `PAYER_REJECTED_OTHER`.
rejection.reasons[].aboutstringWhose side the reason is on.One of: `subscriber`, `patient`, `provider`, `request`, `clearinghouse`, `payer`.
rejection.reasons[].fieldvalueThe request field to change (for example subscriber.member_id), or null.
rejection.reasons[].messagestring
rejection.reasons[].fixstring
rejection.reasons[].suggested_valuestring
coverage_effective_datevalue or null
coverage_termination_datevalue or null
planobject or null
plan.namevalue
plan.typevalue
plan.group_numbervalue
plan.benefit_periodvalue
network_statusstring or nullOne of: `in_network`, `out_of_network`, `unknown`.
maximumsarray of object or null
maximums[].levelstringOne of: `individual`, `family`.
maximums[].periodstringOne of: `calendar_year`, `plan_year`, `lifetime`.
maximums[].amountstring or nullMatches `^-?\d+\.\d{2}$`.
maximums[].usedstring or nullMatches `^-?\d+\.\d{2}$`.
maximums[].remainingstring or nullMatches `^-?\d+\.\d{2}$`.
maximums[].applies_tovalue
deductiblesarray of object or null
deductibles[].levelstringOne of: `individual`, `family`.
deductibles[].periodstringOne of: `calendar_year`, `plan_year`, `lifetime`.
deductibles[].amountstring or nullMatches `^-?\d+\.\d{2}$`.
deductibles[].usedstring or nullMatches `^-?\d+\.\d{2}$`.
deductibles[].remainingstring or nullMatches `^-?\d+\.\d{2}$`.
deductibles[].applies_tovalue
coveragearray of object or null
coverage[].categorystringOne of: `preventive`, `diagnostic`, `basic`, `endodontics`, `periodontics`, `oral_surgery`, `major`, `prosthodontics`, `implants`, `orthodontics`.
coverage[].percent_paidnumber or nullAt least 0.At most 100.
coverage[].coveredvalue
coverage[].frequencyvalue
coverage[].notesvalue
proceduresarray of object or null
procedures[].codestringMatches `^D\d{4}$`.
procedures[].descriptionvalue
procedures[].percent_paidnumber or nullAt least 0.At most 100.
procedures[].coveredvalue
procedures[].frequencyobject or null
procedures[].frequency.countinteger or nullAt least -9007199254740991.
procedures[].frequency.periodvalue
procedures[].frequency.scopevalue
procedures[].max_ageinteger or nullAt least 0.
procedures[].last_service_datestring (date) or null
procedures[].next_eligible_datestring (date) or null
procedures[].statusstring or nullOne of: `covered_now`, `not_due_yet`, `downgraded`, `age_limit`, `not_covered`.
procedures[].notevalue
plan_rulesobject or null
plan_rules.missing_tooth_clausevalue
plan_rules.waiting_periodvalue
plan_rules.pre_authorizationvalue
plan_rules.coordination_of_benefitsvalue
plan_rules.major_services_paid_onstring or nullOne of: `prep_date`, `seat_date`.
payer_notesarray of string or null
not_returnedarray of string or null

Errors

Errors
HTTP statusCodeWhat it means
401UNAUTHORIZEDA valid API key is required. Send it as "Authorization: Bearer <key>".
403PERMISSION_DENIEDThis API key is not allowed to do that.
422INVALID_REQUESTThe request is not valid.
400IDEMPOTENCY_KEY_REQUIREDPOST and PATCH requests need an Idempotency-Key header.
422IDEMPOTENCY_KEY_REUSEDThat Idempotency-Key was already used with a different request.
409IDEMPOTENCY_KEY_IN_USEA request with that Idempotency-Key is still running. Retry shortly.
413PAYLOAD_TOO_LARGEThe request body is larger than 1 MB.
504TIMEOUTThe request took too long to finish. It may still have taken effect: look it up before sending it again with a new Idempotency-Key. What it made is found with GET /api/v1/eligibility?request_id=<this request_id>, and the same filter on /api/v1/claims and /api/v1/attachments (a key with read permission).
422PAYER_REJECTEDThe payer rejected the check. The check object says what to change, and whether resending can help.
502PAYER_UNAVAILABLEThe payer's system is not answering right now. Nothing needs to change: send the check again later.
502NETWORK_ERRORThe check could not be completed because the payer network failed. It is not billed. Send it again later.
503ELIGIBILITY_UNAVAILABLEEligibility checks are not available in live mode yet. Use a test key.
500INTERNALSomething went wrong on our side. Quote the request ID if you contact us.

Example

Example request

Shell
curl -X POST "https://sandbox.myclaimhouse.com/api/v1/eligibility" \
  -H "Authorization: Bearer $CLAIMHOUSE_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "office_id": "off_01JM000000E008000000000003",
  "payer_id": "pyr_01JM000000E008000000000004",
  "subscriber": {
    "first_name": "Alex",
    "last_name": "Example",
    "date_of_birth": "1985-04-12",
    "member_id": "CH-ACTIVE-FULL",
    "group_number": "GRP-100"
  },
  "service_date": "2026-03-10",
  "procedure_codes": [
    "D0120",
    "D1110"
  ],
  "tenant_reference": "visit-1042"
}'

Example response: 200

JSON
{
  "id": "elg_01JM000000E00800000000000G",
  "object": "eligibility_check",
  "office_id": "off_01JM000000E008000000000003",
  "patient_id": "pat_01JM000000E00800000000004K",
  "payer": {
    "id": "pyr_01JM000000E008000000000004",
    "payer_id": "00000",
    "name": "Example Dental Plan"
  },
  "state": "completed",
  "outcome": "answered",
  "status": "active",
  "billing": {
    "charged": false,
    "state": "not_billable",
    "reason": "test_mode",
    "label": "Not billed: test mode"
  },
  "cache": {
    "state": "fresh",
    "source_id": null
  },
  "parent_id": null,
  "request_id": "req_01JM000000E008000000000010",
  "idempotency_key": "visit-1042-attempt-1",
  "source": {
    "network": "sandbox",
    "latency_ms": 180,
    "completed_at": "2026-03-10T15:30:00.430000+00:00"
  },
  "tenant_reference": "visit-1042",
  "created_at": "2026-03-10T15:30:00.250000+00:00",
  "request": {
    "subscriber": {
      "first_name": "Alex",
      "last_name": "Example",
      "date_of_birth": "1985-04-12",
      "member_id": "CH-ACTIVE-FULL",
      "group_number": "GRP-100"
    },
    "patient": null,
    "service_date": "2026-03-10",
    "procedure_codes": [
      "D0120",
      "D1110"
    ],
    "detail_level": "standard",
    "office_npi": "1900000000"
  },
  "coverage_effective_date": "2024-01-01",
  "coverage_termination_date": null,
  "plan": {
    "name": "Example Dental Plan PPO",
    "type": "PPO",
    "group_number": "GRP-100",
    "benefit_period": "Calendar year"
  },
  "network_status": "in_network",
  "maximums": [
    {
      "level": "individual",
      "period": "calendar_year",
      "amount": "2000.00",
      "used": "0.00",
      "remaining": "2000.00",
      "applies_to": null
    },
    {
      "level": "individual",
      "period": "lifetime",
      "amount": "3000.00",
      "used": "0.00",
      "remaining": "3000.00",
      "applies_to": "orthodontics"
    }
  ],
  "deductibles": [
    {
      "level": "individual",
      "period": "calendar_year",
      "amount": "50.00",
      "used": "0.00",
      "remaining": "50.00",
      "applies_to": "basic and major services"
    },
    {
      "level": "family",
      "period": "calendar_year",
      "amount": "150.00",
      "used": "0.00",
      "remaining": "150.00",
      "applies_to": "basic and major services"
    }
  ],
  "coverage": [
    {
      "category": "preventive",
      "percent_paid": 100,
      "covered": true,
      "frequency": null,
      "notes": "Exams and cleanings 2 per calendar year; bitewings 1 per year"
    },
    {
      "category": "diagnostic",
      "percent_paid": 100,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "basic",
      "percent_paid": 80,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "endodontics",
      "percent_paid": 80,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "periodontics",
      "percent_paid": 80,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "oral_surgery",
      "percent_paid": 80,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "major",
      "percent_paid": 50,
      "covered": true,
      "frequency": null,
      "notes": "Every 5 years; paid on seat date"
    },
    {
      "category": "prosthodontics",
      "percent_paid": 50,
      "covered": true,
      "frequency": null,
      "notes": null
    },
    {
      "category": "implants",
      "percent_paid": 0,
      "covered": false,
      "frequency": null,
      "notes": null
    },
    {
      "category": "orthodontics",
      "percent_paid": 50,
      "covered": true,
      "frequency": null,
      "notes": "To age 26; $3,000 lifetime maximum"
    }
  ],
  "procedures": [
    {
      "code": "D0120",
      "description": "Periodic oral exam",
      "percent_paid": 100,
      "covered": true,
      "frequency": {
        "count": 2,
        "period": "calendar_year",
        "scope": null
      },
      "max_age": null,
      "last_service_date": "2025-09-10",
      "next_eligible_date": null,
      "status": "covered_now",
      "note": null
    },
    {
      "code": "D1110",
      "description": "Adult cleaning",
      "percent_paid": 100,
      "covered": true,
      "frequency": {
        "count": 2,
        "period": "calendar_year",
        "scope": null
      },
      "max_age": null,
      "last_service_date": "2025-09-10",
      "next_eligible_date": null,
      "status": "covered_now",
      "note": "Shares 4 visits a year with D4910"
    }
  ],
  "plan_rules": {
    "missing_tooth_clause": "No",
    "waiting_period": "None",
    "pre_authorization": "Suggested over $300",
    "coordination_of_benefits": "Standard, birthday rule",
    "major_services_paid_on": "seat_date"
  },
  "payer_notes": [
    "Posterior composites are paid as amalgam on molars.",
    "Porcelain is downgraded on molars, not on bicuspids.",
    "Multi-visit procedures are paid on the seat date.",
    "D1110 and D4910 share 4 visits per calendar year.",
    "D0210 and D0330 share one limit every 60 months."
  ],
  "not_returned": [],
  "rejection": null
}

A rejection with something to fix: 422

JSON
{
  "error": "PAYER_REJECTED",
  "message": "The payer rejected the check. The check object says what to change, and whether resending can help.",
  "errors": [],
  "request_id": "req_01JM000000E008000000000010",
  "check": {
    "id": "elg_01JM000000E00800000000000G",
    "object": "eligibility_check",
    "office_id": "off_01JM000000E008000000000003",
    "patient_id": "pat_01JM000000E00800000000004K",
    "payer": {
      "id": "pyr_01JM000000E008000000000004",
      "payer_id": "00000",
      "name": "Example Dental Plan"
    },
    "state": "completed",
    "outcome": "rejected",
    "status": null,
    "billing": {
      "charged": false,
      "state": "not_billable",
      "reason": "test_mode",
      "label": "Not billed: test mode"
    },
    "cache": {
      "state": "fresh",
      "source_id": null
    },
    "parent_id": null,
    "request_id": "req_01JM000000E008000000000010",
    "idempotency_key": "visit-1042-attempt-1",
    "source": {
      "network": "sandbox",
      "latency_ms": 180,
      "completed_at": "2026-03-10T15:30:00.430000+00:00"
    },
    "tenant_reference": "visit-1042",
    "created_at": "2026-03-10T15:30:00.250000+00:00",
    "request": {
      "subscriber": {
        "first_name": "Alex",
        "last_name": "Example",
        "date_of_birth": "1985-04-12",
        "member_id": "CH-NOT-FOUND",
        "group_number": "GRP-100"
      },
      "patient": null,
      "service_date": "2026-03-10",
      "procedure_codes": [
        "D0120",
        "D1110"
      ],
      "detail_level": "standard",
      "office_npi": "1900000000"
    },
    "coverage_effective_date": null,
    "coverage_termination_date": null,
    "plan": null,
    "network_status": null,
    "maximums": null,
    "deductibles": null,
    "coverage": null,
    "procedures": null,
    "plan_rules": null,
    "payer_notes": null,
    "not_returned": null,
    "rejection": {
      "kind": "fix_and_resend",
      "payer_code": "75",
      "reasons": [
        {
          "code": "MEMBER_NOT_FOUND",
          "about": "subscriber",
          "field": "subscriber.member_id",
          "message": "Example Dental Plan could not find this subscriber.",
          "fix": "Check the member ID, name and date of birth against the insurance card, then send the check again."
        }
      ]
    }
  }
}

A payer that is not answering: 502

JSON
{
  "error": "PAYER_UNAVAILABLE",
  "message": "The payer's system is not answering right now. Nothing needs to change: send the check again later.",
  "errors": [],
  "request_id": "req_01JM000000E008000000000010",
  "check": {
    "id": "elg_01JM000000E00800000000000G",
    "object": "eligibility_check",
    "office_id": "off_01JM000000E008000000000003",
    "patient_id": "pat_01JM000000E00800000000004K",
    "payer": {
      "id": "pyr_01JM000000E008000000000004",
      "payer_id": "00000",
      "name": "Example Dental Plan"
    },
    "state": "completed",
    "outcome": "payer_unavailable",
    "status": null,
    "billing": {
      "charged": false,
      "state": "not_billable",
      "reason": "test_mode",
      "label": "Not billed: test mode"
    },
    "cache": {
      "state": "fresh",
      "source_id": null
    },
    "parent_id": null,
    "request_id": "req_01JM000000E008000000000010",
    "idempotency_key": "visit-1042-attempt-1",
    "source": {
      "network": "sandbox",
      "latency_ms": 180,
      "completed_at": "2026-03-10T15:30:00.430000+00:00"
    },
    "tenant_reference": "visit-1042",
    "created_at": "2026-03-10T15:30:00.250000+00:00",
    "request": {
      "subscriber": {
        "first_name": "Alex",
        "last_name": "Example",
        "date_of_birth": "1985-04-12",
        "member_id": "CH-PAYER-DOWN",
        "group_number": "GRP-100"
      },
      "patient": null,
      "service_date": "2026-03-10",
      "procedure_codes": [
        "D0120",
        "D1110"
      ],
      "detail_level": "standard",
      "office_npi": "1900000000"
    },
    "coverage_effective_date": null,
    "coverage_termination_date": null,
    "plan": null,
    "network_status": null,
    "maximums": null,
    "deductibles": null,
    "coverage": null,
    "procedures": null,
    "plan_rules": null,
    "payer_notes": null,
    "not_returned": null,
    "rejection": {
      "kind": "payer_unavailable",
      "payer_code": "42",
      "reasons": [
        {
          "code": "PAYER_NOT_ANSWERING",
          "about": "payer",
          "field": null,
          "message": "Example Dental Plan is not answering right now.",
          "fix": "Nothing needs to change. Try again in a few minutes."
        }
      ]
    }
  }
}