Add structured decline/failure context for payments #815
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Abstract
Extend x402 with optional intent traces so clients can explain why they decline to pay and servers can return structured context when verification/settlement fails. Adds an
intent_traceobject (reason_code, trace_summary, metadata, optional remediation) to decline messages and failure responses, with transport bindings for HTTP headers, A2A metadata, and MCP_meta.Motivation
Today a declined or failed x402 payment is a dead end: clients stay silent or servers return terse codes (e.g.,
insufficient_funds) with no signal about budget, network, or timing constraints. This forces guesswork in pricing and UX. Structured intent traces turn non-payments into actionable signals: a decline withprice_sensitivityortiming_deferredtells the server whether to counter-offer now or follow up later; a failure trace withsignature_expiredplus remediation hints lets clients retry successfully.Why structured and bidirectional?
Specification
PaymentDeclinemay includeintent_trace.VerifyResponseandSettleResponsemay includeintent_traceand optionalremediation.price_sensitivity,budget_exceeded,wrong_network,wrong_asset,insufficient_balance,untrusted_facilitator,untrusted_recipient,timing_deferred,comparison,rate_limit_concern,gas_cost_concern,authorization_denied,other.insufficient_funds,signature_invalid,signature_expired,signature_not_yet_valid,amount_mismatch,recipient_mismatch,nonce_already_used,network_mismatch,asset_mismatch,transaction_reverted,transaction_timeout,facilitator_error,smart_wallet_error,other.metadata: flat object; values are string/number/boolean only; no arrays/nested objects.remediation: optional action hint (e.g.,top_up,retry_with_fresh_authorization,switch_network).reason_codevalues and treat them asother(forward compatibility).PAYMENT-DECLINEheader (base64url PaymentDecline JSON); server may returnX-PAYMENT-INTENT-TRACEwith failure context.x402.payment.status,x402.payment.intent_trace._metablock underx402/paymentwithdeclineandintent_trace.Privacy
trace_summary; secrets (keys, auth) must never be included.Files Changed
x402/specs/rfc-intent-traces.md— Spec, examples, transports, conformance, and validator guidance.go/http/client.go,go/http/client_test.go,go/http/server.go,go/types.go— Header encode/decode, decline handling, types.java/src/main/java/.../IntentTrace.java,PaymentDecline.java,Remediation.java,SettlementResponse.java,VerificationResponse.java,SettlementResponseHeader.java,PaymentFilter.java— Types plus HTTP filter wiring.python/x402/src/x402/encoding.py,middleware.py,types.py,tests/test_encoding.py— Header helpers, middleware, types, tests.typescript/packages/core/src/index.ts,typescript/packages/core/src/http/x402HTTPResourceServer.ts,typescript/packages/mechanisms/evm/src/exact/facilitator.ts— Exports, HTTP resource server handling, facilitator intent trace helpers.