post_claims_by_id_approve

Changes data · you confirm first

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

ArgumentTypeDescription
idpathstring (uuid)requiredVoucher id of the claim to approve.
bodyJSONobjectThe request body, as a JSON object. Its fields are listed below.

Fields of body

FieldTypeDescription
amountintegerReviewer-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.
expectedInvoiceSha256string | nullThe 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.

json
{
  "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"
      }
    }
  }
}
Confirmation
The client shows the person the exact request and waits. Nothing runs until they tick Make this change. See Reading and changing.

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.

json
{
  "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

FieldTypeDescription
accountIdstring (uuid) | null
amountintegerAmount credited in CENTS.
creditedbooleanFalse on an idempotent repeat, where the claim was already approved and no second credit was written.
currencystring
eventobject
event.aggregateIdstring
event.aggregateTypestring
event.eventIdstring
event.eventTypestring
event.timestampnumber
newBalanceinteger | nullThe clinic's balance after the credit, in CENTS.
orgIdstring (uuid) | nullThe clinic credited.
statestringThe voucher's state after approval.
transactionIdstring (uuid) | null
voucherIdstring (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.

400

amount is negative or not a number; expectedInvoiceSha256 is 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.

403

Authenticated, but the caller holds none of the required permissions.

404

No such resource — or none this caller may see.

409

The 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.

json
{
  "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
  }
}