- Rate limiting — per-route or per-surface caps on how often a client can call.
- Request guardrails — strict input validation on every route before any upstream call or settlement.
- Replay protection — rejects reused payment authorizations and SIWX sessions.
Rate limits
Limits applied on the live deployment:| Scope | Limit | Keyed by |
|---|---|---|
Unpaid 402 challenges | 120 / min | Client IP |
| Solana RPC routes | 50 rps | Per provider:cluster:surface scope |
| Solana DAS routes | 10 rps | Per provider:cluster:surface scope |
| Tokens API routes | 30 rpm | Across the shared upstream API key (configurable) |
429 Too Many Requests with JSON:
Request guardrails
The gateway rejects overly broad or malformed requests before settlement or any upstream call. Key guardrails:Solana RPC
getBalance,getAccountInfo,getTransaction— accept exactly 1 or 2 params. First param must be a non-empty string.getAccountInfo— ifdataSliceis provided,length <= 1024.getSignaturesForAddress—limit(if provided) must be1..100.getTokenAccountsByOwner— the filter must specify exactly one ofmintorprogramId.getProgramAccounts— requires at least onedataSizeormemcmpfilter (max 4), requires adataSlicewithlength <= 256, andmemcmp.bytes <= 128characters.
Solana DAS
getAsset—params.idrequired, non-empty string.getAssetsByOwner—ownerAddressrequired,limit <= 100.searchAssets—limit <= 100,page <= 10 000.
Tokens API
search—qrequired,limit <= 50.resolve— exactly one ofreformint.curated—listmust be one of the documented values;groupBy(if provided) must beassetormint.market-snapshots—mints+addressescombined must be1..250items.variant-markets—mints+addressescombined must be1..50.variant-top-markets—limit <= 100.tickers/markets—limit <= 50,offset <= 10 000.- OHLCV routes —
intervalmust be one of1m, 5m, 15m, 1H, 4H, 1D, 1W;from <= to. - Asset-level paths —
assetIdpath param must be non-empty.
400 Bad Request with a structured error body and does not trigger settlement.
Replay protection
x402 exact payments
Every paid payment authorization is hashed and stored in Redis. Submitting the same PAYMENT-SIGNATURE twice returns 400 with an error — the second call cannot be settled again. This is enforced before the upstream call.
SIWX sessions
Each SIWX signature is stored with a short TTL. A given signature cannot authorize two different requests. The TTL is tied toexpirationSeconds: 300 in the challenge envelope, so a SIWX signature is only valid within five minutes of being signed.
Bazaar discovery behavior
The CDP Bazaar crawler probes routes with an empty request body to discover schemas. To keep paid routes discoverable, body validation happens after the initial challenge is issued for empty unpaid probes. Paid paths still return402 Payment Required on a bare probe — they never leak upstream data without payment.
Once a paid request carries a PAYMENT-SIGNATURE, strict input validation runs before settlement.
Structured event logs
Every incoming request emits a structured event to stdout (collected by Vercel logs). Event fields include:event— e.g.paid_request_ok,paid_request_upstream_error,siwx_request_ok.requestIdroutePath,cluster,provider,surface,methodwallet(when authenticated)paymentNetwork,paymentAsset,priceUsdhttpStatus,upstreamLatencyMs

