ODATANOODATANOAPIpreprod
x402

Buy a key with tADA

A key or a top-up is paid on Cardano, in one HTTP round trip. No account, no sign-in: the payment is the credential.

How it works

  • 1Ask for the price. POST /keys without a payment answers 402. The body lists one accepts entry per pack: the amount in lovelace, the address to pay to, the network.
  • 2Pay on Cardano. Your client sends that amount to the pay-to address. The transaction spends one of your UTxOs as a nonce, which makes the payment single-use.
  • 3Repeat the call with the proof. The signed transaction travels base64-encoded in the PAYMENT-SIGNATURE header of the same request.
  • 4Get the key. The gateway hands the envelope to its facilitator, which submits the transaction and waits for it on chain. The response is 201 with the key, the pack's calls and the validity.
http# 1. price
POST https://api.preprod.odatano.dev/keys?pack=500
→ 402  { "x402Version": 2, "accepts": [ {
           "scheme": "exact", "network": "cardano:preprod",
           "amount": "5000000", "payTo": "addr_test1…",
           "extra": { "units": 500 } } ] }

# 3. same call, with the signed payment
POST https://api.preprod.odatano.dev/keys?pack=500
PAYMENT-SIGNATURE: <base64 envelope>
→ 201  { "token": "oda_…", "units": 500, "validUntil": "…" }

Packs

CallsPriceAmountNamed pack
  • Network
  • Validitya bought key is valid for from the purchase
  • Choosing?pack=<calls> names the pack. Without it the gateway settles against the largest pack the payment covers.
  • Price per callevery forwarded call costs 1, metadata and the verify lane are free

Top-ups

  • With the keyPOST /topup with Authorization: Bearer oda_…, same 402 round trip
  • By key idPOST /topup?key=<id>, no secret needed; the id is on the account page
  • By addressPOST /topup?address=<stake address> reaches the key bound to that address. A key bought with tADA is bound to the paying address on the spot.
  • Replaya spent nonce is refused by the facilitator, a known transaction hash by the gateway (409)
httpPOST https://api.preprod.odatano.dev/topup?key=<id>&pack=500
PAYMENT-SIGNATURE: <base64 envelope>
→ 200  { "unitsAdded": 500, "unitsLeft": 1000 }

Client

  • Packages@x402/fetch + @x402/cardano on npm, the official x402 client: wrapFetchWithPayment does the 402 round trip, the Cardano scheme builds and signs the payment from your wallet
  • Protocolx402 v2, scheme exact on Cardano, asset lovelace; the 402 carries the requirements in the PAYMENT-REQUIRED header and in the body
  • Walleta mnemonic for the reference signer, or any ClientCardanoSigner (a CIP-30 wallet fits); it needs the pack amount plus the fee on the network above
  • Sourcegithub.com/x402-foundation/x402, package typescript/packages/mechanisms/cardano
  • Also works@odatano/x402's x402Fetch (github.com/ODATANO/x402), the library behind the gateway's facilitator
jsimport { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { toClientCardanoSigner } from '@x402/cardano';
import { ExactCardanoScheme } from '@x402/cardano/exact/client';

// the reference signer: a mnemonic plus a Koios or Blockfrost provider
const signer = toClientCardanoSigner({ mnemonic, network: 'cardano:preprod', provider: { koios: { baseUrl: 'https://preprod.koios.rest/api/v1' } } });
const client = x402Client.fromConfig({ schemes: [{ network: 'cardano:*', client: new ExactCardanoScheme(signer) }], spendControls: false });   // lovelace is not a default asset
const fetchPaid = wrapFetchWithPayment(fetch, client);
const res = await fetchPaid('https://api.preprod.odatano.dev/keys?pack=500', { method: 'POST' });
const { token } = await res.json();   // oda_…