What to charge AI agents for and which endpoints to put behind x402
By Requestway · · 7 min read
Deciding what to charge AI agents for is mostly a question of which endpoints, not how much. Put the wrong route behind x402 and agents walk away or you charge for things that should be free; leave the right one open and you give away the part that costs you money. This guide gives you a way to sort your endpoints, the cases to keep free, and how to test the decision before anyone pays.
If you need the protocol basics first, What is x402 covers the 402, sign, retry flow in a few minutes.
Start from what an agent is actually buying
With x402, the unit of sale is one HTTP request. An agent calls your route, gets 402 Payment Required with the price in the PAYMENT-REQUIRED header, decides whether to pay, signs, and retries. There is no account, no plan and no monthly commitment. Each call stands alone.
That has three consequences for what you put behind it:
- The response has to be worth the price on its own. The agent pays before it sees the result. If one call rarely answers its question, every call feels overpriced.
- The price is visible before payment. A client can compare the
amountinacceptsagainst its budget and decline. Anything that makes your price surprising (a cheap listing that leads to an expensive detail call, say) shows up as abandoned 402s. - Payment is per call, so call count matters. An endpoint designed to be polled every few seconds becomes expensive fast. An endpoint called once per task is easy to justify.
Five signs an endpoint belongs behind x402
None of these is decisive alone. An endpoint that matches three or more is a strong candidate.
1. It costs you something every time it runs
Upstream data you pay for, model inference, heavy queries, rendering, third-party API calls. If your marginal cost per request is real, so is the case for passing it on. Agents can generate far more traffic than people, so an unpriced expensive endpoint is a bill waiting to happen.
2. The response is useful by itself
A report, a lookup result, an enriched record, a converted file. Something an agent can use without making five more calls. Good x402 endpoints answer a question; weak ones are a step in a long conversation.
3. The data or computation is hard to get elsewhere
Proprietary datasets, curated or cleaned data, your own models, aggregated results that take effort to rebuild. If an agent can get the same answer free from a public source, it will.
4. It is safe to call again
Read endpoints that return the same result for the same input fit well. A client that retries, or a payment that fails at settlement, never leaves your system in a half-changed state. Writes need more thought (see below).
5. Machines call it, not people in a browser
x402 is built for programmatic clients holding a wallet. If the main users are humans signed in to your app, they already have a way to pay you. The Laravel package can serve them free with free-for-auth while still charging agents on the same route.
What to keep free
Some endpoints should stay open even if you could charge for them.
- Documentation, schemas and health checks. Agents need to learn what you sell before buying it.
- Discovery. The Laravel package serves
GET /.well-known/x402, listing your paid routes and their prices in the shape of the x402 discovery ("Bazaar") listing. Charging for the price list defeats it. - Indexes and search that lead to paid detail. A free list of what exists, with the valuable record behind a price, lets an agent decide what is worth buying. Make sure the free part does not already contain the answer.
- Authentication and account endpoints. These belong to a different payment model.
- Your own traffic. Monitoring, internal services and existing customers can be exempted with bypass rules:
X402_BYPASS_IPSfor IPs and CIDR ranges, API keys in a header viaX402_API_KEYS, or a closure withX402::bypassUsing(). Bypassed responses carry anX-X402-Bypassheader naming the rule, so you can always tell why something was not charged.
Be careful with endpoints that change things
In the default before_response settlement mode the order is: verify the payment, run your controller, settle, respond. Verification confirms the signature is valid and the payer has funds, but money only moves at settlement, after your code has run.
For a read, that is ideal. If your controller throws, nothing is settled and the agent pays nothing. If settlement fails, the response is discarded and the agent gets a 402.
For a write, the side effect has already happened by the time settlement runs. If settlement then fails, the agent is not charged and does not get the response, but the record was still created or the message still sent. Before putting a write endpoint behind x402, decide what a failed settlement means for it. Endpoints whose work can be repeated safely, or rolled back, are much easier to charge for.
A quick sorting table
Use this as a starting point, not a rule.
| Endpoint type | Fit for x402 | Why |
|---|---|---|
| Data lookup from a proprietary dataset | strong | real value, self-contained, safe to repeat |
| Generated report or export (CSV, PDF) | strong | clear unit of value, often costly to produce |
| Model inference or enrichment | strong | real marginal cost per call |
| Search or listing | usually free | helps agents choose what to buy |
| Real-time feed polled every few seconds | weak | per-call pricing adds up quickly for the client |
| Writes with side effects | case by case | the side effect happens before settlement |
| Docs, health, discovery | keep free | agents need them to buy anything |
| Login, account management | keep free | not a per-request purchase |
Match the price to the work
Once you know which routes to charge for, the price can follow the cost and value of each one. With requestway/laravel-x402 you have three levels of control.
A fixed price per route:
Route::get('/market-data', MarketDataController::class)->middleware('x402:0.01');
Named tiers in config/x402.php, so related routes move together:
'tiers' => [
'micro' => '0.001',
'standard' => '0.01',
'premium' => '0.10',
],
Route::get('/report', ReportController::class)->middleware('x402:premium');
And dynamic pricing, when one route does very different amounts of work depending on the request:
use Requestway\X402\Facades\X402;
X402::priceUsing(function (Request $request, RoutePayment $route): ?string {
return $request->boolean('full_history') ? '1.00' : null;
});
Returning null falls back to the route's own price. The figures above are examples, not recommendations. Prices are USD strings converted to USDC atomic units with string arithmetic; USDC has 6 decimals, so 0.01 becomes 10000, and anything finer than one atomic unit rounds up.
For how to arrive at the numbers themselves, see pricing an API for AI agents.
Make paid endpoints easy for agents to understand
An agent deciding whether to pay has only what your 402 tells it. Give it enough:
Route::get('/report', ReportController::class)
->middleware('x402:0.01,description=Daily report,mime=text/csv,timeout=30');
description and mime describe what is being bought and appear in the requirements and the discovery listing. tags= adds discovery tags. A clear description is cheap and is the difference between an agent recognising your endpoint as the right tool and skipping it.
Test the decision before charging: observe mode
You do not have to guess which endpoints agents will pay for. Run the package in observe mode:
X402_MODE=observe
Nothing is charged. Every request that would have been charged is logged, recorded with status = observed, fires PaymentObserved, and the response carries a header such as X-X402-Would-Charge: $0.25. After a week you can query what each route would have earned:
use Requestway\X402\Models\X402Payment;
X402Payment::query()->observed()->between(now()->subWeek(), now())->get();
Routes with steady observed traffic are your candidates. Routes nobody calls do not need a price. Observe mode measures existing traffic, not willingness to pay, so treat it as an upper bound on demand rather than a forecast. The observe mode guide goes further.
Seeing which choices paid off
Once routes are live, the questions become: which ones earn, which ones agents abandon at the 402, and which ones fail. Requestway is free analytics for x402 APIs: earnings per route, settled, observed and failed counts per day, and observed demand ("would-be revenue") on routes still in observe mode. It receives outcomes after your API has answered and never sits in the payment path. Setup is one environment variable for Laravel or @requestway/reporter for Node, as described in the install guide.
FAQ
Should I charge AI agents for every API endpoint?
No. Charge for endpoints that cost you something per call or return something valuable on its own, and keep docs, discovery, health checks and search free. Agents need the free parts to decide what is worth buying.
Can I charge AI agents but keep my API free for logged-in users?
Yes. With the Laravel package, add free-for-auth to a route (->middleware('x402:0.25,free-for-auth')) or set X402_FREE_FOR_AUTH=true to exempt signed-in users everywhere. Agents without a session still get the 402.
Is an agent charged if my endpoint throws an error?
Not in the default before_response mode. The controller runs before settlement, so if it throws, nothing is settled and the agent pays nothing.
Can the same endpoint have different prices?
Yes. Use X402::priceUsing() with a closure or a PriceResolver class to price by request parameters, such as the number of rows or a full-history flag, falling back to the route's price when you return null.
How do I know which endpoints agents would pay for before charging?
Run with X402_MODE=observe for a week. Every would-be charge is recorded with status = observed, so you can see request counts and foregone revenue per route without charging anyone.
Related articles
-
Pricing
Pricing an API for AI agents: per-request pricing explained
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