settlement_pending, never as a failure. In the console's authorizations list it shows as UNKNOWN, with its transaction hash, and the dashboard leaves it out of the success rate and the failure reasons until it resolves.| Network | Payment identity |
|---|---|
| EVM (EIP-3009) | Network, scheme, token, authorization.from and authorization.nonce |
| Solana | Network, scheme and the transaction message (signatures excluded) |
signature and authorization, a Solana payment only from transaction, and fields meant for the other network are ignored. Payloads whose fields can't be decoded fall back to the exact payload together with the payment requirements./verify and /settle)| Response | HTTP | Retry-After | What it means | What to do |
|---|---|---|---|---|
Fresh result (no replayed) | 200 or 400 | none | The first evaluation of this payment | Act on it. On a /settle success, record the fulfilment against the payment |
replayed: true and header Idempotent-Replayed: true | 200 or 400 | none | The stored result of an earlier request for the same payment. A replayed /settle success carries the original transaction: no new transfer happened | Treat it as confirming an existing charge. Look the payment up in your own order or fulfilment record and don't deliver twice |
duplicate_request | 409 | 5 | Another request for the same payment is running right now | Retry the same payload after Retry-After |
settlement_pending | 409 | 30 | A transaction was (or may have been) broadcast and its outcome isn't known yet. On /verify, a settle of this payment is unresolved. transaction is included when known | Check transaction on chain. Retry the same payload after Retry-After: a /settle retry checks the chain first. Don't deliver, and don't ask for a new payment meanwhile |
idempotency_conflict | 409 | none | The payment already has a binding outcome with a different payTo or amount | Don't retry automatically. Resend with the original requirements, or have the payer sign a new authorization |
payment_already_settled | 400 | none | /verify of a payment that is already settled (same signature). Includes transaction, and payer when known | Treat the payment as used and check your fulfilment record |
payment_settlement_failed | 400 | none | /verify of a payment whose settlement failed for good: reverted on chain, or expired without landing | Don't deliver. The payer needs a new payment |
payment_proof_mismatch | 400 | none | The payment is known, but this signature isn't the one it was settled, verified or first broadcast with. Nothing is recorded | Treat the request as invalid. Only the original payload gets the stored answer |
claim_unavailable | 503 | 5 | Kobaru couldn't claim the payment (temporary database problem). Nothing was recorded or broadcast | Retry the same payload after Retry-After |
rpc_unavailable, bite_unavailable | 503 | 5, 10 | The network's RPC (EVM) or the SKALE BITE encryption service couldn't be reached. Nothing was broadcast; the attempt isn't stored as a result | Retry the same payload after Retry-After |
/settle success looks like this:{
"success": true,
"transaction": "0x5b0e8f1c7a3d4e2b9f6a1c8d0e7b3a5f2c4d6e8a0b1c3d5e7f9a2b4c6d8e0f1a",
"network": "eip155:8453",
"payer": "0x2c7536E3605D9C16a7a3D7b1898e529396a65c23",
"replayed": true
}replayed: true, so always read success or isValid first.reason | HTTP | Retry-After | What it means |
|---|---|---|---|
duplicate_request, claim_unavailable | 503 | 5 | The payment is busy or couldn't be claimed. Answered before your API is called |
rpc_unavailable, bite_unavailable | 503 | 5, 10 | The network's RPC or the SKALE BITE encryption service is down. Nothing was broadcast; if your API already answered, the use is refunded |
settlement_pending | 503 | 30 | The settlement outcome isn't known yet (transaction when known). The use isn't refunded, and it isn't charged again later |
payment_settlement_failed | 402 | none | The settlement failed for good. The agent must pay again |
payment_expired | 402 | none | The payment is settled, but its quota has lapsed or was never created |
payment_already_used | 402 | none | A single-use payment was already used |
payment_bound_to_other_route | 402 | none | The payment's quota belongs to the first route that used it |
Retry-After and never pays again for it.settlement_pending 503 is resolved before your API is called again. The proxy settles first: if the payment settled, the request is served without consuming a new use; if the outcome is still unknown, the agent gets another 503 and your API isn't called; if the settlement failed for good, the agent gets 402 payment_settlement_failed.duplicate_request. The chain is only called after the claim is committed.settlement_pending. A retry records a failure only when the chain proves a revert or an expiry.from and nonce, so Kobaru also stores a digest of the signature. A copied from+nonce with a forged signature never gets a stored success: /settle rejects the bad signature before anything is recorded, a settled payment answers payment_proof_mismatch, and /verify of an unsettled payment checks the new signature from scratch.insufficient_funds or a failed simulation), isn't replayed. A corrected request is evaluated again. The exception is an expiry on the first attempt: that payment can never execute, so its failure is final.settlement_pending. One rare EVM case stays pending even on retry: an authorization used by a transaction Kobaru doesn't know (for example after a transport error during the send). That case waits for the reconciliation job; contact support with the transaction and time if it persists.PAYMENT-RESPONSE marked pending: true instead of waiting. They never broadcast, so there is no double charge. If that settlement then fails for good, those uses were served unpaid. The exposure is bounded: at most limit − 1 extra uses for pay-per-request, or about 65 seconds of a pay-per-time window.payment-identifier extension isn't supported yet. A client that loses a response and signs a new authorization creates a new payment. Retrying with the original payload is always safe; signing again is not.settlement_pending (the chain says it was already used) until Kobaru reconciles it; it was paid once and is never charged twice. Don't retry it; contact support with the original transaction if you need it confirmed.| Kobaru | Coinbase CDP x402 /settle | x402 payment-identifier | Client-supplied keys (Stripe Idempotency-Key, CDP X-Idempotency-Key) | |
|---|---|---|---|---|
| Who supplies the key | Nobody: derived from the on-chain authorization | No idempotency header documented for /settle | The client: an id of 16–128 characters (letters, digits, -, _); optional or required, per server | The client. Stripe: up to 255 characters, V4 UUID suggested. CDP: must be a UUID v4 |
| How long protection lasts | No expiry | Not documented | A server-chosen cache TTL (examples range from 5 minutes to 24 hours; one sample uses 1 hour). After it, the same id is processed again | Stripe: keys can be pruned once at least 24 hours old, and a reused key is then a new request. CDP: unique within a rolling 24 hours |
| Retry of a settled payment | Stored success, same transaction, replayed: true and Idempotent-Replayed: true | Not documented. The error list includes duplicate_settlement and invalid_exact_evm_nonce_already_used without saying when they apply | Cached response, payment skipped (within the TTL) | The stored status and body. Stripe replays even a 500 |
| Same identity, different terms | 409 idempotency_conflict once the payment is bound | Not documented | 409 Conflict on a different fingerprint (scheme, network, asset, amount, payTo, and optionally path, method or order id) | Error on different parameters (Stripe) or a different payload (CDP) |
| In-flight duplicate | 409 duplicate_request with Retry-After; a database lock lets only one request broadcast | Not documented | Not documented | Stripe: treated as a conflict and safe to retry. CDP: an error saying the key is still processing |
| Unknown on-chain outcome | 409 settlement_pending with transaction when known; your retry checks the chain and returns the real outcome when it can | settlement_pending with the tx hash, "for the caller to reconcile before retrying" | Not documented | Not chain-aware: the first response is replayed as-is |
| Signature re-encoding and forged proofs | Re-encodings map to the same payment; a stored success is only returned to the same signature | Not documented | Not documented | Not addressed: the key the client sends, not the payload, identifies the request |
| Proxy quota binding | Quota bound to the payment and to the first route that uses it | N/A | N/A | N/A |
/settle.settlement_pending with the hash instead of a failure. Kobaru also resolves it against the chain on your retry; CDP's documentation leaves reconciliation to the caller.from+nonce with a forged signature never receives a stored success.payment-identifier can recognize a client that signs a fresh authorization after losing a response. Kobaru plans to support it.from and nonce on EVM, or the transaction returned by /settle (it's the same on every replay).replayed: true, look the payment up before delivering.Retry-After on duplicate_request, settlement_pending, claim_unavailable, rpc_unavailable and bite_unavailable, and retry with the same payload.idempotency_conflict or payment_proof_mismatch.settlement_pending, check transaction on chain. Don't deliver and don't ask the payer to pay again until you know the outcome./verifyRetry-After and advice