Your client sends a paid request for a report. The connection times out. Did the payment fail, did the upstream service fail, or did everything finish except delivery of the response?
A timeout cannot answer that question. Automatically authorizing another payment turns a transport failure into a possible duplicate charge.
For an x402 pay-per-call API, the useful default is to recover the original operation before creating another paid operation.
Payment success is not request success
Keep payment state separate from fulfillment state. Verification checks whether a payment payload meets the payment requirements. Settlement concerns the movement of funds. Neither proves that your upstream API produced the report or that the buyer received it.
The official facilitator documentation distinguishes verification from settlement. Its settlement recovery behavior also depends on the mechanism and implementation. It is not a guarantee that your upstream operation executes exactly once.
My recommended gateway design keeps two durable records linked by an operation ID. One tracks payment authorization, settlement evidence, and unresolved outcomes. The other tracks upstream execution and the stored result. A settled payment with failed fulfillment needs recovery or a documented refund policy, not another checkout.
One logical operation, one identifier
Generate an identifier before the first paid attempt and persist it across retries and client restarts.
x402's optional payment-identifier extension supports deduplication when the server advertises it. The documentation recommends binding the identifier to a request fingerprint and returning 409 Conflict when that fingerprint changes. The identifier alone is not an exactly-once guarantee.
For a gateway, I would bind the operation record and its receipt to:
- The verified payer identity and merchant or tenant.
- The HTTP method, path, relevant query parameters, and a canonical request-body hash.
- The payment scheme, network, asset, amount, and recipient.
- The payment identifier and any known settlement transaction reference.
Authenticate recovery requests against that payer or another explicitly authorized identity. An identifier or public transaction hash must not become a bearer credential for downloading someone else's report. A settlement receipt needs the gateway's application record to establish which request it paid for.
Handle concurrent retries before calling upstream
A response cache helps only after a result exists. Two simultaneous retries can both miss the cache.
My recommendation is to reserve the operation atomically in shared durable storage before settlement or upstream execution. Matching retries read the existing state. They receive the stored result when complete, or an explicit pending response while work continues. Conflicting requests fail rather than silently buying something different.
Pass the operation ID upstream as an idempotency key where supported. If the upstream service offers neither deduplication nor a status lookup, a crash after execution but before recording the result leaves an ambiguity. Do not promise exactly-once fulfillment across that boundary.
Recovery is a separate path
The official client/server retry guidance says that after sending PAYMENT-SIGNATURE, clients should treat a missing response as an unknown payment outcome. settlement_pending is non-terminal, not permission to pay again.
Use the transaction and network from PAYMENT-RESPONSE to reconcile when available. Without them, use the provider's lookup or support process. x402 does not define a universal settlement-status endpoint.
I would expose an authenticated operation-status endpoint, retain settlement evidence beyond response-cache expiry, and stop automatic charging while the outcome remains unknown. Cache expiry is a storage event, not evidence of payment failure. Test lost responses, concurrent retries, and crashes between settlement and result persistence before trusting this policy.
These are application-design recommendations, not claims of official Cardano support. Network support needs a compatible payment mechanism and facilitator implementation.
midday.day is an early prototype and demand test for a proposed x402 pay-per-call API gateway on Cardano, not production payment processing. If you sell APIs and need this kind of retry policy, join the midday.day waitlist to help shape this early exploration.
Top comments (0)