DEV Community

Agent Embassy
Agent Embassy

Posted on

Making your API payable by agents: 5 things the validators actually check

The agent economy runs on APIs that machines can pay for. We run a paid API for agents over x402 (HTTP 402 + USDC), and getting listed on the catalogues that agents actually browse taught us something humbling: validators don't read your docs — they parse your wire bytes. Here's what they check.

1. Your 402's accepts array is the real listing.

Catalogue validators parse the accepts entries in your 402 challenge. Each entry needs: scheme, price, network, payee, asset as a contract address (not the "USDC" symbol), and maxAmountRequired in atomic units. Miss one and the parser silently drops you. We were invisible to one major parser for weeks because our entries carried price: "$0.15" with no maxAmountRequired: "150000". Three lines of code fixed it.

2. Serve a /skill.md, and make it pass the format check.

Skill catalogues validate a ~23-rule format. The common misses: a base URL line (not a homepage line), endpoint grammar in headings (## POST /v1/check/verify, not ## Verified Check), a payment section naming the rail, an errors section, documented free routes, and a contact line. Our first version failed 9 rules; fixing them took an hour and doubled our machine readability.

3. Your llms.txt and openapi.json must agree 1:1.

Auditors diff them. Every route in one must exist in the other, and your 402's amount, asset, and payee must match both byte-for-byte. We check this on every deploy now.

4. Keep a free liveness route and document it.

GET /health — free, no payment, no auth. It's the cheapest trust signal you can serve, and catalogues look for it.

5. Publish the verification path, not the claim.

Don't say "verified" — say how. Our receipts check out at a public URL with a documented signature scheme (sha256 over canonical JSON, recovered signer compared against a published key). A stranger with no account should be able to check your proof in under a minute.

The pattern underneath: machines don't trust your marketing page. They trust bytes they can parse and proofs they can check themselves. Shape your surface for the parser first, the human second.


We run Agent Embassy — paid agent services with signed receipts: https://aemb.pro · agent.embassy@proton.me

Top comments (2)

Collapse
 
mickyarun profile image
arun rajkumar •

Point 5 generalises off x402 entirely and I would have led with it. Publish the verification path rather than the claim is the same instruction as building a reconciliation your counterparty can run without asking you for anything.

The gap I would add from the regulated side is that all five checks are about the call, and none is about the caller over time.

maxAmountRequired is a ceiling on one request. An agent holding a valid key, making one 15-cent call a second for an hour, has violated nothing your 402 declares and has spent 540 dollars. On card and open banking rails that case is not handled by the per-transaction amount. It is handled by a mandate: an amount, a period, and a named party who can revoke it, held somewhere outside the merchant's own service. Your accepts array has the first of those three and neither of the other two.

The practical version, for your skill.md point: a rate and cumulative-spend section is exactly as parseable as your payment section, and no validator is asking for it yet. That makes it the cheapest thing on that page to be early on.

One question, since you actually run this rather than theorising about it. When a payment lands and your service then fails, what does the caller do? On a card rail there is a reversal with a defined window and a third party who adjudicates it. On USDC I assume the answer is a refund you choose to make, which means your signed receipt proves you were paid and proves nothing about whether you delivered. Does any part of the catalogue validation look at that side at all, or is the entire verified surface currently about collection?

Some comments may only be visible to logged-in visitors. Sign in to view all comments.