Skip to main content
Sprintcheckout lets your merchants accept x402 payments: an AI agent (or any HTTP client) pays a payment session in USDC on Base, and the settled payment shows up in your dashboard like any other order. Sprintcheckout wraps Coinbase’s hosted x402 facilitator — it does not reimplement the protocol and never custodies funds.
Your X-SC-ApiKey is a secret server credential. It authorizes creating and updating payment sessions on your behalf. Never ship it to an agent, a browser, or any buyer-side code. The agent only ever needs the public sessionId.

How it works

1

Configure your Base wallet

In Settings → Wallet address, set the Base wallet that should receive USDC. This existing address is what the 402 challenge quotes as payTo. No x402-specific configuration is needed.
2

Create a payment session (server-side)

Your backend creates a session with your secret X-SC-ApiKey and receives a public sessionId.
3

Hand the agent the public sessionId

Give the agent only the sessionId — never the API key.
4

The agent pays over x402

The agent requests the x402 endpoint with the public sessionId, receives a 402 Payment Required quoting your wallet and the USDC amount, pays on Base, and retries with proof.
5

Settlement appears in your dashboard

On success the payment is settled via Coinbase’s facilitator and recorded as a paid order — visible in your dashboard transaction list with a BaseScan receipt.

1. Merchant — create a payment session

This runs on your server, with your secret X-SC-ApiKey. The response sessionId is the public identifier the agent will pay.
cURL
curl --request POST \
  --url https://api.sprintcheckout.com/api/checkout/v2/payment_session \
  --header 'X-SC-ApiKey: <YOUR_SECRET_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "amount": 0.01,
    "currency": "USD",
    "orderType": "TRANSIENT",
    "orderId": "agent-demo-001"
  }'
Response
{
  "sessionId": "a7Xk9mQ2pR",
  "redirectUrl": "https://app.sprintcheckout.com/?uid=a7Xk9mQ2pR"
}
A session created from the dashboard Points of Sale / payment link flow works exactly the same way — its public uid is the sessionId the agent pays.

2. Agent — pay over x402

The agent uses only the public sessionId — no secret. A first request returns the challenge:
cURL
curl -i https://api.sprintcheckout.com/x402/session/a7Xk9mQ2pR
402 Payment Required
HTTP/1.1 402 Payment Required
Content-Type: application/json

{
  "x402Version": 2,
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0x986dd13ccab3b637032ebedd30ef8a7fea4d6184",
      "maxAmountRequired": "10000",
      "resource": "/x402/session/a7Xk9mQ2pR",
      "description": "x402 payment for session a7Xk9mQ2pR",
      "mimeType": "application/json",
      "maxTimeoutSeconds": 60,
      "extra": { "name": "USD Coin", "version": "2" }
    }
  ]
}
maxAmountRequired is in USDC base units (6 decimals — 10000 = 0.01 USDC). payTo is the merchant’s Base wallet from Settings. network is the x402 network name base (Base mainnet). extra carries USDC’s EIP-712 domain (name/version) that the agent’s wallet signs the gasless transfer against — x402-fetch reads it automatically, so you rarely handle it by hand. The simplest way to pay is the official x402-fetch wrapper, which handles the challenge, the on-chain USDC payment on Base, and the retry with the X-PAYMENT proof header automatically:
x402-fetch
import { wrapFetchWithPayment } from "x402-fetch";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";

const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const wallet = createWalletClient({ account, chain: base, transport: http() });

// Wrap fetch so 402s are paid and retried automatically.
const fetchWithPayment = wrapFetchWithPayment(fetch, wallet);

const sessionId = "a7Xk9mQ2pR"; // public id, no API key
const res = await fetchWithPayment(
  `https://api.sprintcheckout.com/x402/session/${sessionId}`
);

console.log(res.status); // 200 once paid
console.log(await res.json());
x402-fetch caps spend at 0.1 USDC by default. To pay more, raise the limit: wrapFetchWithPayment(fetch, wallet, maxValue) where maxValue is in USDC base units (e.g. BigInt(1_000_000) for 1 USDC). Larger amounts also need the buyer wallet funded with enough USDC on Base.
Buyer-chosen (variable) amounts. If the session was created with an editable amount, the agent declares what it will pay with an ?amount= query parameter (in the session’s currency) on both the initial request and the X-PAYMENT retry — e.g. …/x402/session/{sessionId}?amount=2.50. Without it, the 402 body asks for ?amount= and echoes the minAmount floor.
Under the hood the second request carries the proof header and returns the resource:
Retry with proof
curl -i https://api.sprintcheckout.com/x402/session/a7Xk9mQ2pR \
  --header 'X-PAYMENT: <base64 payment payload>'
200 OK
HTTP/1.1 200 OK
X-PAYMENT-RESPONSE: <base64 settlement receipt>

{
  "status": "SUCCESS",
  "paymentSessionId": "6a3a46292b5c6620927c3b9f",
  "payTo": "0x986dd13ccab3b637032ebedd30ef8a7fea4d6184",
  "receipt": "https://basescan.org/tx/0x…"
}
receipt links the settled transaction on BaseScan; the same order appears in your dashboard transaction list. The X-PAYMENT-RESPONSE header is the facilitator’s base64 settlement response.

Response codes

StatusMeaning
200 OKPaid — the resource is returned. A request against an already-settled session also returns 200 idempotently (the session is never charged twice).
404 Not FoundUnknown or expired sessionId.
422 Unprocessable EntityThe merchant has no Base wallet configured in Settings, so no payTo can be quoted.
402 Payment RequiredNo payment yet, or the submitted proof is missing / invalid / insufficient — re-pay against the returned challenge.
x402 settlement uses mainnet USDC on Base (network base, chain id 8453). It is not available on other chains or tokens. Settlement is performed by Coinbase’s hosted CDP facilitator; Sprintcheckout never holds funds. The buyer pays no gas — the transfer is a gasless EIP-3009 authorization the facilitator submits on-chain.