Quickstart: protect your agent's x402 payments
Your agent is about to spend money. x402 lets it pay an API on its own, but the protocol can't tell it whether the endpoint works, whether the price is right, or whether the payout wallet still belongs to the seller. Once the agent signs, the money is gone.
Lumière PayCheck sits right before that payment. Free: it tells your agent whether a payment looks safe. Paid plans: it enforces your spending rules, so a payment that breaks them never gets a signed approval.
Free check vs. paid enforcement
| Free check | Paid authorization | |
|---|---|---|
| How | check_payment (MCP) or POST /v1/check-payment | POST /v1/authorize with an agent key |
| Answers | Does this endpoint, price, and wallet look safe? | Is this agent allowed to send this exact payment? |
| Result | allow: true/false with reasons. Advice: your agent can ignore it | allow, deny, or review, plus a signed receipt on allow |
| Spending rules | One-off caps you pass in each call | Per-agent caps, daily and monthly limits, allowed sellers, company caps and blocklists |
| Human approval | No | Yes, on Business and Enterprise |
| Proof | No | Ed25519 receipt bound to the URL, amount, and wallet, plus a tamper-evident audit trail |
| Account | None | Builder $9/month, Business $49/month, Enterprise custom |
The free check is advice. Enforcement means the payment can't go out without PayCheck's signed approval: your wallet code refuses to sign unless the receipt verifies for that exact payment (see step 4).
The flow
Agent ──GET──▶ paid API
◀─402── price 10000, payTo 0xSELLER, network eip155:8453
Agent ──check──▶ Lumière PayCheck
◀──────── allow / deny / review (+ signed receipt on allow)
allow → pay with x402 → get the response → report the outcome
deny → don't pay; the reasons say why
review → wait for a person on your team (Business+)Step 1. Free: check a payment (no account)
In Claude, Cursor, or any MCP client: add https://lumierepaycheck.org/mcp as a connector (no sign-in), then ask: "My agent got a 402 from https://api.seller.example/data for 10000 USDC atomic units to 0xSELLER on eip155:8453. Should it pay?"
Over HTTP:
curl https://lumierepaycheck.org/v1/check-payment -H "content-type: application/json" \
-d '{"url":"https://api.seller.example/data","amount":"10000","payTo":"0xSELLER","network":"eip155:8453","rules":{"maxAmount":"50000000"}}'You get allow, the reasons, the endpoint's grade and verdict, and the payout wallet and price we last observed. Amounts are in the token's smallest unit: for USDC, 1000000 is $1. Free calls allow 60 a minute; a free API key raises that to 300.
Step 2. Paid: get an agent key
Subscribe, save your owner key, then on the account page create a key for each agent with its limits: allowed sellers, max per payment, daily and monthly limits, and (Business and up) when a person must approve. The agent key is shown once. Getting started walks through it.
Step 3. Paid: authorize before every payment
async function authorize(url: string, amount: string, payTo: string, network: string) {
const r = await fetch("https://lumierepaycheck.org/v1/authorize", {
method: "POST",
headers: { authorization: `Bearer ${process.env.PAYCHECK_AGENT_KEY}`, "content-type": "application/json" },
body: JSON.stringify({ url, amount, payTo, network }),
});
if (!r.ok) return { outcome: "deny", reasons: [`PayCheck returned ${r.status}`] }; // fail closed
return r.json() as Promise<{ outcome: "allow" | "deny" | "review"; reasons: string[]; receipt?: string; decision: string }>;
}Pay only on allow, and only that amount to that wallet. If PayCheck can't be reached, don't pay.
On Node with @x402/fetch, our npm package does steps 3 and 4 for you: withPayCheck(client, { agentKey: process.env.PAYCHECK_AGENT_KEY }) asks PayCheck before every payment and never signs one it denied (integration guide).
Step 4. Paid: enforce it in your wallet
Advice becomes enforcement when the code that signs payments refuses to sign without a valid receipt. A receipt is valid for 5 minutes and only for the exact URL, amount, and payout wallet it was issued for. Verify it against our public key at /.well-known/paycheck-receipt-key.json.
The guarded payer example does all of this in one function: read the 402, authorize, verify the receipt, pay, and report. Receipt verifiers in TypeScript and Python are in the examples folder.
Step 5. Report the outcome
After paying, tell us whether you got what you paid for: report_outcome (MCP) or POST /v1/report with your receipt (or, without a plan, the endpoint url and the payment tx) and short answers: {"answers": {"gotResponse": true, "matchedListing": "yes", "charged": "as_quoted", "dataUsable": "yes", "wouldPayAgain": true}}. Reports never change a grade on their own: confirmations move the endpoint up our paid-test queue, and problems trigger our own re-test. Details: Report outcomes.
Example: an agent tries to spend $500 with a $50 limit
Your research agent's key allows at most $50 per payment (50000000). A seller's 402 asks for $500:
{ "url": "https://api.seller.example/report", "amount": "500000000", "payTo": "0xSELLER", "network": "eip155:8453" }PayCheck answers:
{ "outcome": "deny",
"reasons": ["amount 500000000 exceeds maxAmount 50000000",
"amount 500000000 is higher than the monitored price 10000"] }No receipt is issued, so a guarded wallet won't sign. Every reason that failed is listed, here both your cap and the fact that the seller normally charges $0.01. The decision is stored in your audit trail with its inputs, so you can replay it later.
The same machinery covers the other common cases:
- Swapped payout wallet: the 402 names a wallet we haven't seen this seller use →
deny("payTo differs from the monitored payout wallet"). - Runaway loop: a cheap call repeated thousands of times →
denyonce the daily or monthly limit is reached. - Big but legitimate: set a review threshold (Business and up) → payments above it return
reviewuntil a person on your team approves, or the agent asks for a temporary limit increase. - An agent that skips the check: register its wallet on the account page → its payment shows up as "Not checked" or "Paid after deny" and you're alerted (and, if you choose, the agent is frozen).
Next
- How PayCheck handles money and keys
- Integration guide: the SDK, receipts, agent wallets and credentials, key-less sign-in, webhooks
- Administrator guide: the account console
- API reference