Context
The x402 V2 spec includes a Payment-Identifier extension that enables idempotency — clients can safely retry requests without duplicate payment processing.
Problem
Currently, if a client creates an escrow and the retry request fails (network error, timeout), the client has no way to retry with the same payment. Creating a new escrow would double-pay. The escrow deadline will eventually refund, but that's slow.
Required behavior
The client includes a Payment-Identifier in the payment payload. The server/facilitator uses this to:
- Detect duplicate settlement attempts for the same payment
- Return the cached result instead of re-settling
For Hathor, the ncId (nano contract ID) naturally serves as a payment identifier — each escrow has a unique ID. But the spec wants an explicit identifier field.
Changes needed
Resource server
- Cache settlement results by
ncId or Payment-Identifier
- On duplicate requests with the same identifier, return the cached resource instead of re-verifying
Facilitator
- Track settled
ncIds to prevent duplicate release() calls
- Return cached settlement result for already-settled escrows
Client / dApp
- On retry after failure, reuse the same
ncId instead of creating a new escrow
References
Context
The x402 V2 spec includes a Payment-Identifier extension that enables idempotency — clients can safely retry requests without duplicate payment processing.
Problem
Currently, if a client creates an escrow and the retry request fails (network error, timeout), the client has no way to retry with the same payment. Creating a new escrow would double-pay. The escrow deadline will eventually refund, but that's slow.
Required behavior
The client includes a
Payment-Identifierin the payment payload. The server/facilitator uses this to:For Hathor, the
ncId(nano contract ID) naturally serves as a payment identifier — each escrow has a unique ID. But the spec wants an explicit identifier field.Changes needed
Resource server
ncIdorPayment-IdentifierFacilitator
ncIds to prevent duplicaterelease()callsClient / dApp
ncIdinstead of creating a new escrowReferences