直接回答

这页说明团队如何使用 NextModel 的 OpenAI 兼容网关。 From per-request billing headers to cryptographic receipts anchored on Base — how to prove what happened, not take it on faith. 这一页会补充接入步骤、配置重点和常见问题。

Three levels of proof

A response can be checked at increasing strength. First, every response carries billing headers: X-NextModel-Billing-Status (settled, rolled_back, or not_charged), X-NextModel-Reservation-Id, and X-NextModel-Failure-Class. These are the gateway's own word about the request — useful inline, and enough to assert that failures never billed. Second, each billable request produces a structured receipt: a canonical JSON record of what was served and what it cost. Third, receipts are anchored — hashed into Merkle batches, the batch manifests written to retention-locked write-once storage, and each batch root anchored on the Base blockchain — so a receipt can be checked independently of the gateway. The headers are convenient; the receipt is evidence.

What a receipt contains

A receipt is deliberately small: enough to reconstruct what happened, never the conversation.

receipt_idStable identifier for the usage record
request_idGateway request identifier
org_public_idYour account as acct_… — no raw account id in public receipts
requested_model / effective_modelThe id you asked for and the id that actually served
served_modeHow the response was produced (fresh_upstream)
usage_sourceprovider_actual, local_estimated, or cache_replayed
billing_basisfresh_public_price, discounted_cache_price, or byok_management_fee
charged_amount / fresh_equivalent_amountWhat was billed and what the uncached equivalent would have cost
created_atWhen the request completed

Verify a receipt programmatically

POST the three receipt identifiers to the verification endpoint. Verification authenticates with your nextmodel.app dashboard session rather than an API key, and the endpoint lives on the website origin, not the API base URL. A signed-in owner sees the charged amount; an anonymous caller can still verify the hash and anchoring but the charged amount is redacted; a signed-in account that does not own the receipt is refused.

Verify
curl -s https://nextmodel.app/v1/receipts/verify \
  -H "Content-Type: application/json" \
  -d '{"receipt_id": "<receipt_id>", "receipt_hash": "<receipt_hash>", "request_id": "<request_id>"}'

Verification outcomes

A 200 response returns the receipt's model and serving facts plus its anchoring statuses (archive_status, anchor_status) and any public anchor events. Everything else is one of:

400 receipt_input_requiredOne of receipt_id, receipt_hash, request_id is missing
403 receipt_forbiddenReceipt belongs to a different signed-in account
404 receipt_not_foundNo receipt with that id in the verification window
409 receipt_hash_mismatchThe receipt hash does not match the anchored record — tamper evidence
409 receipt_request_id_mismatchThe request id does not match the receipt

No-code paths and what mismatch means

The receipt verifier tool at /tools/receipt-verifier accepts the same three values in a form, and the public verifiable-receipts page at /verifiable shows live anchoring status. A hash mismatch is the strong guarantee: receipts are hashed at creation and committed into Merkle batches, so a mismatch means the record changed after issuance — that is the signal auditors act on. For the full anchoring pipeline, see the AI provenance doc.