Skip to main content
Aegis uses the x402 protocol for all paid endpoints. No API keys, no OAuth — every paid call is a tiny on-chain USDC transfer authorized by the caller, settled by Coinbase’s facilitator service.

The flow

The quote

When you hit a paid endpoint without payment, the server replies:
HTTP/2 402 Payment Required
content-type: application/json
payment-required: <base64-encoded JSON>

{}
Decoded payment-required:
{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "https://x402.aegis-kyt.com/screen/eth/0x6b17…",
    "description": "Per-source labels + Aegis consensus risk score in one call.",
    "mimeType": ""
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "asset":   "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "amount":  "100000",
      "payTo":   "0x6d0A788caC92d83FB827CDfb07C0D111e97Acfb6",
      "maxTimeoutSeconds": 300,
      "extra":   { "name": "USDC", "version": "2" }
    }
  ]
}
FieldMeaning
schemeAlways exact — pay the precise amount, no upto/up-to-N variants
networkCAIP-2 chain ID. eip155:8453 = Base mainnet · eip155:84532 = Base Sepolia
assetUSDC contract on the named chain
amountCost in USDC base units (6 decimals). 100000 = $0.10
payToWallet that collects the payment
maxTimeoutSecondsAfter this many seconds the quote can’t be settled
extraEIP-712 name + version for the USDC contract — feed into your signer

The proof

You sign a EIP-3009 TransferWithAuthorization typed-data structure with your private key:
{
  "types": {
    "EIP712Domain": [
      { "name": "name",    "type": "string"  },
      { "name": "version", "type": "string"  },
      { "name": "chainId", "type": "uint256" },
      { "name": "verifyingContract", "type": "address" }
    ],
    "TransferWithAuthorization": [
      { "name": "from",        "type": "address" },
      { "name": "to",          "type": "address" },
      { "name": "value",       "type": "uint256" },
      { "name": "validAfter",  "type": "uint256" },
      { "name": "validBefore", "type": "uint256" },
      { "name": "nonce",       "type": "bytes32" }
    ]
  },
  "domain":      { "name": "USDC", "version": "2", "chainId": 84532, "verifyingContract": "0x036CbD53…" },
  "primaryType": "TransferWithAuthorization",
  "message": {
    "from":        "<your address>",
    "to":          "0x6d0A788caC92d83FB827CDfb07C0D111e97Acfb6",
    "value":       "100000",
    "validAfter":  0,
    "validBefore": 9999999999,
    "nonce":       "0x" + 32-random-bytes-hex
  }
}
Encode the signed payload as the X-PAYMENT request header (base64 of the full PaymentPayload JSON — see the Coinbase x402 SDK for the precise shape).

Replay protection

The nonce field is your replay-protection key. Aegis writes one row to x402_payments per verified proof, with a UNIQUE(payer, nonce) constraint. A re-sent X-PAYMENT header gets rejected with 402. Generate a fresh nonce per request (e.g. os.urandom(32).hex()).

Settlement

The facilitator (default: https://x402.org/facilitator, hosted by Coinbase) calls USDC.transferWithAuthorization(…) on your behalf. The transaction lands on Base; the resulting tx_hash is recorded in our audit log and you can verify it on Basescan (or sepolia.basescan.org for testnet).

Networks

Today Aegis settles on Base only. Multi-chain settlement (Polygon, Arbitrum) is on the roadmap — see Networks.

Errors

StatusMeaning
402Missing / invalid / expired / replayed proof. Header payment-required carries a fresh quote
400Malformed {address} or {chain} path parameter
429Rate-limited (60 paid calls/min per IP)
5xxAegis-side failure — payment was settled, but our backend errored. See error codes
A 5xx after a successful settle is unusual but possible. We log every such case to our audit channel; if you see one, contact support.