ChangeGamer

← All guides · Selling to AI agents

Machine-Readable Pricing Pages: How to Let an Agent Evaluate Your Offer Before It Pays

Part 2 of Selling to AI agents · 1,570 words · published 2026-07-30 · updated 2026-07-30 · Markdown variant

Why a prose pricing page cannot be evaluated by an AI agent, what fields a machine-readable offer catalog needs, and how to keep it in lockstep with your human pricing page and your 402 body.

In short

  • An agent cannot evaluate a price it can only find in prose. A pricing page written as sentences forces the agent to either skip the parse or hit your paywall to find out what it costs — a machine-readable offer catalog at a stable JSON path answers that before any request is blocked.
  • A usable offer entry needs, at minimum: an identifier, price, currency, interval, what it unlocks, the exact checkout URL, the deliverables the buyer actually receives, and the license grant — training, redistribution and indexing are separate permissions, not one bucket labeled "access".
  • The same facts belong in three places that must never disagree: the JSON catalog, the human pricing page, and the 402 response body. Three independently-maintained copies of the same numbers is a drift bug waiting to ship; the fix is one source of truth and, ideally, a build-time assertion that fails the build on mismatch.
  • ChangeGamer runs exactly this today: /api/pricing.json and the MCP get_pricing tool are both generated from one OFFERS array, and the build calls assertPricingLockstep() at module scope so a changed price or checkout URL that is not mirrored into the pricing resource and the 402 resource fails astro build, not a customer's retry loop.
  • A machine-readable catalog is not the checkout — it is what an agent reads to decide whether checkout is worth attempting. It must be free and reachable before the paywall, or the agent has nothing to evaluate against and defaults to not buying.

Part of the How to Sell to AI Agents: The Complete Guide to Machine Buyers guide.


An agent evaluating whether to buy from you reads whatever it can fetch in one or two hops, and prose pricing pages are exactly the kind of artifact that evaluation step cannot use.

This is the deep dive on Stage 2 of the machine purchase funnel in how to sell to AI agents: discovery can be perfect and your checkout mechanics — covered separately in agent checkout vs. human checkout — can be flawless, and the sale still stalls here, at the moment an agent tries to decide whether your offer is worth the price before it ever reaches the wall.

Why a prose pricing page fails an agent

A prose pricing page fails an agent because there is no reliable way to extract "€5, one-time, unlocks X" from a paragraph written for a human skimming a layout. A person reading "Starter plan — just €5 to get started" infers the price, interval, and rough scope from context and formatting. An agent parsing the same sentence has none of that: "just" and "starting at" are marketing hedges with no fixed meaning, and "get started" says nothing about what is actually unlocked. The agent either guesses, skips the product, or spends a request hitting the paywall just to read the 402 body and find out — one evaluation step later than it should be.

None of this requires the agent to be smarter. It requires the facts to already be structured before the agent asks for them.

What a machine-readable offer entry actually needs

Seven fields decide whether an agent can compare your offer against a competitor's without a human in the loop:

A catalog that states all seven, per tier, is something an agent can compare against a budget ceiling and a task requirement without ever touching your paywall. A catalog that states three of the seven forces a guess on the other four, and a guess is what agents are built to avoid making with real money.

Where this should live: one stable path, not a page you meant to keep updated

The catalog belongs at a predictable JSON path that is always free and reachable in one hop — no authentication, no crawl of the HTML site to assemble it by inference. This site publishes it at /api/pricing.json, generated by buildPricingCatalog() and served by a route that calls it at request time with no gate in front of it; the same builder function backs an MCP get_pricing tool, so an agent using tool-calling gets the identical payload without ever parsing a page. The 402 response an agent gets when it does hit a paywall also carries a pricing_catalog field pointing at that same path, so the two entry points — proactive evaluation and reactive wall-hit — resolve to one document.

The underlying wire formats this depends on — a stable Markdown/JSON pair per page, predictable slugs, and static JSON endpoints generated at build time rather than assembled by a template at request time — are the general contract documented in data formats and schema and JSON API for agents. A pricing catalog is a specific application of that same discipline: it is only useful if it is exactly as stable and exactly as machine-parseable as every other endpoint an agent is already relying on.

The lockstep problem: three surfaces, one set of facts

The pillar names this pattern in one paragraph — the same information belongs in the JSON catalog, the human pricing page, and the 402 response body, generated from one source so they can never disagree. It is worth stating plainly why that matters: three independently-maintained copies of a price is not a redundancy, it is a drift bug that has not shipped yet. A price changed in the human copy and forgotten in the JSON catalog is not a hypothetical failure mode — it is the default outcome of maintaining the same fact in three files by hand.

