nouliVerify a receipt ↗
Instructions for the record

Read it.
Check it. Keep it.

nouli is the external witness for AI agents: instant, verifiable Proof of Existence. Agents are the only actors in the economy that can’t testify for themselves — a record that survives them can. Bind data to a public beacon, get back a signed, hash-chained receipt anyone can check without sending it back to nouli.

What you’re holding

A receipt is a JSON document signed with Ed25519. It records a random output, its cited entropy sources, a time of issue, and the hash of the previous receipt. The record is tamper-evident and time-bound: it proves this existed at or before the cited beacon round, and was not rewritten since. It cannot prove the record is complete — whoever writes a journal can omit an entry; the chain makes gaps visible, not impossible.

receipt_id
The unique identifier of this record.
endpoint
The product that issued it: receipt, flip, or anchor.
issued_at
The recorded time of the mix, in UTC.
output
The value, its encoding, and byte length. For the free example: 32 bytes, encoded as base64.
sources
Ordered contributions: OS entropy (digest only), drand quicknet (round and signature), and, for anchors, caller bytes (digest only).
prev_receipt
The SHA-256 digest of the previous receipt. This binds adjacent records into a chain.
signature
The Ed25519 signature and the key_id naming the published signing key.
payment
Present for paid receipts. An x402 record cites a settlement; a prepaid record cites a ledger debit, not an independently verified on-chain payment.

Download a real receipt ↓

Three checks. Separate evidence.

  1. Signature

    Verify the canonical receipt body against nouli’s published Ed25519 keys. A passing signature establishes that the signed content has not changed.

  2. Beacon

    Verify the cited quicknet round’s BLS signature against the embedded public key, then cross-check the round and beacon information with the public drand API. If the API is unreachable, the local cryptographic check can still pass, but the live comparison is marked unavailable.

  3. Chain

    Recompute predecessor hashes from adjacent receipts you supply. One receipt alone cannot prove a missing link or its global chain position. “Not checked” is not a pass or a failure.

Check the real example ↗

On the command line

curl -s https://nouli.dev/v1/receipt -o receipt.json
curl -s https://nouli.dev/.well-known/nouli-keys.json -o keys.json
npx nouli-verify receipt.json --keys keys.json

In a browser, zero setup: nouli.dev/verify — paste the receipt JSON, drop the file, or open a verification link; the checks run entirely in your browser and nothing you paste is uploaded.

Verification checks the record and its beacon citation. The secret OS entropy and the mix cannot be independently reconstructed from digest-only citations. A signed timestamp is an issuer’s attestation, not a separate proof of when caller data first existed.

Ask for a receipt

No signup is needed for the free tier. Use the server’s payment requirements as authoritative for paid requests.

GET /v1/receipt

32 bytes of randomness with a receipt. Free within the per-IP allowance (30 per minute, 300 per day); $0.02 via x402 above that allowance.

GET /v1/chain/head

The public chain surface: the one digest that commits to the whole chain. Free, read-only, never cached — watching it over time makes retroactive rewriting detectable by anyone. Pair with GET /v1/receipt/{id}: any stored receipt by its id, served exactly as issued.

GET /v1/flip

The impartial tie-breaker that comes with proof: a fair bit no stakeholder can accuse you of rigging — and the receipt IS the proof of fairness. Paid, $0.02 per call.

POST /v1/anchor

Proof of Existence: mix in your own bytes — “this existed, at or before this point.” Paid, $0.05 per call. Send application/octet-stream, at most 1,024 bytes. Hash larger data first; only a digest of the contribution appears in the receipt.

Paid calls return HTTP 402 with a Payment-Required header. An x402 client pays and retries with payment-signature. Failed settlement means no charge and no receipt. Inspect cited settlements separately; this browser verifier does not confirm payments.

Payment is per call, direct, and accountless: the current deployment settles on Base mainnet (eip155:8453) in native USDC, with nouli as its own x402 facilitator (relayed in-process). Treat the 402's requirements as the truth for network, asset, and amount, never these docs. There are no refunds; a failed settlement charges nobody and serves no receipt.

The HTTP tools are also available through POST /mcp (three tools mirroring these endpoints, prices and caps included). Optional prepaid access and its claim flow are documented in AGENTS.md.

Genuine, with a caveat

Degraded does not mean false.

