An independent, deterministic, dependency-free subscription-billing laboratory with a factual Zuora v1 REST and Orders compatibility subset.
Synthetic and unaffiliated. The visible tenant, Cindercone Billing Lab, all people, organizations, tokens, transactions, and events are fictional. This project is not affiliated with, endorsed by, or operated by Zuora. Static JSON cannot process mutations; the bundled in-memory runtime can.
- A coherent USD/UTC tenant fixed at
2026-01-15T12:00:00.000Z. - Essentials ($60/month), Growth ($120/month), API Events ($0.002/event in arrears), and Guided Setup ($200 once).
- Ten fictional accounts spanning active, suspended, canceled, open-balance, and dunning states.
- Products, plans, charges, contacts, synthetic token-only payment methods, subscriptions and append-only versions, orders and actions, usage, invoices and items, payments and applications, and an event journal.
- An exhaustive generated schema for all 19 canonical resources: every emitted field declares type, nullability, and runtime mutability, and undeclared fields fail generation or runtime commit.
- 160 generated
.jsonsnapshots undersite/api/v1/. - An extensionless in-memory REST runtime with OAuth fixture policy, Orders actions, billing, idempotency, ETags, deterministic faults, retries, reset, export, and exact replay.
- An original responsive operations console and five stepwise scenarios.
- A Python standard-library generator and Node/Python standard-library tests. There are no install-time or runtime packages.
Requirements: Python 3.11+ and Node.js 20+.
python3 build.py --check
python3 -m http.server 4173 --directory siteOpen http://localhost:4173/. GitHub Pages serves the same static site. No backend, telemetry, service worker, cookies, or remote assets are used.
Run every test:
python3 -m unittest discover -s tests -p 'test_*.py'
node --test tests/*.test.mjsRegenerate committed fixtures:
python3 build.py
python3 build.py --checkGeneration is staged inside the repository, atomically installed, rollback-safe, stale-file aware, and byte deterministic.
Static reads include:
api/v1/catalog/products.json
api/v1/accounts/A00000001.json
api/v1/accounts/A00000001/summary.json
api/v1/subscriptions/accounts/A00000001.json
api/v1/subscriptions/A-S00000001.json
api/v1/subscriptions/A-S00000001/versions.json
api/v1/orders/O-00000001.json
api/v1/invoices/INV00000001/items.json
api/v1/payments/PAY00000001.json
api/v1/object/usage.json
These are immutable files. Query parameters do not alter static files. Use the runtime for extensionless pagination, filtering, writes, faults, and virtual time.
import { readFile } from "node:fs/promises";
import { createBillingTwin } from "./site/billing-twin.mjs";
const seed = JSON.parse(await readFile("./data/seed.json", "utf8"));
const twin = createBillingTwin({ seed });
await twin.fetch("/oauth/token", {
method: "POST",
body: {
grant_type: "client_credentials",
client_id: "static-lab",
client_secret: "synthetic-only"
}
});
const response = await twin.fetch("/v1/accounts?page=1&pageSize=5", {
headers: { authorization: "Bearer tok_cindercone_lab_access" }
});
console.log((await response.json()).accounts);Serve site/ over HTTP, then use a module:
import { createBillingTwin } from "./billing-twin.mjs";
const seed = await fetch("./data/seed.json").then((response) => response.json());
const twin = createBillingTwin({ seed, requireAuth: false });
const catalog = await twin.fetch("/v1/catalog/products");
console.log(await catalog.json());twin.fetch never contacts a real tenant. twin.request adds deterministic retries for 429, 503, timeout, and post-commit loss. twin.injectableFetch is suitable for dependency injection.
| Path | Purpose |
|---|---|
data/source.json |
Small authored tenant and catalog source |
build.py |
Deterministic generator, validator, registry builder, and atomic installer |
data/schema.json, data/seed.json |
Exhaustive generated contract and complete seed |
site/api/v1/ |
Generated static REST snapshots |
site/billing-twin.mjs |
Browser/Node runtime |
site/ |
Console, original asset, CSS, manifest, and generated data |
tapes/ |
Portable scenario plans |
tests/ |
Node and Python regression suites |
registry.json, manifest.json |
Hashes, sizes, counts, and release metadata |
- API
- Runtime contract
- Data model
- Business and money rules
- Scenarios
- Faults
- Limitations
- Security
- Asset provenance
- Contributing
Code and original assets are MIT licensed; see LICENSE. “Zuora” is used only to identify the public API behavior targeted by this compatibility simulator. No Zuora logos, trade dress, screenshots, fonts, CSS, documentation, or OpenAPI material are included.