Skip to main content
The PayAI facilitator applies per-client rate limits at its edge, and bounds how long a /settle request will wait for an on-chain outcome before answering. This page documents both behaviors so you can build clients that handle them correctly.

Batch channel admission

Solana batch settlement has additional limits on sponsored channels and deposit attempts. The public /supported response publishes them in batchPolicy. Authenticated requests share the quota across an account’s API keys. Anonymous requests use a deterministic merchant bucket derived from the Solana receiving address and also have a 10 deposit-attempts/minute/IP anti-abuse limit. A full merchant or service-wide channel quota returns 429 with Retry-After; reuse an existing funded channel or complete its cleanup. Claims, distribution, recovery, and closure remain available during an admission pause.

Per-IP rate limits

The facilitator’s edge (nginx ingress) uses separate rate-limit buckets for each endpoint group. The production configuration reviewed on September 13, 2026 sets the following per-client-IP, per-ingress-replica limits. These are configured admission limits, not a measured settlement-throughput guarantee: The controller’s default burst multiplier is 5; do not rely on bursts as sustained capacity. Effective allowance depends on replica routing, and requests can also hit connection or application limits. The controller can return 429 or 503 for edge limiting depending on configuration; a status alone does not identify the source. See the ingress rate-limit semantics. The common verify-then-settle pattern consumes one request from each bucket. Separate buckets do not isolate shared compute or database capacity. These edge limits also do not replace the account-wide batch limits above. Contact PayAI before planning sustained volume near a limit; do not rotate IPs to evade limits.
If you expect sustained single-IP volume near the /settle budget, get in touch to review workload, connection use and available capacity before rollout.
Reuse connections. Keep-alive and HTTP/2 are both supported at the edge; a client that opens a fresh TLS connection per request pays an extra round trip on every call and consumes its concurrent-connection budget far faster than a pooled client.

Read the status and response body together

HTTP status alone does not establish whether a payment was submitted or settled. Keep the response body, original payment payload and any transaction identifier. PayAI’s settlement recovery uses the original operation identity. Keep its payload, requirements, signed receipts and transaction identifiers in durable storage. Recovery records have bounded, scheme-dependent retention; the facilitator is not permanent receipt storage. For channel operations, use the batch recovery procedure.

The settlement_pending response

POST /settle waits for the on-chain outcome, but only up to a bounded response budget (currently 100 seconds). If the settlement is still in flight when the budget expires — for example during network congestion — the facilitator answers instead of letting the connection time out. The response wait budget applies across Solana and EVM settlement paths. Keep the original operation identity when reconciling, but follow the selected scheme’s recovery rules: ordinary exact payments and batch channel operations do not have identical state or retention. Whether transaction can be populated is covered below.
Key properties of this response:
  • It arrives with HTTP 200, so standard x402 clients surface it in the normal !success path. Other policy or validation failures can use non-2xx responses.
  • It is not a verdict. The settlement job keeps running after the response is sent — the payment may still land on-chain. Do not treat settlement_pending as a failure, and do not treat it as a success.

How to reconcile: re-submit the identical payload

To learn the real outcome, re-POST the exact same payload (the same payment payload and payment requirements) to /settle:
  1. While the original attempt is still in flight, you normally receive 409 duplicate_settlement. A reconciliation request can also wait and return another settlement_pending response; continue with backoff.
  2. Once the attempt resolves, the facilitator serves the recorded outcome: the cached success response (including the transaction hash) if the payment landed, or the recorded failure if it did not.
Reconcile promptly without changing the payment authorization or channel operation. If the recovery record is no longer available, use your retained transaction/receipt evidence and chain state before deciding whether a new payment is appropriate. Do not interpret an expired record as proof of failure.

Solana vs EVM: whether transaction is populated

The transaction field of a settlement_pending response differs by chain family:
  • Solana — transaction can be empty when the API wait budget expires before the worker returns a signature. Batch recovery responses may include the recorded signature when available. Keep it if present and re-submit the identical payload to reconcile the specific operation.
  • EVM (Base, Polygon, Arbitrum, Avalanche, Sei) — if the transaction was already broadcast when the budget expired, transaction carries the broadcast hash. You can watch that hash on-chain directly, in addition to (or instead of) polling /settle.
On EVM, a populated transaction means the transaction was broadcast, not that it landed. Wait for confirmation on-chain, or poll /settle for the recorded outcome.

Client-side timeouts

Some x402 client libraries default to shorter timeouts than the facilitator’s response budget; check your pinned SDK version and client configuration. A client-side timeout gives you no settlement verdict: the request may not have arrived, or settlement may still be in flight. Preserve the original operation and follow its recovery procedure instead of assuming payment failed.

Need help?

Join our Community

Have questions or want to connect with other developers? Join our Discord server.