Pay per request (x402)
An agent with a crypto wallet can use UberLLM with no account and no API key. It pays for each request in USDC on Base, using the open x402 payment standard (version 2).
This works for chat: POST /v1/chat/completions and POST /v1/messages. Images, video and music
still need a key.
To check that pay-per-request is switched on, open api.uberllm.dev/x402. It shows the network, the USDC contract and the wallet that gets paid. If it answers "404 not found", pay-per-request is off. Use a key instead (Quickstart).
How it works
- Send the request with no key. The answer is HTTP 402 Payment Required. The
PAYMENT-REQUIREDheader (base64 JSON, also in the body) says how much the request can cost at most, and which ways to pay are accepted. - Your wallet signs one of those options. Send the same request again with the signature in the
PAYMENT-SIGNATUREheader. - UberLLM checks the payment, answers, then collects the payment. A normal (non-streaming) answer
comes with the receipt in the
PAYMENT-RESPONSEheader, which includes the on-chain transaction.
Each signature pays for one request. To make another request, sign again.
What you pay
The 402 quotes the most the request can cost. That is your prompt plus max_tokens of output, at
the priciest route the request may take, plus 10%. Set max_tokens to keep the quote low.
There are two ways to pay:
upto(offered first). You sign the quote as a ceiling. After the answer, only the real cost is taken, rounded up to the next millionth of a dollar. The first payment needs a one-time USDC approval. Where the payment service supports it, that approval needs no gas.exact. The full quoted amount is taken, even if the request used less. Nothing is refunded. Pickexactonly if your wallet can't doupto.
You are never charged more than the amount you signed. If nothing is served (no model available, an error before the answer starts), nothing is taken.
Try it with curl
curl -i https://api.uberllm.dev/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"deepseek/deepseek-v4-flash","max_tokens":200,"messages":[{"role":"user","content":"Hello"}]}'
# HTTP/1.1 402 Payment Required
# PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6Mi…
#
# {"x402Version":2,"error":"PAYMENT-SIGNATURE header is required",
# "accepts":[{"scheme":"upto","network":"eip155:8453","amount":"…","asset":"0x8335…2913","payTo":"0x…",…},
# {"scheme":"exact",…}]}
amount is in USDC base units: 1,000,000 is $1. Sign one entry of accepts with your wallet. Then
send the same request again with -H 'PAYMENT-SIGNATURE: <base64 payment>'.
From code
An x402 client library does the 402, signing and retry for you. In JavaScript:
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const pay = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
const res = await pay("https://api.uberllm.dev/v1/chat/completions", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
model: "deepseek/deepseek-v4-flash",
max_tokens: 200,
messages: [{ role: "user", content: "Hello" }],
}),
});
console.log(await res.json());
To pay only the real cost, also register UptoEvmScheme from @x402/evm/upto/client. Libraries for
Go and Python are listed at x402.org.
Good to know
- Streaming works. With
"stream": true, the answer streams as usual. The payment is collected when the stream ends. There is noPAYMENT-RESPONSEheader, because the headers were already sent. Your wallet shows the transfer. - One wallet, at most 4 paid requests at a time.
- If a payment can't be collected after the answer (for example, the wallet was emptied in the
meantime), a normal answer is held back and you get
402 payment_failed. That wallet then can't pay for 24 hours. - Version 1 x402 (
X-PAYMENTheader) is not accepted. Use a version 2 client. - Lots of requests? An account with prepaid credit is simpler and has no on-chain step: sign up.
Errors
| HTTP | meaning | do |
|---|---|---|
402 + PAYMENT-REQUIRED |
no payment, or the payment was refused (the error field says why) |
sign one of accepts and retry |
402 payment_failed |
the answer was ready but the payment couldn't be collected | fund the wallet; that wallet can pay again in 24 hours |
400 invalid_payment |
PAYMENT-SIGNATURE isn't a base64 x402 v2 payment |
fix the client |
429 rate_limited |
4 paid requests already running from this wallet | wait for one to finish |
503 service_unavailable |
the payment service is briefly down | retry in a minute |