post_claims_by_id_approve
Calls POST /api/claims/{id}/approve as the signed-in person · REST reference
Approve a claimed voucher and credit the clinic (deferred EFT)
THE ONLY STEP IN THE CLAIM FLOW THAT MOVES MONEY. The whole operation — the state change and the credit — runs in one DAL command transaction and is idempotent, so a repeat call does not double-credit. The credit is deferred EFT: it accrues to the clinic's balance account whether or not that org has a Stripe Connect account yet. The path id is the VOUCHER id; there is no separate claim entity. EVERY voucher is paid on its invoice: the PDF of the work done must be STORED, and the payout is the procedure and its supporting costs read off it, capped at the voucher's cap — min(covered amount, maxPayout, else face value). No voucher credits its face value by default. On the automatic path the service WAITS up to about six seconds polling for the AI verdict before answering, and anything not confidently VALID is held for a human with a 409 rather than denied. Supplying amount is how a reviewer resolves that hold; it is still capped. THE APPROVAL NAMES THE INVOICE IT WAS DECIDED ON. A clinic may file another invoice while its claim is CLAIMED, so a reviewer sends expectedInvoiceSha256 — the receiptSha256 of the voucher they read (GET /api/vouchers/{id}) — and the approval is refused, 409, with nothing credited, once another invoice is on file. It is required whenever the voucher's invoice carries a hash: an approval naming none is refused 400 before anything is read from the AI or written. A claim whose invoice was filed before hashes were stored carries none and is approved without one. A repeat of an approved claim credits nothing and names nothing.
Arguments
| Argument | Type | Description | |
|---|---|---|---|
idpath | string (uuid) | required | Voucher id of the claim to approve. |
bodyJSON | object | The request body, as a JSON object. Its fields are listed below. |
Fields of body
| Field | Type | Description | |
|---|---|---|---|
amount | integer | Reviewer-approved covered amount in CENTS, for resolving a claim held in manual review. Parsed with parseInt, so a decimal is truncated; negative or non-finite answers 400. Omitted or blank takes the automatic path. Capped at the voucher's cap like the automatic amount. | |
expectedInvoiceSha256 | string | null | The invoice the reviewer read: the receiptSha256 of the voucher they approve from, 64 lowercase hex characters (anything else answers 400). Required whenever the voucher's invoice carries a hash; omitted or null names none. The approval is refused, 409, when another invoice is on file. |
Example call
A client sends this over the MCP session; Claude and other agents build it for you. The values are placeholders — the shape is real.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "post_claims_by_id_approve",
"arguments": {
"id": "11111111-1111-4111-8111-111111111111",
"body": {
"amount": 1,
"expectedInvoiceSha256": "string"
}
}
}
}Result
On success (HTTP 200) the tool returns one text item holding the API's JSON, pretty-printed.
The claim was approved; credited says whether money actually moved.
{
"amount": 1,
"credited": true,
"currency": "string",
"event": {
"aggregateId": "string",
"aggregateType": "string",
"eventId": "string",
"eventType": "string",
"timestamp": 1
},
"state": "string",
"voucherId": "11111111-1111-4111-8111-111111111111",
"accountId": "11111111-1111-4111-8111-111111111111",
"newBalance": 1,
"orgId": "11111111-1111-4111-8111-111111111111",
"transactionId": "11111111-1111-4111-8111-111111111111"
}Fields
| Field | Type | Description |
|---|---|---|
accountId | string (uuid) | null | |
amount | integer | Amount credited in CENTS. |
credited | boolean | False on an idempotent repeat, where the claim was already approved and no second credit was written. |
currency | string | |
event | object | |
event.aggregateId | string | |
event.aggregateType | string | |
event.eventId | string | |
event.eventType | string | |
event.timestamp | number | |
newBalance | integer | null | The clinic's balance after the credit, in CENTS. |
orgId | string (uuid) | null | The clinic credited. |
state | string | The voucher's state after approval. |
transactionId | string (uuid) | null | |
voucherId | string (uuid) |
When it fails
A failed call returns isError: true with the API's message as text. A change the person declines, or lets time out, also comes back this way and nothing changes.
400amountis negative or not a number;expectedInvoiceSha256is not a sha256 digest; or the voucher's invoice carries a hash and the approval names none (Name the invoice you reviewed: …). Nothing is written.403Authenticated, but the caller holds none of the required permissions.
404No such resource — or none this caller may see.
409The claim is not approvable as it stands — the voucher is not CLAIMED, its state changed under the compare-and-set, it names no claiming org, it has no invoice PDF stored, the receipt is pending manual review and a reviewer must resupply
amount, or the invoice the approval names is no longer the one on file (The invoice changed after this claim was evaluated): read the voucher again and review the invoice now on file.
What the model is shown
This is the tool exactly as the server lists it in tools/list. The description starts with the REST call it makes.
{
"name": "post_claims_by_id_approve",
"description": "POST /api/claims/{id}/approve — THE ONLY STEP IN THE CLAIM FLOW THAT MOVES MONEY. The whole operation — the state change and the credit — runs in one DAL command transaction and is idempotent, so a repeat call does not double-credit. The credit is deferred EFT: it accrues to the clinic's balance account whether or not that org has a Stripe Connect account yet. The path id is the VOUCHER id; there is no separate claim entity. EVERY voucher is paid on its invoice: the PDF of the work done must be STORED, and the payout is the procedure and its supporting costs read off it, capped at the voucher's cap — min(covered amount, maxPayout, else face value). No voucher credits its face value by default. On the automatic path the service WAITS up to about six seconds polling for the AI verdict before answering, and anything not confidently VALID is held for a human with a 409 rather than denied. Supplying `amount` is how a reviewer resolves that hold; it is still capped. THE APPROVAL NAMES THE INVOICE IT WAS DECIDED ON. A clinic may file another invoice while its claim is CLAIMED, so a reviewer sends `expectedInvoiceSha256` — the `receiptSha256` of the voucher they read (`GET /api/vouchers/{id}`) — and the approval is refused, 409, with nothing credited, once another invoice is on file. It is required whenever the voucher's invoice carries a hash: an approval naming none is refused 400 before anything is read from the AI or written. A claim whose invoice was filed before hashes were stored carries none and is approved without one. A repeat of an approved claim credits nothing and names nothing.\n\nThis changes data. The person is asked to confirm it before it runs, and nothing happens if they decline.",
"inputSchema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Voucher id of the claim to approve."
},
"body": {
"type": "string",
"description": "The JSON request body: { amount: integer (Reviewer-approved covered amount in CENTS, for resolving a claim held in manual review.); expectedInvoiceSha256: string (The invoice the reviewer read: the `receiptSha256` of the voucher they approve from, 64...) }"
}
},
"required": [
"id"
]
},
"annotations": {
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": false,
"openWorldHint": false
}
}