[ Introduction ]

Payments and x402

Payment is part of the request. There is no account to create, no key to rotate and no invoice to reconcile: the wallet that signs the payment is the identity, and the answer comes back in the same round trip.

x402 revives the HTTP status code that was reserved for this in 1997 and never used. An unpaid request is answered with the price. A paid one is answered with the resource.

The handshake

  1. 1
    Call the endpoint with no payment

    Send the request you actually want to make. Nothing is charged and nothing is executed.

    shell
    curl -i -X POST https://www.tereno.xyz/api/v1/capabilities/prediction.evidence/invoke \
      -H "Content-Type: application/json" \
      -d '{"question":"Will Ethereum Pectra activate on mainnet before Q4 2026?"}'
  2. 2
    Read the terms from the header

    The server answers 402. The terms are in the payment-required header, not in the body: chain, asset, amount in base units, and the address to pay.

    payment-required (decoded)
    {
      "x402Version": 2,
      "resource": { "url": ".../prediction.evidence/invoke" },
      "accepts": [{
        "scheme":  "exact",
        "network": "eip155:8453",
        "amount":  "50000",
        "asset":   "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "payTo":   "0xfbF218ACCBb0D57fc4E8fc3E2A885C910c4C9e94",
        "maxTimeoutSeconds": 300
      }]
    }
  3. 3
    Sign an EIP-3009 authorization and retry

    Sign a USDC transfer authorization for exactly that amount and attach it as payment-signature. Any x402 client library does this for you; the TypeScript client is on the command line page.

  4. 4
    Payment settles, then the answer is released

    Settlement happens before the response leaves. The confirmation comes back in the payment-response header with the transaction hash.

What you are paying with

Value
Protocolx402, scheme exact, EIP-3009 transferWithAuthorization
ChainBase mainnet, eip155:8453
AssetUSDC, 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
AmountPer call, from $0.001. Set by the capability and its cache tier.
Account neededNone. A funded wallet is the whole onboarding.

Know the price before you sign

The live 402 challenge is always authoritative, but you do not have to trigger one to find out what something costs. Two free reads answer that:

  • GET /api/v1/capabilities lists every capability with its price tiers. Free, no wallet.
  • GET /api/v1/quotes returns a wallet-bound quote: the exact price for you, including any credit you have earned, plus the invoke URL and method.
Prices in prose drift
Any number written into a page, including this one, can fall behind the catalogue. When the two disagree, the catalogue and the live 402 are right and the prose is stale.

Why the same call has two prices

A capability that can be shared charges less when it serves a stored answer. The response always tells you which tier you were charged, so this is never ambiguous after the fact:

json
"pricing":  { "listPriceUsd": 0.05, "pricePaidUsd": 0.01, "currency": "USDC" },
"artifact": { "cacheStatus": "hit", "expiresAt": "2026-09-20T15:50:40.320Z" }

cacheStatus is miss when you paid for fresh work, hit when you were served a stored answer, and partial when only part of the answer could be reused.

One payment, one execution

Idempotency is keyed to the signed payment authorization itself, never to a header a caller can choose. Replaying the same authorization cannot buy a second execution.

  • A retry while the first call is still running returns 409 with alreadySettled: false.
  • A retry after it settled returns 409 with alreadySettled: true and the receipt URL of the execution it bought, so a client that lost the response can still collect what it paid for.
  • A request that fails before the work is done is never charged.

What a receipt proves, and what it does not

Every paid answer carries a deterministic receipt and a content address. Both are reproducible: same inputs, same hashes.

FieldMeans
invocationIdThis specific purchase. Fetch it later at GET /api/v1/receipts/{invocationId}.
artifactIdThe content address of the answer: sha256 over capability, version, normalized input and output.
receipt.hashCommits to the question, the observation time and the capability version.
expiresAtThe moment this answer stops being claimed as current. After it, the answer is history, not a fact.
A receipt is evidence of observation, not of truth
It proves Tereno observed what it says it observed, when it says it did, and that the bytes reproduce the hash. It does not promise the underlying chain state has not changed since. That is what the validity window is for, and why every answer states one.

Free reads around a paid answer

If another agent hands you an artifactId, you can check where it came from without paying and without any relationship to Tereno:

shell
curl -s https://www.tereno.xyz/api/v1/evidence/sha256:1bf295935c1cfca0f107cd193f345b7d...

That returns origin, declared validity and the exact normalized input needed to reproduce the work. It never returns payer identity or the original paid output.