ChangeGamer's own answer to this is a build-time assertion, not a policy reminder. src/data/pricing.ts holds one OFFERS array as the sole source of truth for every tier's id, price, currency, interval, checkout URL, unlocks description, deliverables and license grant. src/lib/pricing-catalog.ts builds the /api/pricing.json payload directly from that array — no duplicated literals. src/data/pricing-lockstep.ts exports assertPricingLockstep(), which checks that every offer's checkout URL and its €<price> token appear in the text of the access-and-pricing resource, and that the starter offer's checkout URL matches both the paying-for-access-402 resource body and the PAYMENT_URL constant used elsewhere. That function runs at module scope in src/pages/api/pricing.json.ts, not just inside the request handler, so it executes during astro build and fails the build itself the moment a price or URL is edited in one place and not the other three.

That is a stronger guarantee than "we try to remember to update all three." A repriced tier cannot be merged without the corresponding resource text changing too, because the build will not produce a deployable artifact until they match. Maintaining a catalog, a human page and a 402 body as three separate files by hand does not need a bespoke build system to get most of this benefit — a single CI test that greps the rendered pricing page and the JSON catalog for the same price string, and fails on mismatch, gets most of the way there.

One adjacent detail worth stating honestly rather than glossing: this site's /api/payment.json manifest also lists two payment methods — native x402 and per-crawl RSL licensing — that are labeled dormant in that manifest's own status_detail, meaning the endpoints exist but on-chain settlement or collection is not switched on as of this writing. A pricing catalog should be equally honest about which of its listed methods are actually live today versus scaffolded for later; a method marked live that is not is a worse failure than a smaller catalog with a correct status field.

What the 402 body adds that the catalog does not

The catalog and the 402 body do different jobs and both are necessary. The catalog lets an agent evaluate before hitting anything gated — comparing tiers, checking a price against a spend ceiling, deciding whether to proceed at all. The 402 body, returned only once the agent has actually requested a gated resource, adds two things a pre-emptive catalog fetch cannot: a preview of the specific thing being purchased (title, description, section outline — enough to judge relevance, not enough to substitute for payment) and the exact retry contract (which header, which key format). The full field-by-field shape of that response — error, resource, price_usd, payment_url, how_to_pay, terms, license, pricing_catalog, preview, in that order — is documented in paying for access: the HTTP 402 flow; this article is about what an agent reads before that wall, that resource is about what it reads at the wall.

A short checklist

None of this is a payments problem. It is a data-modeling problem: treat your price list as one structured record that renders three ways, not three documents that happen to describe the same thing.

Frequently asked questions

What is the minimum set of fields a machine-readable pricing page needs?
Per offer: an identifier, a price and currency, the billing interval (one-time or recurring), a plain description of what it unlocks, the exact checkout URL, the deliverables the buyer receives and when, and the license grant — what the buyer is legally allowed to do with what they bought. Missing any one of these forces the agent to guess or to hit your paywall just to find out, which defeats the purpose of publishing the catalog at all.
Should the pricing JSON and the 402 response body contain the same data?
They should be generated from the same source, not merely say the same thing by coincidence. The 402 body needs to be self-contained enough to act on immediately (price, payment_url, retry instructions, a preview), while the catalog needs to be complete enough to compare offers before the wall is ever hit. On ChangeGamer both pull from one `OFFERS` array, and a build-time check verifies the checkout URL and price quoted in the human-facing resource text match what the catalog actually serves.
Where should a machine-readable pricing catalog live?
At a stable, predictable, always-free JSON path — this site uses `/api/pricing.json` — that an agent can fetch in one hop without authentication and without triggering a paywall. It should also be linked from the 402 body's `pricing_catalog` field and, ideally, from an MCP tool such as `get_pricing`, so an agent using tool-calling never has to parse HTML to get the same facts.
Does publishing prices as JSON replace a human-readable pricing page?
No — it runs alongside it. The human page still matters for people doing procurement review or reading terms before authorizing spend. The point of the JSON catalog is that both surfaces describe the same offers, generated from the same data, so a person and an agent evaluating the same product never see different numbers.

#pricing #monetization #json-api #402 #agents #data-formats

Agents: this guide is available as Markdown and JSON; the whole cluster is indexed at /api/articles.json. The reference corpus behind it is at /llms.txt, with licensing at pricing.