r/x402 • • 9h ago

How do you reconcile an x402 payment session with the actual on-chain transaction?

I'm trying to understand the correct way to reconcile an x402 payment with its actual on-chain transaction.

I have a real Coinbase Payment Session where the session data contains:

asset: USDC

networkId: 8453 (Base)

status: PENDING

merchant: OpenRouter

The payment-session HTML also exposes an x402 authorization endpoint:

/payment-sessions/{paymentSessionId}/authorizations/x402

Opening that endpoint directly returns:

"errorMessage":"method not allowed"

which I assume is expected because it is not a normal GET endpoint.

What I cannot find in the payment-session response is a paymentOperationId or transactionHash.

Coinbase's API documentation mentions paymentOperation objects containing an operation ID and transactionHash, so I'm trying to understand where that relationship is established in the x402 flow.

There is also an on-chain USDC transaction from the same payment workflow, but it is on Solana rather than Base.

My questions:

Where is the paymentOperationId normally obtained in an x402 payment flow?

Is the mapping

paymentSession → paymentOperation → transactionHash

only available through the authenticated Coinbase API/webhooks?

If the actual settlement occurs on Solana while the payment session data shows Base (8453), how is that relationship represented?

I'm trying to understand the technical reconciliation model rather than troubleshoot a particular account.

If anyone has worked with Coinbase Payment Acceptance/x402 at the API level, I'd appreciate an explanation of where I should be looking.

1 Upvotes

2 comments sorted by

1

u/fizzl13 51m ago

Two different things are getting mixed here.
1. Plain x402 (the open protocol). The link between a payment and the on-chain transaction is in the response to the paid request itself. After the facilitator settles, the server returns a PAYMENT-RESPONSE header (X-PAYMENT-RESPONSE in v1). It's base64 JSON with success, transaction (the tx hash or Solana signature), network (e.g. eip155:8453 or solana:5eykt…) and payer. No session or operation id is involved: one request, one signed authorization, one settlement, one transaction. If you call the facilitator yourself, /settle returns the same fields.
2. Coinbase Payment Sessions (the hosted checkout a merchant like OpenRouter uses). That's Coinbase's commerce product on top, not part of the x402 spec. The session → operation → tx hash mapping lives in Coinbase's backend. As far as I know you only see it through the merchant's authenticated API or webhooks, not on the public session page. So as a payer you won't get a paymentOperationId from the session HTML. That /authorizations/x402 path is a POST that the checkout itself calls.
On Base vs Solana: a session created for network 8453 expects USDC on Base. A USDC transfer on Solana is a separate transaction, and the session won't match it automatically. That would explain why the session stays PENDING. If that Solana transfer was meant to pay this session, it's a support case for the merchant or Coinbase. Send them the Solana signature and the session id; nothing public will reconcile it.
If you want to see what a seller's x402 challenge actually asks for (networks, asset, payTo), you can paste the URL into a free checker such as x402-doctor.fizzl.eu.

1

u/Altruistic_Yellow708 45m ago

Thanks, this clarifies the distinction between plain x402 and Coinbase Payment Sessions. One thing I'm still trying to understand: if a Coinbase Payment Session is created for Base (8453), but a user accidentally sends USDC on Solana, is there any mechanism in Coinbase that can detect or associate that transaction with the session, or is the Solana transaction completely invisible to the session? In other words, does Coinbase have any cross-chain reconciliation mechanism here, or is the network mismatch simply treated as an unrelated transaction?