Pay with x402
A wallet pays for one completion in USDC on Base. No API key and no Klinn account. The call is the same POST /v1/chat/completions.
How a request is paid
- 1Call with no keySend the completion with no Authorization header.
- 2Read the 402The API answers
402 Payment Requiredwith aPAYMENT-REQUIREDheader. That is the USDC price of this prompt plus the output cap. - 3Sign and retryThe agent signs the payment and repeats the request with
PAYMENT-SIGNATURE. The answer is in that response.
404 or a 503 before any provider accepts is not settled. x402 does not pay decisions: a decisions call needs a model key. To add credit to an account instead, see Top-ups.Prerequisites
- A wallet that can sign an EIP-3009 USDC authorization on Base (
eip155:8453). Any such wallet works, including a viem account. The private key stays on the agent. - An x402 client. The sample uses
@x402/fetchandExactEvmSchemefrom@x402/evm. Any client that readsPAYMENT-REQUIREDand retries withPAYMENT-SIGNATUREworks. The olderX-PAYMENTheader is accepted too.
The only network is Base, the asset is USDC, and the scheme is exact. Settlement goes through the Coinbase facilitator.
The price of one call
Two numbers, found in two places. The catalog is the rate card: wholesale USD per million prompt tokens and per million completion tokens, with no key and no wallet (GET /v1/models, or GET https://app.klinn.dev/api/v1/models). The charge for one completion depends on this prompt and this output cap, so it comes back on the call itself.
accepts[0] names the scheme (exact), the network (eip155:8453, Base), the USDC asset, the payee, and amount in atomic units (6 decimals, so divide by 1,000,000). The resource description names the model and the output cap the amount covers. A paid response repeats the dollar amount in x-price-usd.
The quote is our price for that estimate. It uses the model's rates from the catalog, it is at least $0.001, and it is rounded up to a micro-dollar. The estimate counts the prompt at about four characters per token, plus the output cap. You pay the quote. max_tokens is 512 when you set none and 4,096 at most, and the provider is held to that cap, so the answer cannot run past what the price covers. Reasoning models spend output tokens thinking: give them 1,000 or more. A later provider that takes over after a failure keeps the same quote: the price belongs to the model. A keyed request is charged that same price per token, on the tokens it used.
A client on Base
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const wallet = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY);
const pay = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:*", client: new ExactEvmScheme(wallet) }] });
const res = await pay("https://api.klinn.dev/v1/chat/completions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ model: "claude-sonnet-5", max_tokens: 400, messages: [{ role: "user", content: "Summarise this page" }] }),
});wrapFetchWithPaymentFromConfig parses PAYMENT-REQUIRED, signs with the wallet you give it, and retries with PAYMENT-SIGNATURE. The completion comes back as soon as a provider accepts, and the USDC transfer is submitted in the background. The body carries x-price-usd. @x402/fetch returns that body either way: it reads a settlement header when one is present, and still hands back the body when the completion is already streaming.
Top-ups are different. They settle before they answer, and that response carries PAYMENT-RESPONSE with the transaction.
The same route as a key
Ranking is the usual one: the cheapest healthy provider for this token estimate, then the next if that one fails before the first byte. Routing fields (router, provider, x-router-*) are removed before ranking, so a paid call and a keyed call are ranked the same way.
Streaming
"stream": true is honored. The response is text/event-stream, the same chunks as a keyed request. stream_options.include_usage is forwarded, and a final usage chunk keeps prompt, completion and total tokens. The USDC amount stays the quote from the cap. The usage chunk reports the tokens the provider counted. The stream starts only after the signature verifies and a provider accepts. If the connection drops after that, the quoted amount is still settled, which is the same moment a keyed request is debited.
