Integrate18

x402 payments

CompliR has no API keys; a request pays for itself. The first call answers 402 with what to sign, the client signs a USDC authorization, retries, and CompliR verifies and settles it through Circle's facilitator on Arc before returning the verdict. Nothing is charged when the handler fails; nothing settled is ever silently kept.

The 402 flow

text
client                              CompliR                                 Circle facilitator (Arc)
  │  POST /api/v1/screen                │                                        │
  │ ───────────────────────────────────►│                                        │
  │  402 + PAYMENT-REQUIRED             │                                        │
  │ ◄───────────────────────────────────│                                        │
  │  sign EIP-3009 TransferWithAuthorization (USDC, 0.01) with the payer key      │
  │  POST again + PAYMENT-SIGNATURE     │                                        │
  │ ───────────────────────────────────►│  /verify ────────────────────────────► │
  │                                     │ ◄──────────────────────── isValid      │
  │                                     │  run the handler (screen)              │
  │                                     │  /settle (payment-identifier = nonce) ►│
  │                                     │ ◄──────────────── transaction, payer   │
  │  200 + PAYMENT-RESPONSE + verdict   │                                        │
  │ ◄───────────────────────────────────│                                        │
json
// 402 body and PAYMENT-REQUIRED (base64 of the same object)
{
  "x402Version": 2,
  "error": "PAYMENT-SIGNATURE header is required",
  "resource": { "url": "https://trycomplir.xyz/api/v1/screen", "description": "CompliR screen: one address", "mimeType": "application/json" },
  "accepts": [{
    "scheme": "exact", "network": "eip155:5042", "amount": "10000",            // 0.01 USDC in 6-dp atomic units
    "asset": "0x3600000000000000000000000000000000000000", "payTo": "0x…",    // X402_PAY_TO (the Circle revenue wallet)
    "maxTimeoutSeconds": 60,
    "extra": { "assetTransferMethod": "eip3009", "name": "USDC", "version": "2" }  // EIP-712 domain of USDC on Arc
  }]
}

Protocol: x402 v2 (x402Version: 2), scheme exact on eip155:5042, transfer method eip3009. The CompliR SDK and MCP server implement the client side; the header and status reference is on HTTP API.

What the server guarantees

  • Fail closed. Any verify or settle problem answers 402 or 502 and the handler's body is never leaked.
  • Handler first, then settle (default): a failing or refusing handler is never charged. settleFirst is used only where the side effect must not happen unpaid (the tip stake); anything that fails after that settlement is auto-refunded.
  • Idempotent per nonce for 5 minutes. A retry after a settled payment replays the cached response without a second settle; a retry after settlement_pending re-settles without re-running the handler; concurrent duplicates share one in-flight attempt.
  • Requirements are re-checked against the signed payload: scheme, network, asset, payTo, amount, authorization.to, authorization.value, validAfter and validBefore. Signing for less than the current price is rejected before anything runs.
  • One payment per authorization on Circle too: the settle call carries the payment-identifier extension derived from the EIP-3009 nonce (complir_<nonce>), so a client retry converges on one payment.
  • Pending settlements are polled up to 3 times (X402_PENDING_POLLS) via the facilitator's status endpoint before the client is asked to retry with the same authorization.

Facilitator and config

X402_DISABLED
1 today (every call free, X-CompliR-Payment: disabled). Set 0 to charge.
X402_FACILITATOR_URL
https://api.circle.com/v1/facilitator/x402 (Circle Facilitator Service, Arc native)
X402_FACILITATOR_API_KEY
Circle Console key → Authorization: Bearer; required for production settle
X402_SELLER_PRIVATE_KEY
alternative keyless trial: Facilitator-Seller-Proof signed by the X402_PAY_TO key
X402_PAY_TO
where USDC lands - the Circle revenue wallet once provisioned
X402_NETWORK
CAIP-2; defaults to eip155:$ARC_CHAIN_ID
X402_ASSET_NAME / _VERSION
EIP-712 domain of the token, default USDC / 2
PRICE_SCREEN_USDC / PRICE_WATCH_USDC
config defaults 0.01 / 0.05; the operator may move them inside its bounds

The same-origin free rule

Requests whose browser sends Sec-Fetch-Site: same-origin bypass x402 on /api/v1/screen, /api/v1/watch and /api/v1/tips. That is what keeps the hosted Explorer, Shadow and Tips pages free to use: they are thin views over the same handlers. An API client, a curl from another host or an agent never sends that header and always pays (unless X402_DISABLED=1). Screens made this way are recorded under the internal client id web-explorer and never count as traction.

Gateway-batched x402 (Circle Nanopayments) is not implemented: it would fit the buyer side of the tip stake, but the SDK is not installed and Arc settlement here goes through the standard facilitator.