x402invoices.

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

Sign in with an EVM or Solana wallet, configure your receiving addresses, and create an API key in settings. Replace your-username below with your own username or wallet address.
01

Create

A shareable invoice with a fixed amount.

02

Pay

A wallet checkout or x402 authorization.

03

Confirm

A settled transaction and payment record.

POST https://x402invoices.com/api/invoices
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

Example response
{
  "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.

Browser actions use your signed wallet session. Server applications and MCP clients authenticate with a Bearer API key created in settings. The payment endpoint remains available to payers without a merchant API key.
Authenticated request
curl "https://x402invoices.com/api/invoices" \
  --header "Authorization: Bearer $X402INVOICES_API_KEY"

Choose the access your integration needs

  • invoices:read for reporting and invoice lookup.
  • invoices:create to create invoices and invoices:cancel to cancel them.
  • profile:read and profile:write for profile and receiving wallets.
  • payments:submit for 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

Amounts are decimal strings. Network recipients are resolved when the invoice is created; later wallet setting changes apply to new invoices.
POST/api/invoices

Create an invoice with invoices:create access.

GET/api/invoices

List your invoices with pagination and filters.

GET/api/invoices/{id}

Read invoice detail with invoices:read access.

PATCH/api/invoices/{id}

Cancel an unpaid invoice with invoices:cancel access.

GET/api/invoices/{id}/status

Public payment status; a valid owner key adds account detail.

GET/api/invoices/export

Export your filtered invoices as a CSV file.

Create invoice fields
FieldTypeUse
payTostringYour wallet address or registered username.
networksstring[]base, arbitrum, solana for USDC; ela-pg for BTCD when supported.
amountstringA positive decimal amount, such as 25.00. Use token precision.
tokenstringUSDC (6 decimals), or BTCD (18 decimals) on ELA-PG.
expiresAtstring · optionalA future ISO 8601 timestamp.
webhookUrlstring · optionalA public HTTPS endpoint that receives payment events.
webhookSecretstring · optionalA 32–128 character signing secret; generated if omitted with webhookUrl.
metadataobject · optionalYour 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.

Cancellation
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.

BTCD invoice fields
{
  "payTo": "your-username",
  "networks": [
    "ela-pg"
  ],
  "amount": "0.05",
  "token": "BTCD"
}

04 · x402 v2

A standard payment handshake

Share /inv/{id} for a wallet checkout. An agent can pay the same invoice through /api/x402/{id} using the exact payment scheme.
01

Request an invoice

GET /api/x402/{id}

The payer asks for the invoice without a payment header.

02

Read the requirements

402 + PAYMENT-REQUIRED

Decode the base64 JSON requirements and choose an accepted network.

03

Authorize in a wallet

GET + PAYMENT-SIGNATURE

Sign the exact payment requirements, then retry with the base64 payload.

04

Confirm settlement

200 + PAYMENT-RESPONSE

The server verifies and settles the payment, then records the receipt.

Read the current server quote
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
Decoded PAYMENT-REQUIRED · 25 USDC on Base
{
  "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.

The status endpoint is safe to poll. Confirm paid and store the returned transaction reference before fulfilling your order.
Poll the status
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.
Public status · settled payment
{
  "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.

Node.js · verify a webhook signature
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.
invoice.paid · webhook payload
{
  "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"
}
Common responses
400Check input, token precision, address format, and network combination.
401 / 403Check API key validity, scopes, or wallet session.
402Payment is required or a supplied payment authorization was rejected.
409An idempotency conflict or a concurrent payment needs your attention.
503A required facilitator or service is temporarily unavailable. Check status before retrying payment.

06 · Model Context Protocol

Give your agent a payment workspace.

Connect a client to /api/mcp with a scoped API key. Your agent can manage invoices and read payment quotes; your wallet authorizes any payment.
Codex · config.toml
[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.

View public server discovery

The endpoint supports modern stateless MCP and compatible legacy clients through the official SDK. MCP specification update.