Pricing an API for AI agents: per-request pricing explained
By Requestway · · 7 min read
Pricing an API for AI agents is different from pricing it for people: there is no signup page to persuade, no plan comparison table, and no sales call. An agent sees a price in a 402 response, decides in milliseconds whether the request is worth it, and either pays or moves on. This guide explains how per-request pricing works in x402, how to arrive at a number, and how to set fixed, tiered and dynamic prices without creating payment failures.
What a per-request price is in x402
With x402, the price is part of the HTTP exchange. The first request to a paid route gets 402 Payment Required with a PAYMENT-REQUIRED header listing what the server accepts: the scheme, the network, the token contract, the recipient (payTo) and the amount. The client signs a payment for that amount and retries. If you have not read the protocol overview yet, what x402 is covers the full flow.
Three properties of that amount shape every pricing decision.
It is a string in atomic units. USDC has 6 decimals, so the smallest possible charge is one atomic unit, a millionth of a dollar. Some reference points:
| Price in USD | Atomic units (USDC) |
|---|---|
| $0.000001 | 1 |
| $0.001 | 1000 |
| $0.01 | 10000 |
| $0.10 | 100000 |
| $1.00 | 1000000 |
It is advertised on every request. There is no price list the client downloaded last month. Whatever the 402 says right now is the price, which makes prices easy to change and easy for an agent to evaluate.
It is exact. The "exact" scheme on EVM chains uses an EIP-3009 transferWithAuthorization: the payer authorises one transfer of one amount to one address. There is no "up to" amount and no later adjustment. If you want to charge more for bigger requests, you work that out before the 402 is sent, which is what dynamic pricing is for.
Start with your cost floor, then the value ceiling
A price needs a floor and a ceiling. The floor is what a request costs you; the ceiling is what it is worth to the caller.
The floor. Add up what one request consumes: compute time, any upstream API you call, storage reads, and a share of fixed costs. As an example only: if an endpoint calls an upstream data provider that costs you $0.002 per call and your infrastructure adds roughly $0.0005, then anything below $0.0025 loses money on every request. Payment costs matter less than you might expect, because for EIP-3009 transfers the facilitator submits the transaction and pays gas, so neither you nor the agent needs ETH. Check the terms of whichever production facilitator you use.
The ceiling. Ask what the agent would have to do instead. If your endpoint returns a cleaned dataset that would take an agent several upstream calls and some parsing to assemble, it is worth more than the sum of those calls. If it wraps something freely available, the ceiling is low no matter what it costs you.
Somewhere in between. For most endpoints, round numbers between $0.001 and $0.10 are easy to reason about. Whoever sets an agent's budget has to reason about your prices, and a price that is a clean multiple of others in your API is easier to budget for. These are example numbers, not benchmarks: the only way to know what your callers will pay is to measure, which is covered below.
Fixed prices and named tiers
Most routes should start with a fixed price. In Laravel with requestway/laravel-x402, the price is the first middleware parameter, in USD:
Route::get('/market-data', MarketDataController::class)->middleware('x402:0.01');
Prices are converted to atomic units with string arithmetic, never floats, and anything finer than one atomic unit rounds up, so a route can never be underpriced by rounding.
Once you have more than a handful of paid routes, name your price points in config/x402.php and use the names on routes:
'tiers' => [
'micro' => '0.001',
'standard' => '0.01',
'premium' => '0.10',
],
Route::get('/report', ReportController::class)->middleware('x402:premium');
Tiers keep your pricing coherent. Changing what "standard" costs becomes a one-line config change instead of a search through route files, and php artisan x402:routes prints the resulting table of every paid route and its price.
In Node, the official middleware takes the price per route as a dollar string:
'GET /premium-data': {
accepts: [{ scheme: 'exact', price: '$0.01', network: 'eip155:8453', payTo: '0xYourAddress' }],
description: 'Premium market data',
},
The Express, Next.js and Hono guide shows the full setup.
Dynamic pricing for requests that vary in cost
Some endpoints do very different amounts of work depending on the input: a query that returns ten rows and one that returns ten thousand should not cost the same. The Laravel package lets you compute the price per request.
A closure is enough for simple rules. Return null to fall back to the route's own price:
use Requestway\X402\Facades\X402;
X402::priceUsing(function (Request $request, RoutePayment $route): ?string {
return match (true) {
$request->boolean('full_history') => '1.00',
default => null,
};
});
For anything you want to test on its own, implement Requestway\X402\Pricing\PriceResolver:
final class UsageBasedPrice implements Requestway\X402\Pricing\PriceResolver
{
public function resolve(Request $request, RoutePayment $route): string|int|float|null
{
return bcmul('0.0001', (string) $request->integer('rows', 1), 6);
}
}
X402::priceUsing(UsageBasedPrice::class);
Here a request for 500 rows costs $0.05 and a request for 1 row costs $0.0001. Price on something the caller controls and can see in its own request (rows, date range, resolution), so the agent can predict the cost before it asks.
The rule dynamic pricing must follow
The price must be a pure function of the request. The client receives a 402 for one request, signs that amount, and sends the same request again with the payment. If your resolver returns a different number the second time, because it reads the clock, a counter, a cache that expired or a random value, the server rejects the payment as an underpayment with invalid_exact_evm_payload_authorization_value_mismatch. The failure guide covers that code and its fixes in detail.
Make the price easy for an agent to evaluate
An agent deciding whether to pay has very little to go on: the amount, the description and the MIME type. Fill them in.
Route::get('/report', ReportController::class)
->middleware('x402:0.01,description=Daily report,mime=text/csv');
The Laravel package also publishes every paid route at GET /.well-known/x402, in the shape of the x402 discovery ("Bazaar") listing. Because it is generated from your registered routes, the advertised prices cannot drift from what you actually charge.
A few habits help agents, and the developers who configure them:
- Say what one request buys. "Daily report for one ticker, CSV" beats "Report".
- Keep units obvious. If you price per row, put the row count in the request, not in a header the agent has to guess.
- Do not split one task across many paid calls. If a useful answer always takes five requests, agents see five charges and five chances to fail. Consider one endpoint at the combined price.
- Remember the wallet behind the agent is usually small. Agents are advised to pay from a dedicated low-balance wallet, so a $5 request may simply be unaffordable for a caller that would happily pay $0.05 a hundred times.
Measure demand before you charge
The hardest pricing question is whether anyone will pay at all. Observe mode answers it without charging anyone:
X402_MODE=observe
Nothing is charged. Each request that would have been charged is logged, recorded with status = observed, fires a PaymentObserved event, and the response carries an X-X402-Would-Charge header such as $0.25. After a week you can see which routes agents use and what they would have earned at your chosen prices:
use Requestway\X402\Models\X402Payment;
X402Payment::query()->observed()->between(now()->subWeek(), now())->get();
Observe mode measures demand at zero price, which is the upper bound: some of that traffic will disappear once a charge applies. Even so, it tells you where to start, and which routes are not worth putting behind a price at all. The observe mode guide goes further.
Changing prices later
Because the price travels in every 402, changing it is cheap. There is no plan migration and no customer email; the next request sees the new amount. Two things to watch when you do:
- Underpayments right after a change. A client that cached old requirements will sign the old amount. A short burst of
value_mismatchfailures after a price rise is that, not a bug. - Volume per route. Compare request counts and earnings for the route over the week before and the week after. If volume halves when the price doubles, revenue is flat and you have annoyed your callers for nothing.
For one-off checks, the payments table answers both. Settled revenue for a route over a period:
X402Payment::query()->settled()->forRoute('reports.show')->between($from, $to)->sum('amount_atomic');
Tracking it in Requestway
Requestway is free analytics for x402 APIs. It shows earnings per route (daily, and over 7, 30 and 90 days), settled, observed and failed counts per day, and would-be revenue on routes in observe mode, so before-and-after comparisons around a price change are a glance rather than a query. It receives outcomes after your API has answered and is never in the payment path. In Laravel it is one setting, X402_PLATFORM_KEY; the install guide covers Node as well, and you can create a free account when you are ready.
FAQ
What is the minimum price I can charge with x402?
With USDC, one atomic unit: $0.000001. In the Laravel package, any price finer than that is rounded up to the next atomic unit.
Who pays the gas fees on an x402 payment?
For EIP-3009 transfers, the facilitator submits the transaction and pays gas, so neither the API nor the agent needs ETH. Check your production facilitator's own terms for any fees it charges you.
Can I charge different prices to different callers?
Yes. A closure passed to X402::priceUsing() receives the request, so it can price by input or by signed-in user. To exempt signed-in users entirely, use the free-for-auth middleware option.
Should I price per request or per unit of data?
Per request is simplest and suits endpoints whose cost is roughly constant. When cost varies a lot with input, use dynamic pricing based on a value the caller sets in the request, so it can predict the price before paying.
Related articles
-
Strategy
What to charge AI agents for and which endpoints to put behind x402
7 min read
-
Pricing
Observe mode: measuring what agents would pay before you charge
6 min read
-
Strategy
x402 vs API keys and subscriptions: when pay-per-request makes sense
6 min read