A receipt marked status: "degraded" cites a beacon round older than the 60-second freshness bound at mix time. The status and reason are signed. If verification passes, it is genuine but stale; freshness is not correctness.

The free allowance is 30 receipts per minute and 300 per day, per IP (the daily count persists across restarts). Paid calls are capped at 60 per minute and 4 concurrent per IP, shared. A 429 response includes Retry-After; capped requests do not charge.

If something does not check out

  • Failed: the supplied evidence disagrees. Do not rely on the receipt until resolved.
  • Unavailable: a required resource could not be reached. Retry with a connection; no successful check is implied.
  • Not checked: evidence such as an adjacent receipt was not supplied.

Prohibited use

don't use nouli to break the law or anyone's rules that apply to you: no unlawful gambling or lotteries, no sanctions evasion, no money laundering, no market manipulation, and no attacking this service itself — no hammering it with requests you don't intend to pay for, and no circumventing the per-IP caps. You are responsible for what you do with the outputs. On the default lane nouli keeps no accounts and no personal data; caps are per IP address; payment settles directly on-chain. The opt-in prepaid lane is the documented exception: its ledger keeps your wallet address, tx hashes, amounts, and timestamps — nothing else; deposited funds sit with the operator.

Errors — what each code means

Every non-200 answer is the same envelope: { "error", "docs_url", "detail" }. error is a code from this list, docs_url points here, and detail is a plain-language sentence. Nothing but the receipt itself is ever a 200.

payment_required
You hit a paid call without paying — HTTP 402. The Payment-Required header has the requirements; pay and retry (see AGENTS.md).
payment_invalid
The payment you sent did not match the requirements — wrong amount, reused, or already settled. Fetch a fresh 402 and pay that; you were not charged.
rate_limited
You exceeded a cap (free or paid). Wait the Retry-After seconds and retry; capped requests never charge.
insufficient_balance
Your prepaid API key's account has less than the call's price — HTTP 402, no debit taken. Top up with a new deposit and claim it, or pay the same request per call with x402 (the Payment-Required header on this response).
unknown_key
The API key credential is missing or not recognized. Send Authorization: Bearer noul_… with a valid key.
facilitator_unavailable
The x402 facilitator is unreachable or cannot price the route. Nothing can be charged; retry shortly.
settlement_failed
Settlement was attempted and failed after one retry. No charge, no receipt — retry with a fresh payment.
drand_unavailable
The randomness beacon is unreachable and no round is known yet (a cold box only) — try again shortly.
core_unavailable
The receipt core behind the gateway is unreachable — retry shortly. On a paid call that settled, the box's operators have been notified by the logs.
payload_too_large
An anchor body over 1,024 bytes — hash larger data yourself (sha256) and anchor the 32-byte digest. Rejected before any payment.
invalid_request
The request body did not arrive complete. Retry.
claim_invalid_message
The claim's signed message is not one this box will honor — wrong domain, wrong chain id, missing fields, or the statement does not bind the deposit tx hash. Rebuild the message per AGENTS.md and sign it again.
claim_expired
The signed message's Issued At is outside the 5-minute window (or it carries an expired Expiration Time) — send a fresh claim.
claim_payer_mismatch
The signature does not prove the claiming wallet sent this deposit. Claims are 1:1: a deposit funds exactly the wallet that sent it.
claim_tx_unverified
The deposit could not be verified on-chain — not confirmed yet, reverted, not a plain USDC transfer to this box's deposit address, or below the $25.00 per-claim minimum. Wait for the transfer to confirm and claim again.
claim_rpc_unavailable
The box cannot read the chain right now to verify the deposit — nothing was credited; retry shortly.
claim_duplicate
This deposit tx was already claimed — the key was issued once at the original claim and is never re-issued. If you lost that key, the operator can revoke it after a new deposit.
not_found
Unknown path — the 404's detail lists what this box serves.
internal_error
Something broke on the box. Retry; if it repeats, it's the operator's problem, not yours.

The precise reference

Use the live OpenAPI contract for schemas and errors, AGENTS.md for payment and prepaid examples, and llms.txt for discovery. The agent card provides machine-readable capabilities.

Use the outputs lawfully. No unlawful gambling, sanctions evasion, money laundering, market manipulation, abuse, or circumvention of rate limits.

Endpoint behavior, prices, and limits follow the published service documentation. The live API response is authoritative.