x402 payments and Stripe MPP: let your AI agent top up its own balance
When your QuanticData balance runs out, the API answers 402 with two ways to pay that an AI agent can use without you: x402, a USDC payment on Base signed from a wallet, and Stripe's Machine Payments Protocol (MPP), a one-time token on your card in Link. Either one adds credit to the balance of your API key: $3 to $500 with x402, $5 to $500 with MPP.
$2 of free API usage per month · No card required · Failed calls are never billed
POST https://api.quanticdata.io/v1/serp Authorization: Bearer qd_live_… → 402 INSUFFICIENT_FUNDS · nothing run, nothing charged PAYMENT-REQUIRED x402 · 5 USDC on Base WWW-Authenticate Payment method="stripe" · $5 + 22% VAT # the agent pays one offer and repeats the same call → 200 the search · X-X402-Topup: 5.00 the call is billed from the balance at list price
x402 and MPP, in one sentence each
Both are open protocols built on the HTTP status 402 Payment Required: the server says what to pay, the client pays and repeats the request. On QuanticData they do one thing only: they add credit to the balance of the API key that made the call. They never buy a single call and never change a price.
- x402 is an open payment protocol, published by Coinbase and maintained by the x402 Foundation: your agent signs a USDC payment from its own wallet, and QuanticData settles it on the Base network.
- MPP, the Machine Payments Protocol, is the open standard Stripe and Tempo published for agent payments over HTTP: QuanticData accepts it with Stripe Shared Payment Tokens, a one-time permission, capped to one amount, to charge your card in Link.
| x402 | MPP (Stripe) | |
|---|---|---|
| Pays with | USDC on Base, from a wallet the agent can sign with | a Shared Payment Token on your card in Link |
| Credit per top-up | $3 to $500 | $5 to $500 |
| VAT | none, paid in crypto | 22% on top, as on every card top-up |
| Your approval | none: the cap you set in the client and the wallet balance are the limits | with Link, one tap in its app for each payment |
| Network fee | paid by QuanticData | none |
Why you would turn it on
- The agent does not stop at an empty balance. A job that runs overnight keeps going: the top-up and the call happen in the same request, and the call is billed at list price like any other.
- No card form, no dashboard. Nobody opens a checkout page: the payment travels as a header on the API request the agent was already making.
- Pay in USDC if you prefer. x402 takes USDC on Base, with no VAT and no card, and the wallet needs nothing else: QuanticData pays the network fee.
- You keep the limits. A cap per payment in the client, a monthly budget on the account and a key you can revoke, all explained below.
- The free tier comes first. Every account has $2 of free API usage a month; the 402 appears only when that and the balance together cannot cover the next call.
What you need
| x402 | MPP | |
|---|---|---|
| A QuanticData API key | yes, from the API keys page or the agent's own registration | yes, the same |
| Money | USDC on the Base network, in a wallet the agent can sign with | a card saved in your Link wallet |
| Software | an x402 client: @x402/fetch for TypeScript, x402 for Python | Stripe's Link CLI, or an agent platform that issues Shared Payment Tokens |
| ETH for gas | no: QuanticData pays the network fee | not needed |
Give the agent a wallet of its own and keep in it only what you are happy for it to spend. Its private key lives where the agent runs, in an environment variable next to the API key, never in code, logs or chat.
Set up x402 in five steps
- Get an API key. Create one on the API keys page, or let the agent register itself with your email. The key decides which balance is topped up.
- Fund a wallet with USDC on Base. Send USDC on the Base network, not on Ethereum mainnet, to the wallet the agent will use, and put its private key in the agent's environment, for example
WALLET_PRIVATE_KEYnext toQD_API_KEY. No ETH is needed. - Give the agent an x402 client with a cap. Install
@x402/fetchor the Pythonx402package and wrap the HTTP client the agent already uses, as in the code below. Set the cap per payment: both clients refuse anything above $1 by default, and a QuanticData top-up starts at $5, so $20 is a sensible first cap. - Let it run. When the balance is short, the call answers 402, the client signs the amount offered, repeats the call and returns the result. To top up ahead of time instead, the agent sends
POST /v1/billing/x402-topupwith{"amount_usd": 20}. - Check the first payment. The credit shows on the balance in the dashboard, the invoice, with no VAT, reaches the account's email, and the response header
PAYMENT-RESPONSEcarries the Base transaction hash.
Set up MPP in four steps
The simplest way to hold Shared Payment Tokens yourself is Link, Stripe's wallet, through its command-line tool. An agent platform that issues the tokens for you works the same way from step 3.
- Get an API key. The same as for x402: the payment tops up the balance of the key that made the call.
- Sign in to Link where the agent runs. Run
npx @stripe/link-cli auth login, keep a card in your Link wallet and the Link app on your phone for approvals. - Let the agent pay through the Link CLI when the balance is short.
npx @stripe/link-cli mpp paysends the call with the API key, reads the 402, asks Link for a token of the exact amount ($6.10 for $5 of credit with VAT), sends you a request to approve in the Link app, then pays and repeats the call. The command is in the code below. - Check the invoice. A numbered invoice with 22% VAT is emailed to the account, and the credit appears on the balance with the Stripe payment reference.
Link asks you to approve each request within 30 minutes, and each token pays once: the next top-up is a new request.
Limits, VAT and invoices
Both ways buy the same thing, credit on the prepaid balance of your account, which does not expire. The call is then billed from it at the published price, and a failed call is not billed.
| x402 (USDC on Base) | MPP (Stripe) | |
|---|---|---|
| Credit per top-up | $3 to $500 | $5 to $500 |
| Amount offered on a 402 | the shortfall rounded up to the whole dollar, at least $5 | $5, or the shortfall rounded up to the cent if larger |
| VAT | 0%, paid in crypto | 22% on top: $5 of credit costs $6.10 |
| Invoice | emailed to the account, no VAT | numbered, emailed to the account, 22% VAT |
| Offer valid for | 60 seconds to sign it | 5 minutes, single use |
| Paid twice by mistake | not possible: each signed transfer is credited once | not possible: each challenge is used once |
| Above $500 | no offer: top up on the dashboard, or write to hello@quanticdata.io | the same |
An account can pay up to 30 MPP top-ups a minute and 2,000 a day. Unit prices for every call are on the pricing page and in llms.txt.
See every top-up, and stop it when you want
- See it. Every top-up is a row in the balance history and an invoice on the invoices page, and the same invoice is emailed to the account. The agent gets the Base transaction hash (x402) or the Stripe payment reference (MPP) in the response.
- Cap each payment. The x402 client refuses any offer above the cap you set in it; Link asks you to approve every MPP payment.
- Cap the month. In Billing, under Spend controls, set a monthly Data API budget with the hard stop on. Once it is reached the API answers 402
BUDGET_REACHED, which carries no payment offer, so the agent cannot top up again until next month or until you raise it. - Get an alert. The same Spend controls send an email, or a webhook, when the balance falls under the amount you choose.
- Stop everything. Revoke the key on the API keys page: the agent can no longer call, and no payment can be credited without a valid key. For x402 you can also empty the agent's wallet; for MPP, remove the card from Link.
For developers: one 402, two offers
Every call made with an API key that answers 402 INSUFFICIENT_FUNDS carries both offers, as long as the shortfall is at most $500. The body is the usual error envelope; the offers travel in two headers, PAYMENT-REQUIRED for x402 and WWW-Authenticate: Payment for MPP.
curl -i https://api.quanticdata.io/v1/serp \
-H "Authorization: Bearer $QD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"best espresso grinder","engine":"google","country":"us"}'
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi… # x402 version 2, base64 JSON
www-authenticate: Payment id="…", realm="api.quanticdata.io", method="stripe", intent="charge",
request="eyJhbW91bnQiOiI2MTAi…", expires="…", description="…", opaque="…"
{"type":"error","message":"Your free tier for this month is used up …",
"payload":{"code":"INSUFFICIENT_FUNDS","estimated_cost":0.002,"balance":0,"free_remaining":0}}
Decoded, PAYMENT-REQUIRED holds one exact requirement in USDC base units (6 decimals). payTo is QuanticData's own wallet: read it from the offer, never hardcode it.
{
"x402Version": 2,
"resource": { "url": "https://api.quanticdata.io/…", "serviceName": "QuanticData Data API", … },
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "5000000",
"payTo": "0x…",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
}]
}
You can see a real offer now, without a key or a wallet: the top-up endpoint answers 402 with the requirements for the amount you ask. We ran it on 30 October 2026; a payment sent without a key is refused with 401 before anything is charged.
curl -i -X POST https://api.quanticdata.io/v1/billing/x402-topup \
-H "Content-Type: application/json" -d '{"amount_usd":20}'
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi… # accepts[0].amount "20000000" = 20 USDC
{"x402Version":1,"error":"Pay $20 in USDC on eip155:8453 and retry this request with the payment
header and Authorization: Bearer <API key> (the key whose balance is topped up)","accepts":[…]}
x402
x402 in TypeScript and Python
The reference x402 clients wrap the HTTP client: on a 402 they sign the offer, an EIP-3009 transferWithAuthorization of the amount to payTo, and repeat the request with PAYMENT-SIGNATURE, keeping your Authorization header. We ran both on 30 October 2026 with @x402/fetch 2.29.0 and x402 2.26.0. Set the cap: by default they refuse more than $1.
// npm i @x402/fetch @x402/evm viem
import { wrapFetchWithPaymentFromConfig, decodePaymentResponseHeader } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const wallet = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const fetchWithTopup = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(wallet) }], // Base
spendControls: { maxAmountPerPayment: "$20" }, // default $1; a top-up starts at $5
});
// any call: when the balance is short, the client pays the top-up offered and repeats it
const res = await fetchWithTopup("https://api.quanticdata.io/v1/serp", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.QD_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ query: "best espresso grinder", engine: "google", country: "us" }),
});
console.log(res.status, res.headers.get("X-X402-Topup"), res.headers.get("X-Balance-After-Topup"));
const receipt = res.headers.get("PAYMENT-RESPONSE");
if (receipt) console.log("Base tx", decodePaymentResponseHeader(receipt).transaction);
MPP: the credential, and a test with Link
The challenge in WWW-Authenticate is paid by repeating the same request with Authorization: Payment <credential> (or Payment-Authorization). The credential is base64url JSON of every challenge parameter, unchanged, plus the token. The challenge is bound to your key and account, so the paid request needs no Bearer header. amount is in cents and already includes VAT: "610" for $5 of credit.
# the paid request: same method, URL and body as the call that got the 402
Authorization: Payment base64url({"challenge":{"id":"…","realm":"api.quanticdata.io","method":"stripe",
"intent":"charge","request":"…","expires":"…","description":"…","opaque":"…"},"payload":{"spt":"spt_…"}})
→ 200 { …the search… }
Payment-Receipt: base64url({"status":"success","method":"stripe","reference":"pi_…","timestamp":"…"})
X-MPP-Credited: 500 # credit added, in cents
X-MPP-Invoice: <invoice id>
To try it yourself, Stripe's Link CLI does the whole round trip: it calls the URL, reads the challenge, creates a spend request for a Shared Payment Token scoped to QuanticData, waits for your approval in the Link app and repeats the call with the credential.
npx @stripe/link-cli auth login
npx @stripe/link-cli mpp pay https://api.quanticdata.io/v1/serp \
--header "Authorization: Bearer $QD_API_KEY" \
--data '{"query":"best espresso grinder","engine":"google","country":"us"}' \
--context "Top up my QuanticData API balance with 5 USD of credit plus 22% VAT, 6.10 USD in all, so my research agent can keep running searches."
Until the free allowance and the balance are used up, the call simply runs and nothing is paid: the Link CLI returns the response as it is.
Answers an agent should handle
| Answer | What it means | What the agent does |
|---|---|---|
402 X402_TOPUP_FAILED | the signature, amount, network, asset or recipient did not match, or the transfer did not go through; nothing was credited | pay the fresh PAYMENT-REQUIRED that comes with it |
500 X402_TOPUP_CREDIT_PENDING | the transfer went through but the balance was not updated yet | write to support with the transaction hash in the answer: it is credited |
| 401 | an x402 payment sent without an API key; nothing was charged | repeat it with Authorization: Bearer |
400 X402_TOPUP_ABOVE_MAX | more than $500 asked of /billing/x402-topup | ask for $500 or less, or top up on the dashboard |
402 payment-expired, verification-failed (MPP) | the challenge expired or the token was declined | pay the fresh challenge in the answer |
403 invalid-challenge (MPP) | a credential that was already used | repeat the call with the API key for a new challenge |
429 mpp_limit | more than 30 payments a minute or 2,000 a day | wait for Retry-After |
402 BUDGET_REACHED | the monthly budget you set on the account is used up | no offer: ask the person |
The full reference, with every header and problem type, is in the Agents tag of the API documentation.
The setting to start with
An API key in QD_API_KEY, then either an x402 client on eip155:8453 with a $20 cap per payment and a wallet holding USDC on Base, or the Link CLI signed in with a card. Every account starts with $2 of free API usage per month; a top-up is $3 to $500 of credit with x402, $5 to $500 with MPP.
Sources and standards
The protocols and tools this page relies on, so you can check every header and command against its specification:
- x402: the protocol site of the x402 Foundation
- x402 on GitHub: the specification and the reference clients, @x402/fetch on npm and x402 on PyPI
- EIP-3009: transferWithAuthorization, the signature an x402 client sends for USDC
- Machine Payments Protocol: the open specification for agent payments over HTTP 402
- The HTTP Payment authentication scheme: draft-httpauth-payment-01 and the Stripe charge method
- Stripe: Shared Payment Tokens, and how to issue one with the Link CLI
- Link for agents: the Link CLI and its limits
What is x402?
x402 is an open payment protocol built on the HTTP status 402 Payment Required, published by Coinbase and maintained by the x402 Foundation. The server answers 402 with what to pay, the client signs a stablecoin payment, usually USDC, and repeats the request with it. QuanticData accepts it on Base to top up the balance of an API key.
What is the difference between MPP and x402?
Both use HTTP 402. x402 pays in stablecoins signed from a wallet, so the agent needs USDC and nothing else. MPP, from Stripe and Tempo, lets the agent pay with a Stripe Shared Payment Token, a one-time permission on a card. On QuanticData both buy the same thing: balance, $3 to $500 with x402, $5 to $500 with MPP.
Does x402 need an API key on QuanticData?
Yes. An x402 payment tops up the balance of the API key sent with it, so the agent repeats the request with Authorization: Bearer and the PAYMENT-SIGNATURE header. A payment without a key is refused with 401 before anything is charged; the payment requirements can be read without one.
Can I pay for the API in USDC?
Yes. x402 takes USDC on the Base network, $3 to $500 per payment, with no VAT and an invoice emailed to the account. QuanticData pays the network fee, so the wallet needs only USDC. A person can also top up with crypto on the dashboard.
Is VAT charged on these top-ups?
22% VAT is added to MPP top-ups, as to every card payment: $5 of credit costs $6.10, on a numbered invoice. x402 top-ups are paid in crypto and carry no VAT. In both cases the credit is the amount shown, and calls are billed from it at list price.
How do I stop my agent from paying?
Set a monthly Data API budget with the hard stop in Billing, under Spend controls: once it is reached, calls answer BUDGET_REACHED with no payment offer. You can also lower the cap per payment in the x402 client, remove the card from Link, or revoke the API key, which ends calls and top-ups at once.
Does the agent pay for each call?
No. A payment always adds credit to the balance and never buys a single call, and no price changes. The call that met the empty balance then runs from the new credit at list price, failed calls are not billed, and what is left stays on the balance, which does not expire.
Is the free tier used first?
Yes. Every account has $2 of free API usage a month, with no card. The 402 with the two offers appears only when the free allowance and the balance together cannot cover the next call.
Let your agent keep its own balance
One API key, two ways to pay, from $3 a time. $2 of free API usage per month, no card to start.
Get my free API key