x402 Endpoints
402 payload schema
What this does: defines the minimum payload a protected endpoint should return.
{
"x402Version": 1,
"resourceId": "0x...",
"accepts": [
{
"scheme": "exact:evm:permit2",
"schemeId": "0x...",
"network": "bnbTestnet",
"asset": "0x...",
"amount": "1000000",
"reference": "api-credit-001",
"router": {
"address": "0x...",
"intent": {
"paymentId": "0x...",
"merchant": "0x...",
"token": "0x...",
"amount": "1000000",
"deadline": 1731763200,
"payer": "0x0000000000000000000000000000000000000000",
"resourceId": "0x...",
"referenceHash": "0x...",
"nonce": "0x..."
}
}
}
]
}
Expected result: clients have all fields needed to sign and execute a valid payment.
Header expectations
- Client receives
402 Payment Required. - Client executes one accepted payment route.
- Client retries request with payment authorization header.
Default profile header:
X-PAYMENT-AUTHORIZATION: <serialized-payment-proof>
How to verify and unlock resource
What this does: verifies submitted authorization against settlement state.
import { createApiClient } from '@pepay/x402flex';
const api = createApiClient({ baseUrl: 'https://api.bnbpay.org' });
async function verifyAndUnlock(paymentId: string) {
const payment = await api.payments.get(paymentId);
if (!payment?.paymentId) {
throw new Error('payment_not_settled');
}
return {
ok: true,
paymentId: payment.paymentId,
resourceId: payment.resourceId,
};
}
Expected result: endpoint returns protected resource only after verified settlement.
Error handling patterns (invalid signature, stale intent, mismatch)
- Invalid signature:
- Symptom: payment rejected by router/relay.
- Fix: re-create witness typed data from the exact intent.
- Stale intent:
- Symptom: deadline exceeded.
- Fix: regenerate challenge with fresh deadline.
- Reference mismatch:
- Symptom: settlement not correlated.
- Fix: recompute
referenceHashfrom final reference string.
- Session mismatch:
- Symptom: session spend revert.
- Fix: ensure session-tagged reference and current epoch/spend nonce.