> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aegis-kyt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 protocol

> How payment-gated access actually works on the wire.

Aegis uses the [x402 protocol](https://www.x402.org/) 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

```mermaid theme={null}
sequenceDiagram
    participant Agent
    participant API as x402.aegis-kyt.com
    participant Facilitator as facilitator (Coinbase)
    participant Base as Base RPC

    Agent->>API: GET /screen/eth/0x6b17…
    API-->>Agent: HTTP 402 + payment-required quote
    Note right of Agent: Sign EIP-3009 transferAuthorization
    Agent->>API: GET /screen/eth/0x6b17… + X-PAYMENT
    API->>Facilitator: verify + settle the proof
    Facilitator->>Base: USDC transferWithAuthorization(…)
    Base-->>Facilitator: tx receipt
    Facilitator-->>API: settled (tx_hash)
    API-->>Agent: HTTP 200 + JSON
```

## The quote

When you hit a paid endpoint without payment, the server replies:

```http theme={null}
HTTP/2 402 Payment Required
content-type: application/json
payment-required: <base64-encoded JSON>

{}
```

Decoded `payment-required`:

```json theme={null}
{
  "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" }
    }
  ]
}
```

| Field               | Meaning                                                                        |
| ------------------- | ------------------------------------------------------------------------------ |
| `scheme`            | Always `exact` — pay the precise amount, no upto/up-to-N variants              |
| `network`           | CAIP-2 chain ID.  `eip155:8453` = Base mainnet · `eip155:84532` = Base Sepolia |
| `asset`             | USDC contract on the named chain                                               |
| `amount`            | Cost in USDC base units (6 decimals).  `100000` = `$0.10`                      |
| `payTo`             | Wallet that collects the payment                                               |
| `maxTimeoutSeconds` | After this many seconds the quote can't be settled                             |
| `extra`             | EIP-712 `name` + `version` for the USDC contract — feed into your signer       |

## The proof

You sign a [EIP-3009 `TransferWithAuthorization`](https://eips.ethereum.org/EIPS/eip-3009)
typed-data structure with your private key:

```json theme={null}
{
  "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](https://github.com/coinbase/x402) 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](https://basescan.org/) (or
[sepolia.basescan.org](https://sepolia.basescan.org/) for testnet).

## Networks

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

## Errors

| Status | Meaning                                                                                                       |
| ------ | ------------------------------------------------------------------------------------------------------------- |
| `402`  | Missing / invalid / expired / replayed proof.  Header `payment-required` carries a fresh quote                |
| `400`  | Malformed `{address}` or `{chain}` path parameter                                                             |
| `429`  | Rate-limited (60 paid calls/min per IP)                                                                       |
| `5xx`  | Aegis-side failure — payment was settled, but our backend errored.  See [error codes](/reference/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](mailto:support@aegis-kyt.com).
