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.
Three checks. Separate evidence.
Signature
Verify the canonical receipt body against nouli’s published Ed25519 keys. A passing signature establishes that the signed content has not changed.
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.
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.
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.jsonIn 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/receipt32 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/headThe 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/flipThe 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/anchorProof 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.