Skip to content

Eligibility check Operation

Canonical../OperationDefinition/eligibility-check
Statusdraft · 1.26.0
InvocationPOST [base]/$eligibility-check
Levelsystem
Affects stateyes -- not safe to repeat
SourceFSH · JSON

Ask a patient's province, through one clinic's payer account, whether that patient may be billed, and report how that run ended.

POST [base]/$eligibility-check

The caller names a patient, never a card. The health card the payer is asked about is read from the patient's own record. No health number travels in the request, and a caller cannot ask about a card the record does not hold. The caller's identity is likewise taken from the session rather than from the body, so a disclosure cannot be attributed to somebody else.

affectsState is true. A run spends the clinic's payer credential, writes an audit record, and on success replaces the settled answer stored on the patient's health card Identifier in the health-card-eligibility extension. It is a POST, it is not cacheable, and it is not safe to repeat blindly -- see the retry rule below.

There is no freshness rule and no cache. Every request asks the payer, unless a check for the same patient at the same clinic is already queued or running, in which case the second press collapses into the first rather than opening a second call. There is no parameter that forces, bypasses or re-asks: an unrecognised part in the body changes nothing and is ignored.

Do not feature-detect this operation from a running server's /metadata. Two different documents are easy to conflate here. This guide's server statement has kind = requirements: it says what a conformant endpoint must offer, and it does declare this operation. What a running instance publishes at /metadata is its own kind = instance statement, and the gateway serves this operation itself without advertising it there -- so a live capability lookup answers "absent" while the operation works. Neither document is wrong; they answer different questions.

So do not branch on /metadata. A practice that has the feature switched off is refused with an OperationOutcome at 403, and that refusal is the signal to act on.

What a reply can say, and what never reaches one

A reply is published only for a request that settled, was taken on, or collapsed into one already running. On a 200 the status parameter carries exactly one of four words:

status what it means
answered The payer settled the question while the caller waited. The answer part is present.
pending The request is queued. The answer lands on the patient's record when it arrives. Never means "not eligible".
alreadyInFlight A check for this patient at this clinic was already running, so no second one was taken on.
noAnswer The run reached the end and the payer settled nothing. Terminal: nothing further is queued and the record is unchanged.

Every other ending is an OperationOutcome rather than a reply, so the words naming those endings are never readable from a status parameter:

HTTP issue.code the endings that read this way
403 forbidden The caller may not ask, or the practice has eligibility checking switched off.
400 invalid The body does not describe a check, or the platform refused the request before the payer was asked.
422 business-rule The practice's own data cannot produce a question: an unsupported province, no usable card on record, a card issued by another province, or a patient the store does not hold.
503 transient A fault stopped the question being put, or stopped its outcome being read.

Match on the HTTP status and issue.code, never on the sentence beside them. The sentence in issue.diagnostics is developer-facing, is not a translation of anything, and is not stable.

Retrying is not free

A 503 covers two different situations that the wire does not distinguish. In one, the payer was never asked and the identical request may be sent again. In the other -- a reply that could not be read, or a wait that ran out after the request had gone out -- the check may already have run, because the platform does not stop when the caller's wait does. Re-read the patient's card before asking again rather than retrying on a timer. A 400, 403 or 422 is not worth repeating unchanged.

Reading the answer

The answer part is present exactly when status is answered, and its three children are named and typed exactly as the same three children are stored on the card in health-card-eligibility, so one parser serves both this reply and a Patient read.

Read it whole or not at all: eligible and answeredAt are both required for the answer to mean anything. answeredAt is when the payer gave THIS answer, not when the patient was last checked -- a re-check that agrees leaves the moment alone, so no freshness may be inferred from it. An absent coverageExpiry means the payer delivered none, not that coverage is unlimited.

For any status other than answered, this run settled nothing, and the patient's own record remains the place to read the current answer.

Asking for a check requires both the eligibility-check execute right and the eligibility write right. A caller holding one but not the other is refused at 403 before anything in the body is judged, so that outcome describes nothing that was sent.

Request parameters

Parameter Card. Type Documentation
patient 1..1 Reference
Patient Profile
The patient to ask about, as a literal relative reference of the form Patient/{id} and nothing else. It must be a Reference: a plain string carrying the same text is not read. The shape is judged exactly -- a bare id, an absolute URL, a versioned reference (Patient/1/_history/2), a reference to another type, and a trailing empty id are each refused, because each carries either no slash or more than one.
clinicId 1..1 string The clinic whose payer account asks the question, and whose credential the run spends. A string that must parse as a UUID; a value that does not parse is refused. The clinic is verified against the caller's own tenant before anything is queued.
serviceDate 0..1 date The day the check is asked for. CONTEXT ONLY: it gates nothing, opens no window, and does not change the answer -- it is carried alongside the queued work and echoed back. It must name a whole day: 2026-08 and 2026 are refused rather than rounded, and a string carrying the same text is not read. Omitting it is normal and is not read as today.

Response parameters

Parameter Card. Type Documentation
status 1..1 string How the run ended, published as a valueString. On a reply it is one of exactly four words: answered, pending, alreadyInFlight, noAnswer. The endings named featureDisabled, provinceNotSupported, noCardOnRecord, cardOutOfProvince, patientNotFound, patientUnreadable, credentialMissing and vendorUnavailable are published as OperationOutcomes and can never be read here. Tolerate a word this guide does not list: the platform and this guide ship on different cadences.
problem 0..1 string Why the run ended the way it did, when it ran and produced a typed problem, published as a valueString. Finer-grained than status and never a substitute for it. The vocabulary is credentialMissing, vendorUnavailable, vendorRejected, vendorAnswerUnknown, vendorPending, rateLimited, pollTimeout, alreadyInFlight, patientNotFound, patientUnreadable, noCardOnRecord, cardOutOfProvince, cardChangedDuringCheck, provinceNotSupported, featureDisabled, answerNotStored. Not every word can accompany every status, and a word this guide does not list must not break a reader.
message 1..1 string Display words a caller may show. Never a card value and never the payer's own text. Display it; do not branch on it.
patient 1..1 Reference
Patient Profile
The patient the request named, echoed back exactly as sent, so a reply read out of band still says who it is about.
serviceDate 0..1 date The day the request named, echoed back when it named one. Absent when the request named none; it is never filled in.
answer 0..1 (parts) The settled answer this run produced. Present EXACTLY when status is answered, and absent for every other status -- a pending reply carrying an answer is malformed. Its three children are named and typed exactly as the same three are stored on the card in the health-card-eligibility extension.
eligible 1..1 boolean The payer's settled answer for the card that was asked about. Required: an answer part without it carries no answer.
answeredAt 1..1 instant When the payer gave THIS answer -- NOT when the patient was last checked. The stored answer is rewritten only when it changes, so a re-check that agrees leaves this moment untouched and no freshness may be inferred from it. Required.
coverageExpiry 0..1 date The coverage expiry the payer delivered alongside the answer. Absent means the payer delivered none, NOT that coverage is unlimited.