Payments

x402 + USDC

DirectMailAmerica implements HTTP-native x402 v2 concepts. Protected resources return 402 with a base64 JSON PAYMENT-REQUIRED header. Clients retry with PAYMENT-SIGNATURE. Success includes PAYMENT-RESPONSE.

Flow

1. POST /api/v1/credits  { "amountCents": 5000 }
   or MCP send_letter / purchase_credits (guest send_letter needs no API key)
2. 402 Payment Required
   Header PAYMENT-REQUIRED: base64(PaymentRequired)
   accepts[] includes (live stables):
     - scheme: exact · network: eip155:8453 · USDC on Base
     - scheme: exact · network: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp · USDC on Solana
3. Client signs EIP-3009 transferWithAuthorization (or Solana exact payload)
4. Retry the same URL with PAYMENT-SIGNATURE: base64(PaymentPayload)
   MCP agents may instead pass paymentSignature in the tool arguments
5. 200 OK + PAYMENT-RESPONSE: base64(SettlementResponse)
   Credits are added 1:1 with USD cents, or the letter job is created.

curl

curl -i -X POST "$HOST/api/v1/credits" \
  -H "Authorization: Bearer lbl_your_key" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":1000}'

# Decode PAYMENT-REQUIRED, sign, then:
curl -i -X POST "$HOST/api/v1/credits" \
  -H "Authorization: Bearer lbl_your_key" \
  -H "PAYMENT-SIGNATURE: $SIGNED_PAYLOAD" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":1000}'

Facilitator

Settlement is on-chain. Set X402_FACILITATOR_URL to a facilitator that exposes Coinbase CDP-style /verify and /settle and returns a real transaction hash. Missing facilitator URL or keys fail closed — the payment is not marked paid and no credits or jobs are recorded. The server never invents or hex-encodes a placeholder hash.

For USDC on Base the client signs EIP-3009 transferWithAuthorization. After settle, History / billing stores the Base transaction hash and links it on Basescan.

Merchant wallets come from X402_PAY_TO (Base) and X402_PAY_TO_SOLANA. Never commit those keys; only public receive addresses belong in env. The Coinbase CDP facilitator authenticates with a per-request JWT from CDP_API_KEY_ID and CDP_API_KEY_SECRET. A static X402_FACILITATOR_API_KEY Bearer is only a fallback for non-CDP facilitators. Optional X402_EVM_RPC_URL / BASE_RPC_URL add Base receipt proof.