x402Flex Overview
x402Flex mirrors Coinbase's 402 protocol while anchoring every accept option to X402FlexRouter metadata. Agents, wallets, and humans all see the same deterministic payload, so settlement logic remains identical.
Why X402Flex
Want the short, persuasive positioning? Read Why X402Flex.
HTTP 402 Payload
- Client requests a protected resource (
POST /api/x402/introspect). - Server responds with
402 Payment Requiredand JSON body describing acceptable payment paths.
{
"x402Version": 1,
"resourceId": "0xf296...",
"accepts": [
{
"scheme": "exact:evm:permit2",
"network": "bnb",
"asset": "0x55d398326f99059fF775485246999027B3197955",
"amount": "1000000",
"router": {
"address": "0xRouter",
"intent": {
"paymentId": "0x...",
"resourceId": "0x...",
"referenceHash": "0x...",
"nonce": "0x...",
"deadline": 1731763200
},
"referenceData": "api:credits:134"
}
}
],
"metadata": {
"merchant": "Pepay Labs",
"memo": "x402 gating"
}
}
- Wallet/agent picks an accept option, executes the router call (
payWithPermit2, push, AA, etc.). - Merchant verifies the resulting
PaymentSettledV2via SDK or indexer and retries the original request with authorization headers.
referenceHashis computed from the final reference string (session tags included).nonceis mandatory per invoice; it is part of thepaymentIdbinding.
Facilitator Toolkit (@pepaylabs/x402flex)
import express from 'express';
import { createFlexMiddleware, createFlexExpressMiddleware } from '@pepaylabs/x402flex';
import { createFlexIntent, buildFlexResponse } from '@pepaylabs/bnbpay';
const flex = createFlexMiddleware({
merchant: process.env.MERCHANT!,
networks: {
bnb: {
provider: BNB_PROVIDER,
registry: process.env.BNB_REGISTRY!,
router: process.env.BNB_ROUTER!,
chainId: 56,
confirmations: 3,
},
opbnb: {
provider: OPNB_PROVIDER,
registry: process.env.OPBNB_REGISTRY!,
router: process.env.OPBNB_ROUTER!,
chainId: 204,
confirmations: 1,
},
},
});
const app = express();
app.use('/api/generate', createFlexExpressMiddleware(flex, {
'/api/generate': {
buildResponse: async () => {
const intent = createFlexIntent({
merchant: process.env.MERCHANT!,
token: process.env.USDT!,
amount: 1_000_000n,
chainId: 56,
referenceId: 'api.generate',
scheme: 'exact:evm:permit2',
});
return buildFlexResponse({
intent,
network: 'bnb',
router: process.env.BNB_ROUTER!,
metadata: { memo: 'API credit' },
});
},
onAuthorized: async (_req, settlement) => {
console.info('Authorized', settlement.paymentId, settlement.referenceData);
},
},
}));
buildResponseis called on every 402 challenge; bake in rate limits or variable pricing.onAuthorizedreceives the decodedPaymentSettledV2object once confirmations land.- Use
referenceDatato encode CRM IDs, invoice IDs, or agent handles.
Scheme Catalog
| Scheme String | SchemeId | Notes |
|---|---|---|
push:evm:direct | 0x2914a5ad49430794a41289b127686141b95eb37498f4abd184b28a0b69808b12 | Native/token push via router helpers. |
push:evm:aa4337 | 0x38535c5fa3d21dae45dbc4b490c7b97d00903f89c8785b145dd204d4670a4807 | AA4337 UserOp push payments. |
exact:evm:permit2 | 0xc07338ac3a63d5933e6a5b2184602e306eb7c25700866301b635132c811546f1 | Permit2 witness signature transfer. |
exact:evm:eip2612 | 0x9429a5bd2d856a1fb737472aa76f02e1be1b968a1f4eb757c60cb7f042e6a4d9 | ERC-2612 permit + transferFrom. |
exact:evm:eip3009 | 0x7b76f402569ceb571fa538a410383abd8186ad7e6043c5687c2ac19717b3c535 | USDC-style pull payments. |
Retrieve IDs programmatically with getFlexSchemeId('exact:evm:permit2').
EIP-3009 nonce rule: authNonce must be derived from the intent hash + router + chainId:
keccak256(abi.encodePacked("X402Flex", intentHash, router, chainId)).
Open Flex Spec Alignment
Pepay Labs publishes the entire x402Flex spec + implementation so builders can audit every assumption. Cross-reference the repo artifacts below when extending flows:
| Capability | Spec Reference | Implementation |
|---|---|---|
| HTTP 402 envelope fields, status codes, and error semantics | docs/X402_FLEX_SPEC.md §§3-5 | packages/x402flex (createFlexMiddleware, createFlexExpressMiddleware) |
Router-only settlement + PaymentSettledV2 resource IDs | docs/ROUTER_MIGRATION.md | contracts/payments, packages/sdk-ts/src/x402.ts |
| Agent-to-agent intents + MCP toolchains | docs/X402_FLEX_SPEC.md §8, updates.md "MCP Server" entries | /mcp-server + docs on this page |
| Scheme catalog & deterministic hashing | docs/X402_FLEX_SPEC.md Appendix A | @pepaylabs/bnbpay helpers (getFlexSchemeId, createFlexIntent) |
Because every component above is open source, wallets can fork the middleware, swap signing backends, or extend schemes without waiting on Pepay Labs. Keep updates.md up to date whenever a new scheme ships so partners can diff spec vs. implementation quickly.
Agent-to-Agent x402 Payment
Autonomous agents can both issue and satisfy HTTP 402 challenges—useful for paywalled APIs or when Claude/Codex agents exchange compute.
import { decodePaymentSettledEvent } from '@pepaylabs/bnbpay';
// Agent A (provider) issues a challenge
const response = await issue402Challenge();
// Agent B (payer) uses the MCP tool exposed by /mcp-server
const receipt = await mcpClient.invoke('handle_402_response', {
paymentInfo: response.body,
senderPrivateKey: process.env.AGENT_PRIVATE_KEY!,
preferredChain: 'opbnb',
});
const settlement = decodePaymentSettledEvent(receipt.settlementLog);
await notifyPeer({ paymentId: settlement.paymentId, reference: settlement.referenceData });
- Embed the agent identifier inside
referenceData(e.g.,agent:claude:design-review) so both parties reconcile quickly. - Agents should persist
paymentId+resourceIdlocally, then pass them back through MCP to prove completion.
Claude/Codex MCP Wiring
- Build the MCP server inside
/mcp-server(npm install && npm run build). - Add the server to Claude Code or Anthropic Codex configuration:
{
"mcpServers": {
"bnbpay": {
"command": "node",
"args": ["./mcp-server/dist/index.js"],
"env": {
"BNB_RPC_URL": "https://bsc-dataseed.binance.org/",
"BNB_PAYMENT_REGISTRY": "0x1fAa1B7445ed1B3120451cC3F8f2230CB172602f",
"BNB_PAY_ROUTER": "0xRouter",
"DEFAULT_CHAIN": "bnb"
}
}
}
}
- Restart Claude Code/Codex so the new MCP server loads. The
create_402_payment,handle_402_response, andverify_paymenttools become available and mirror the snippets above.
MCP Tie-In
create_402_payment→ Build HTTP payloads identical tobuildFlexResponse.handle_402_response→ Executes permit, push, or AA flow and streams the resulting settlement log.get_payment_status→ Confirms thePaymentSettledV2emission and returns scheme + fee data for downstream agents.
Ensure your MCP deployment uses the same contract addresses surfaced on the documentation homepage so agents and humans remain on a single source of truth.