API
Seven operations
Send a bill and the Explanation of Benefits your insurer issued for the same care. Get back where the two disagree, and a letter you can send about it.
Status: live. The base URL is https://medbillanalyzer.onrender.com and it answers now. It runs on an instance that spins down when nothing is calling it, so the first request after a quiet spell takes about 50 seconds; everything after that is immediate. The document below is generated from the code that serves these operations, not written alongside it.
Shape
What the calls are
| Call | Does | Costs |
|---|---|---|
| POST /v1/cases | Reads the documents and compares them. Returns how many findings there are and how much is in question. | Free |
| GET /v1/cases/{id} | The same summary, plus every finding in detail once the case is unlocked. | Free / paid |
| POST /v1/cases/{id}/unlock | Returns a checkout URL. It never charges anything itself. | $10, or $10/mo |
| POST /v1/cases/{id}/outputs | The dispute letter and the phone script, in the patient's name. | Paid |
| GET /v1/cases/{id}/export | Everything held about the case, as JSON. Needs no token and costs nothing — you cannot be charged to see what we hold about you. | Free |
| POST /v1/cases/{id}/outcome | What came of the letter — corrected, refused, ignored, or never sent. The answer is counted in aggregate and never recorded against the case. | Free |
| DELETE /v1/cases/{id} | Destroys the case. Needs the one-time delete token issued when it was created; the case id alone reads, it does not erase. | Free |
Seven, deliberately. Four do the work; two exist because a person is entitled to take their record back and to destroy it, and a right nobody can exercise through the API is not a right. An agent works better against a surface it can hold at once, so there are no others.
Two things that bite
Read these before you call it
- Never add the findings together. amount_in_question_cents is already de-duplicated. Two findings routinely describe the same dollars from different angles — a line billed above the contracted rate is usually also part of a bill that asks for more than the plan says is owed — so summing them overstates the problem in a letter a patient signs and sends. Use the total we give you.
- next_step is addressed to you, not to the patient. It says things like "Ask the patient for a clearer copy". If you are rendering straight to a person, use you_can, which is the same guidance in the second person.
- The comparison is not done by a model. A reader transcribes what is printed; fixed rules decide what it means. The same documents always produce the same findings, and every finding names the rule behind it.
- Send the document, not your own transcription. Both work, but bill_document is read by an extractor tuned for these forms and measured against a field-accuracy harness. Your own parse is not.
Errors
Every failure says what to do
Each error carries a stable code to branch on, a message that is safe to show a patient, and guidance. The status is specific on purpose: a generic 4xx sends an agent into a debugging loop that burns the user's usage meter.
| Status | Means |
|---|---|
| 402 | The case is not unlocked. Call unlock first. |
| 409 | Nothing to unlock — there were no findings. Do not offer to sell anything. |
| 415 | We cannot read that kind of file. |
| 422 | The document was too poor to check. Ask for a clearer copy. |
| 429 | Back off and retry. |
| 503 | A dependency is down. Retryable. |
Also
MCP, if you prefer it
The same seven operations are exposed as MCP tools over stdio, with the same names and the same schemas — both faces are generated from one declaration, so they cannot drift apart. check_medical_bill, get_case, unlock_case, get_case_outputs, delete_case, export_case, report_outcome.
The machine-readable description is at /openapi.json. It is generated from the routing table, so it describes what the server actually answers rather than what someone remembered to write down.