08 · Submit
Pre-flight should hold no surprises. Every check it runs has been running since you added the first line.
Everything below elaborates this sentence.
Why this stop exists
Two things happen here, in order, and they get conflated: the visit closes, then the claim is sent. Closing needs consent from the patient. Sending needs the claim to be complete.
Close the visit with consent
A visit closes the way it opened, with consent. Discharge is authorised in its own right rather than treated as a formality.
Two pre-discharge checks run before the closing consent is even offered. Every unretired line must have an active reservation, and where the visit was opened from a card swipe, the authorisation has to trace back to a live session rather than to some other factor.
Ask for the closing authentication. It is the same call as visit open, with purpose set to close the visit. See 03 · Consent.
closing_authorization_refClosing is a purpose of its own. A proof taken to open the visit can never satisfy it, however strong and however recent it is, so there is nothing to reuse here and no shortcut worth hunting for. The reason for that rule, and what it prevents, is at one proof, spent more than once.
closing_authorization_ref travels onto the claim.
Pre-flight: the six gates
| Call | What it does | What you keep |
|---|---|---|
Reservation exists | Every billed line traces to a reservation | reservation_id per line |
Amount ≤ reserved | No line bills more than was held for it | — |
Lines mapped | Every code has an unbroken path to a payer revenue code | mapping |
Attachments present | Every requiredDocuments entry has a matching document | document keys |
Diagnosis present | Exactly one primary diagnosis is recorded, each linked to the intervention it justifies. This is recorded at 05 · Treat rather than assembled here | icd11_code |
Dates within cover | Visit dates fall inside the cover's validity window | — |
Run every gate and return all failures at once, each with a route to its fix.
Every reason carries fix_stage and fix_label. Use them to send the operator straight to the
screen that can resolve the problem, rather than showing a list and leaving them to hunt.
Severity matters. A blocker stops submission and a warning does not, but a warning cannot
ride through unexamined either, so it persists until someone confirms it.
Close and submit
Re-run every gate, then submit. Idempotent on external_id.
There is one endpoint, whichever payer the claim is destined for. The dispatch decision was made back at eligibility when the cover was chosen and has been carried on every line since, so you never select a different endpoint per payer.
Submission needs somewhere to deliver the decision, and that is a precondition, not a nicety. If
there is no registered claim.decision endpoint and no X-Callback-Url header on the request,
you get CALLBACK_NOT_REGISTERED. Register the default once at
00 · Authenticate and you will never see the check. Use the header
when one particular claim's outcome belongs somewhere else.
Six kinds of claim, and eleven states
Two counts are worth correcting, because a state machine built to the wrong one leaves cases with no branch.
There are six claim types, not four. Ambulance is live and behaves differently from everything else, and oncology is live for named facilities rather than still in development. Treat the type as data on the claim and switch on it, rather than assuming one shape.
The authorisation moves through eleven states, not four. These are the states of the authorisation that opened and closed the visit, a different enum from the twelve a preauthorisation moves through, and the two are easy to confuse. Anything modelled on "pending, approved, rejected, done" will meet states it quietly drops. Read the enum from the reference, and when a value arrives that you do not know, hold the claim instead of discarding it.
Missing documents have their own terminal deadline. A claim returned for documents can be resubmitted, but only inside a window, after which it is rejected and cannot be resubmitted at all. It is the one deadline where nothing can be recovered afterwards, so it belongs on a worklist of its own rather than in a general queue.
After it lands
Submissions are reviewed in batches with rules doing part of the work, but anything with an issue goes to a person. Expect decision latency to reflect that.
Decisions are per line and can be partial:
Code
A claim can also come back returned, meaning sent back with feedback for correction rather
than rejected. It keeps its claim_id and is resubmitted under the same external_id. A
resubmitted bill may not exceed the original.
Documents are checked in two places
The required list is per procedure, and it splits across two moments: some documents belong to the preauthorisation and some to the claim. An inpatient submission needs a discharge summary and a final bill; maternity needs only the discharge summary. Collecting the right documents at the wrong stage still fails here.
Two practical rules. Uploads must be idempotent, so a retry does not create a second attachment. PDFs must be sent with the correct content type, because the failure you get when they are not is confusing rather than explicit.
What breaks here
| Where it surfaces | What the desk sees | What actually went wrong |
|---|---|---|
| Submit | "It will not let us submit and we cannot see why" | Pre-flight returned blockers. Every one carries a fix_stage, so surface them as actions rather than as a wall of text. |
| Submit | "Callback not registered" | A callback for claim.decision has to exist before any claim can be sent. Register it at Authenticate rather than here. |
| Submit | "The visit will not close" | Almost always the missing discharge consent. Closing needs an authentication of its own. |
| After | "We resubmitted and now there are two claims" | A new external_id was generated. Reuse the original one, because submission is idempotent on it. |
Errors
| HTTP | error | When |
|---|---|---|
| 422 | NOT_READY | Close called while pre-flight is ready: false. |
| 409 | CALLBACK_NOT_REGISTERED | No callback exists for claim.decision. |
| 409 | CLAIM_DATE_OUT_OF_COVER | A billed date falls outside the cover's window. |
| 409 | RESERVATION_MISSING | A line has no active reservation at discharge. |
| Where it surfaces | What the desk sees | What actually went wrong |
|---|---|---|
| Submit | "The claim sat in our queue and the window closed" | Someone assumed the time bar was generous. It is disputed and may be short, so show the deadline on the claim and alert before it rather than after. |
| Submit | "A returned claim can no longer be resubmitted" | The missing-documents window elapsed. That deadline is terminal, and nothing recovers the claim afterwards. |
| Anywhere | "Our state machine has no branch for this status" | Eleven authorisation states and six claim types, and preauthorisations have their own twelve. Handle an unknown value by holding the claim rather than dropping it. |
Next
Next: 09 · Reconcile

