Build
Receipts and verification.
Every request returns a receipt. Follow it to its settlement and check it against the public log.
On this page
Every request returns a receipt: what was billed, at which price, and where it settles.
The same receipt appears in five places:
- The JSON body, as
receipt. - A stream's last comment line,
: receipt {…}. - The
x-request-idheader, with the cost inx-cost-unitson a response that is not streamed. A chat or text completion paid per request carriesreceipt.paidinstead. GET /v1/receipts/{id}, with the key that made the request.- The MCP
receipttool.
The receipt on a response
"receipt": {
"request_id": "<request_id>",
"model": "<model>",
"provider": "<provider>",
"status": "ok",
"usage": { "prompt_tokens": …, "completion_tokens": …, "cached_tokens": … },
"price": { "version": "<price sheet>", "input": …, "output": … },
"cost": { "units": "<units>", "usd": "<usd>", "usdf": "<usdf>" },
"balance": { "units": "<units>", "usd": "<usd>", "usdf": "<usdf>" },
"data_policy": { … },
"settlement": {
"status": "unsettled",
"next_batch_after": "<time>",
"lookup": "https://api.usdf.fi/v1/receipts/<request_id>"
}
}Looked up later, the receipt adds when it was made and its place in the usage log:
Look up a receipt
curl https://api.usdf.fi/v1/receipts/<request_id> \ -H "Authorization: Bearer $USDF_API_KEY"
Response
{
"request_id": "<request_id>",
"model": "<model>",
"provider": "<provider>",
"status": "ok",
"created_at": "<time>",
"usage": { "prompt_tokens": …, "completion_tokens": …, "cached_tokens": … },
"price_version": "<price sheet>",
"cost": { "units": "<units>", "usd": "<usd>", "usdf": "<usdf>" },
"settlement": { "status": "unsettled", "next_batch_after": "<time>" },
"log": {
"leaf_index": …, "tree_size": …, "status": "published",
"anchored_by": null,
"proof": "https://api.usdf.fi/v1/log/proof/<request_id>"
}
}Every field:
| Field | Meaning |
|---|---|
request_id | The request's id. Also the response id. |
model | The model, without any routing suffix. |
provider | The route that served it. |
status | ok, partial, or failed_refunded with a reason: upstream_error, upstream_timeout, empty_output, gateway_shutdown or gateway_error. |
usage | The provider's token counts. |
price, price_version | The sheet version and the rates charged. A lookup names the version. |
cost | What was charged, as { units, usd, usdf }. |
balance | On a response: the balance after the charge. |
data_policy | What the serving route does with content, and what was asked. |
settlement | status and next_batch_after; once settled, batch, tx_hash, explorer and rows. |
log | On a lookup: leaf_index, tree_size, status, anchored_by and the proof URL. |
A partial receipt was cut short and is billed for what was produced. A failed_refunded one costs zero.
A request paid per request carries the payment too:
paid: the quote, which is what was charged;usage_cost: what the request used.payment:tx,explorer,payer,amount,assetandmethod.settlement.scheme:x402 exact, ormpp evm charge, with thenetwork.- On non-chat endpoints,
modality,endpointandbilled, pluslookup.
The receipt of any request, keyed or paid per request, is public with no key. It publishes nothing the log does not.
Read a public receipt
curl https://api.usdf.fi/x402/v1/receipts/<request_id>
A USDG payment, or a refund, has settlement none: its own payment transaction is the on-chain record. A USDF payment is burned in a later settlement batch with the rest of the spend.
GET /v1/receipts lists the latest receipts, newest first, with limit, before, model and status.
A key lists its own requests. A session lists the account's. Naming another key gets 403 key_scope.
List and read receipts
curl "https://api.usdf.fi/v1/receipts?limit=20" \ -H "Authorization: Bearer $USDF_API_KEY" curl https://api.usdf.fi/v1/receipts/<request_id> \ -H "Authorization: Bearer $USDF_API_KEY"
Response, trimmed
{
"data": [
{
"request_id": "<request_id>",
"created_at": "<time>",
"model": "<model>",
"cost": { … },
"status": "ok",
"settlement": { "status": "unsettled", … },
"receipt": "https://api.usdf.fi/v1/receipts/<request_id>"
}
],
"page": { "next_before": "<before>" }
}Spend settles on-chain in batches. A receipt's settlement.status moves through these states:
| Status | Meaning |
|---|---|
unsettled | Charged in the ledger. The spent USDF is still in the gateway's custody. |
pending | In a batch that has opened. |
sent | The batch's transaction is broadcast. |
confirmed | Mined. The USDF was burned and the same USDG paid out. |
A batch runs hourly, or sooner once 50 USDF unsettled has built up. Its transaction burns the batch's spent USDF, releases the same USDG to the revenue wallet, and carries the batch digest and a log checkpoint in its calldata.
A settled receipt, settlement only
"settlement": {
"batch": "<batch>",
"status": "confirmed",
"tx_hash": "<transaction hash>",
"explorer": "…",
"rows": "https://api.usdf.fi/v1/settlements/<batch>"
}GET /v1/settlements lists batches. GET /v1/settlements/{batch} lists every row in one, with recomputed_digest and digest_matches, so anyone can check that the digest on-chain commits to exactly those requests.
Every request, keyed or paid per request, is a leaf in an RFC 6962 Merkle log. Its roots are anchored on-chain by the settlement transactions.
| Endpoint | Returns |
|---|---|
GET /v1/log/checkpoints | The roots anchored on-chain. |
GET /v1/log/proof/{id} | A request's leaf and its inclusion proof. |
GET /v1/log/consistency | A consistency proof between two tree sizes, from and to. |
GET /v1/log/frontier | The tree's current frontier. |
GET /v1/log/leaves | The leaves themselves. |
Check a request in the log
curl https://api.usdf.fi/v1/log/proof/<request_id> curl https://api.usdf.fi/v1/log/checkpoints
The log publishes figures, never content. See Data handling.
Three more public reads let anyone check the money:
| Endpoint | Returns |
|---|---|
GET /v1/audit/costs | Every charge recomputed from public inputs: the usage and the archived price sheet. |
GET /v1/flows | Every USDF and USDG movement the gateway claims, with its transaction. |
GET /v1/reserve | The reserve, the supply and the gateway's custody, read from the chain. |
Verify runs these checks in your browser against the chain. Transparency shows the same figures live.
A private-tier request is tied to the provider's own signed receipt. Its data_policy.attestation starts pending, then turns verified or failed.
GET /v1/privacy/receipts/{id}, with the same key, returns the provider's archived receipt byte for byte, with its hash. See Private inference.