Developer guide · x402 v2
Payments your apps
and agents can understand.
Create an invoice, share a checkout link or settle through x402, and track the result. One workflow for people, applications, and AI agents.
01 · Get started
Your first invoice
your-username below with your own username or wallet address.Create
A shareable invoice with a fixed amount.
Pay
A wallet checkout or x402 authorization.
Confirm
A settled transaction and payment record.
curl --request POST "https://x402invoices.com/api/invoices" \
--header "Authorization: Bearer $X402INVOICES_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: order-1042" \
--data '{
"payTo": "your-username",
"networks": ["base", "arbitrum", "solana"],
"amount": "25.00",
"token": "USDC",
"metadata": { "orderId": "order-1042" }
}'The receiving wallet must belong to the authenticated account. A multi-network USDC invoice needs a compatible receiving address for each network.
201 Created
{
"invoiceId": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://x402invoices.com/inv/550e8400-e29b-41d4-a716-446655440000",
"payToWallet": "0xYourReceivingWallet",
"expiresAt": null
}02 · Account access
One identity. Scoped access.
curl "https://x402invoices.com/api/invoices" \
--header "Authorization: Bearer $X402INVOICES_API_KEY"Choose the access your integration needs
invoices:readfor reporting and invoice lookup.invoices:createto create invoices andinvoices:cancelto cancel them.profile:readandprofile:writefor profile and receiving wallets.payments:submitfor explicitly confirmed, wallet-signed MCP payments.- Copy a newly created key once, keep it in server environment variables, and revoke it when an integration is retired.
03 · Reference
The invoice API
/api/invoicesCreate an invoice with invoices:create access.
/api/invoicesList your invoices with pagination and filters.
/api/invoices/{id}Read invoice detail with invoices:read access.
/api/invoices/{id}Cancel an unpaid invoice with invoices:cancel access.
/api/invoices/{id}/statusPublic payment status; a valid owner key adds account detail.
/api/invoices/exportExport your filtered invoices as a CSV file.
| Field | Type | Use |
|---|---|---|
| payTo | string | Your wallet address or registered username. |
| networks | string[] | base, arbitrum, solana for USDC; ela-pg for BTCD when supported. |
| amount | string | A positive decimal amount, such as 25.00. Use token precision. |
| token | string | USDC (6 decimals), or BTCD (18 decimals) on ELA-PG. |
| expiresAt | string · optional | A future ISO 8601 timestamp. |
| webhookUrl | string · optional | A public HTTPS endpoint that receives payment events. |
| webhookSecret | string · optional | A 32–128 character signing secret; generated if omitted with webhookUrl. |
| metadata | object · optional | Your order reference and additional invoice context. |
List and export filters: view=created|received, status=pending|processing|paid|expired|cancelled, and search. Lists also accept page and pageSize.
Retry without creating another invoice
Supply Idempotency-Key when creating an invoice. Reuse the same key and request body if the connection fails. A key reused with different input is rejected.
curl --request PATCH "https://x402invoices.com/api/invoices/INVOICE_ID" --header "Authorization: Bearer $X402INVOICES_API_KEY"Token and network combinations
USDC invoices accept Base, Arbitrum, and Solana. BTCD invoices accept ELA-PG only. Each requested network must be supported by the configured facilitator and have a compatible receiving wallet.
{
"payTo": "your-username",
"networks": [
"ela-pg"
],
"amount": "0.05",
"token": "BTCD"
}04 · x402 v2
A standard payment handshake
/inv/{id} for a wallet checkout. An agent can pay the same invoice through /api/x402/{id} using the exact payment scheme.Request an invoice
GET /api/x402/{id}The payer asks for the invoice without a payment header.
Read the requirements
402 + PAYMENT-REQUIREDDecode the base64 JSON requirements and choose an accepted network.
Authorize in a wallet
GET + PAYMENT-SIGNATURESign the exact payment requirements, then retry with the base64 payload.
Confirm settlement
200 + PAYMENT-RESPONSEThe server verifies and settles the payment, then records the receipt.
curl --include "https://x402invoices.com/api/x402/INVOICE_ID"
# 402 Payment Required
# PAYMENT-REQUIRED: <base64-encoded PaymentRequired JSON>
# Decode with the x402 SDK and authorize the selected accepts[] entry.
curl --include "https://x402invoices.com/api/x402/INVOICE_ID" \
--header "PAYMENT-SIGNATURE: $SIGNED_PAYMENT_PAYLOAD"Requirements are the source of truth
Quotes use x402Version: 2, CAIP-2 network identifiers, and atomic-unit amount strings. EVM wallets sign the token’s typed authorization; Solana wallets sign a transaction using the facilitator fee payer supplied in the quote. Only offered networks are payable. Use the official SDK to build and encode your payload.
If a payment is processing or its settlement result is uncertain, check invoice status before starting another payment. A signed payload alone doesn’t mean the invoice is paid.
Official x402 HTTP specification{
"x402Version": 2,
"resource": {
"url": "https://x402invoices.com/api/x402/INVOICE_ID",
"description": "Invoice INVOICE_ID",
"mimeType": "application/json"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "25000000",
"payTo": "<invoice receiving address>",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
]
}05 · Completion
Track the result, not just the signature.
paid and store the returned transaction reference before fulfilling your order.curl "https://x402invoices.com/api/invoices/INVOICE_ID/status"
# Treat pending and processing as unresolved.
# paid is a confirmed settlement.
# expired and cancelled are terminal unpaid states.{
"status": "paid",
"settled": true,
"paymentState": "settled",
"paymentError": null,
"paidAt": "2026-10-01T08:00:00.000Z",
"txHash": "0x…",
"paidNetwork": "base",
"paidToAddress": "0xReceivingWallet",
"paidBy": "0xPayerWallet"
}Signed webhooks
Set webhookUrl when creating an invoice to receive a payment callback. Save the webhookSecret from the authenticated creation response, or supply your own 32–128 character secret. The secret belongs to that invoice.
Verify the X-X402-Signature header against the raw request body before processing the event. Reject timestamps outside a five-minute window, deduplicate X-X402-Delivery IDs, and return a successful HTTP response promptly. Retryable delivery failures are attempted up to three times.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyWebhook(rawBody, signatureHeader, invoiceSecret) {
const fields = Object.fromEntries(
(signatureHeader || "").split(",").map(part => part.split("="))
);
if (!/^\d+$/.test(fields.t || "")) return false;
if (!/^[0-9a-f]{64}$/.test(fields.v1 || "")) return false;
const timestamp = Number(fields.t);
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = createHmac("sha256", invoiceSecret)
.update(`${timestamp}.${rawBody}`)
.digest();
const received = Buffer.from(fields.v1, "hex");
return received.length === expected.length &&
timingSafeEqual(received, expected);
}
// Read the body as text before parsing JSON.
// Look up the saved secret for the invoice, then verify.
// Independently confirm paid status before fulfillment.{
"invoiceId": "550e8400-e29b-41d4-a716-446655440000",
"status": "paid",
"txHash": "0x…",
"paidAt": "2026-10-01T08:00:00.000Z",
"paidNetwork": "base",
"paidBy": "0xPayerWallet",
"amount": "25",
"token": "USDC"
}| 400 | Check input, token precision, address format, and network combination. |
|---|---|
| 401 / 403 | Check API key validity, scopes, or wallet session. |
| 402 | Payment is required or a supplied payment authorization was rejected. |
| 409 | An idempotency conflict or a concurrent payment needs your attention. |
| 503 | A required facilitator or service is temporarily unavailable. Check status before retrying payment. |
06 · Model Context Protocol
Give your agent a payment workspace.
/api/mcp with a scoped API key. Your agent can manage invoices and read payment quotes; your wallet authorizes any payment.[mcp_servers.x402invoices]
url = "https://x402invoices.com/api/mcp"
bearer_token_env_var = "X402INVOICES_API_KEY"Configure a secret environment variable
Set X402INVOICES_API_KEY in the environment that launches your MCP client. Restart the client after changing its configuration. Don’t paste a key into a prompt, a shared config file, or browser code.
Invoice management
invoice_list · invoice_create · invoice_get · invoice_cancel · invoice_summary
Create, find, and cancel invoices within your account’s scopes.
Payment tools
invoice_payment_quote · invoice_payment_status · invoice_submit_payment
Read requirements and submit an explicitly confirmed, wallet-signed payload.
Payment authorization stays with the payer
Invoice API keys manage records; they don’t hold your private key. A payment tool requires a signed payload and explicit confirmation. Review the network, token, amount, and receiving address before signing.
Plugin and discovery
The source repository includes an MCP plugin in plugins/x402invoices-mcp with a local stdio bridge and setup instructions. Clients that support remote HTTP can use the configuration above directly.
The endpoint supports modern stateless MCP and compatible legacy clients through the official SDK. MCP specification update.