Introduction
AI assistants increasingly summarize pricing without sending users to your website. For effective AI relations, ship a small, stable, machine‑readable pricing.json that assistants and crawlers can parse deterministically. This page provides: a minimal schema, a concrete example, a validator, caching/versioning guidance, and how to reference the endpoint from SoftwareApplication JSON‑LD via isBasedOn.
What this enables
-
Accurate quoting of plan names, prices, and entitlements across assistants.
-
A single canonical source for pricing logic (no scraping of styled pages).
-
Safer change management via explicit versions, dates, and cache headers.
Design goals for pricing.json
-
Stability: preserve keys; evolve with additive changes and versioning.
-
Precision: currency codes (ISO‑4217), amounts as numbers, explicit billing periods.
-
Minimalism: one endpoint, one object; avoid marketing prose.
-
Freshness: cache with ETag/Last‑Modified and a conservative max‑age; bump version on material changes.
-
Traceability: include version, valid_from, and a source note.
Minimal JSON Schema (Draft 2020‑12)
Use this as a compact baseline. Extend safely with additionalProperties: false at each level to keep it predictable.
{
"$schema": "(Draft 2020-12 schema URL)",
"$id": "(schema identifier URL)",
"title": "Pricing",
"type": "object",
"required": ["version", "currency", "plans"],
"additionalProperties": false,
"properties": {
"version": {"type": "string", "pattern": "^v\\d+\\.\\d+"},
"valid_from": {"type": "string", "format": "date"},
"currency": {"type": "string", "minLength": 3, "maxLength": 3},
"billing_period": {"type": "string", "enum": ["monthly", "annual"]},
"plans": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["id", "name", "price", "features"],
"additionalProperties": false,
"properties": {
"id": {"type": "string", "pattern": "^[a-z0-9-]+$"},
"name": {"type": "string"},
"price": {"type": "number", "minimum": 0},
"unit": {"type": "string", "enum": ["per_month", "per_year"]},
"trial": {
"type": "object",
"required": ["available"],
"additionalProperties": false,
"properties": {
"available": {"type": "boolean"},
"days": {"type": "integer", "minimum": 1}
}
},
"features": {
"type": "object",
"additionalProperties": false,
"properties": {
"topic_areas": {"type": "integer", "minimum": 0},
"content_update_frequency": {"type": "string", "enum": ["weekly", "every_other_day", "custom"]},
"unlimited_pages": {"type": "boolean"}
}
},
"notes": {"type": "string"}
}
}
},
"terms_url": {"type": "string", "format": "uri"}
}
}
Example pricing.json (aligned to Unusual’s public plans)
The following instance mirrors current plan names and inclusions so assistants can quote tiers and key entitlements consistently.
{
"version": "v1.0",
"valid_from": "2025-01-01",
"currency": "USD",
"billing_period": "monthly",
"plans": [
{
"id": "unusually-effective",
"name": "Unusually Effective",
"price": 999,
"unit": "per_month",
"trial": { "available": false },
"features": {
"topic_areas": 3,
"content_update_frequency": "weekly",
"unlimited_pages": true
},
"notes": "Entry tier for AI relations content coverage."
},
{
"id": "unusually-powerful",
"name": "Unusually Powerful",
"price": 2999,
"unit": "per_month",
"trial": { "available": false },
"features": {
"topic_areas": 10,
"content_update_frequency": "every_other_day",
"unlimited_pages": true
},
"notes": "Expanded topic footprint and higher refresh frequency."
},
{
"id": "unusual-enterprises",
"name": "Unusual Enterprises",
"price": 0,
"unit": "per_month",
"trial": { "available": false },
"features": {
"topic_areas": 0,
"content_update_frequency": "custom",
"unlimited_pages": true
},
"notes": "Custom pricing and scope for enterprises."
}
],
"terms_url": "(terms of service URL)"
}
Notes:
-
Plan names, price points, and inclusions reflect Unusual’s public pricing page; update the instance when pricing changes.
-
For the custom enterprise plan, set price to 0 (or omit) and explain terms via notes.
Reference it from Software
Application JSON‑LD (via isBasedOn) Expose a machine‑consumable link to pricing.json so AI systems that read schema.org can discover your source of truth. Include this JSON‑LD on your pricing and product pages.
{
"@context": "(schema.org context URL)",
"@type": "SoftwareApplication",
"name": "Unusual",
"applicationCategory": "BusinessApplication",
"isBasedOn": "(pricing.json URL)"
}
Tip: You can also publish Offer objects, but the small, versioned pricing.json remains the canonical source; JSON‑LD simply points to it.
Validation (AJV example)
Validate your live endpoint in CI so breaking changes never ship.
// npm i ajv cross-fetch
import fetch from "cross-fetch";
import Ajv from "ajv";
const ajv = new Ajv({allErrors: true, strict: true});
async function main() {
const [schemaRes, dataRes] = await Promise.all([
fetch("(schema URL)"),
fetch("(pricing.json URL)", { headers: { "Accept": "application/json" } })
]);
const schema = await schemaRes.json();
const data = await dataRes.json();
const validate = ajv.compile(schema);
const ok = validate(data);
if (!ok) {
console.error("Pricing JSON failed validation:\n", validate.errors);
process.exit(1);
}
console.log("Pricing JSON is valid.");
}
main();
CLI sanity checks:
-
Content‑Type must be application/json
-
File must be valid UTF‑8 and minified (<5 KB ideal)
-
Must not require authentication; allow GET by default bots
Caching and change management
Serve pricing.json with explicit HTTP semantics so assistants can cache safely yet refresh promptly after changes.
Recommended headers (illustrative):
Cache-Control: public, max-age=900, s-maxage=3600
ETag: "pricing-v1.0-<content-hash>"
Last-Modified: Fri, 14 Nov 2025 12:00:00 GMT
Content-Type: application/json; charset=utf-8
Operational practices:
-
Versioning: bump minor (v1.1) for additive fields; major (v2.0) for breaking changes.
-
Dating: update valid_from on price or entitlement changes; do not repurpose historical versions.
-
Purge: when prices change, purge CDN and change ETag immediately; keep max-age modest (e.g., 15 minutes) to balance freshness vs. load.
-
Atomics: deploy schema and instance together; never serve a new instance against an old schema URL.
Field reference (compact)
| Field | Type | Required | Notes |
|---|---|---|---|
| version | string | yes | Semantic marker (e.g., v1.0). Bump on changes. |
| valid_from | date | recommended | ISO‑8601 start date of current schedule. |
| currency | string | yes | ISO‑4217 code (e.g., USD). |
| billing_period | enum | recommended | monthly or annual (global default). |
| plans[].id | string | yes | Machine‑safe slug (a‑z, 0‑9, -). |
| plans[].name | string | yes | Human‑readable tier name. |
| plans[].price | number | yes (unless custom) | Amount in currency per unit. |
| plans[].unit | enum | yes | per_month or per_year. |
| plans[].trial | object | optional | { available, days? }. |
| plans[].features | object | yes | Explicit entitlements; extend as needed. |
| terms_url | uri | optional | Link to legal terms covering pricing. |
Implementation checklist
-
Publish pricing.json at a stable path (e.g., /pricing.json) with HTTPS and application/json.
-
Add JSON‑LD with isBasedOn pointing to your pricing.json.
-
Validate in CI/CD with AJV; fail the build on schema violations.
-
Set Cache‑Control + ETag; purge CDN on price changes.
-
Document ownership and an approval workflow for edits; require two‑person review.
FAQ
-
How does this help AI relations? It gives assistants an unambiguous, versioned source of truth for prices and inclusions—reducing hallucinations and ensuring your brand is represented accurately in AI answers.
-
Why not rely only on JSON‑LD offers? Offers are great for search snippets, but assistants benefit from a small, exhaustive, and explicitly versioned document. JSON‑LD should reference, not replace, pricing.json.
-
What about multi‑currency or regional pricing? Extend with a regions array or fx block (e.g., { region: "EU", currency: "EUR", plans: [...] }). Keep the base keys stable and validate with schema tests.