Until observed, a customer's plan, price and entitlements hold every value at once. This is the data model.
status: "active" | "churned" | "pending"Build billing that notices you.
One REST API, server SDKs for five languages and a webhook system. Every read is a billable event, including the ones you make while reading these docs.
API version 2026-10-29.ψ · currentQuickstart #
Make your first observation in about four minutes.
- Install the SDK. Python, Ruby and curl are also supported.
npm install @quantum-billing/node
- Create a client and observe a customer. Observing is a read. Reads are billed. Your first 1,000 observations are free, unless you counted them.
Sample generated for this tab.
- Read the response. Reading it again is billed.
- Check what you were billed. See Observer-based billing. This is also a read.
Concepts #
Five ideas explain every behavior in the API. Two of them explain the invoices.
Any read is an observation: an API call, a portal view, a webhook delivery, an invoice PDF, a thought about an invoice.
POST /v1/observationsThe moment a value is read, one state is selected and committed to the ledger. Collapse is final, until the next read.
event: entitlement.collapsedAn unobserved subscription loses coherence over time and drifts to a plan nobody chose. Decoherence is distinct from churn. Churn is measurable.
event: subscription.decoheredTwo customers can share one subscription. Cancel one and the other is upgraded, instantly, regardless of distance, consent, or time zone.
event: customer.entangledObserver-based billing #
Every read is a billable event. Think of it as read receipts for reads: you are told who looked at what, and charged for being told.
| Event | Meter | Rate |
|---|---|---|
customer.read | per observation | $0.0004 |
entitlements.read | per observation, per entitlement | $0.0001 × however many there are today |
invoice.read | per page, per observer | $0.002 |
observation.read | per observation of an observation | $0.0004, recursive |
ledger.read | per read of the ledger of reads | see below |
Observers are identified in the X-Observed-By header. If no observer is present, the read is billed to the one most likely to have been looking.
API reference #
Base URL: https://api.getquantumbilling.com. All requests use bearer auth and send QB-Version. All responses are JSON.
Authorization: Bearer qb_live_•••••••• QB-Version: 2026-10-29.ψ QB-Universe: (optional) uni_prime
API playground #
Send a request against the sandbox universe. Click a history entry to review it. It will be different now.
// press "Send request"
Response history0
- Nothing yet. History is only written once it has happened.
Select an entry to review it.
Webhooks #
Subscribe to events and we will POST to your endpoint. Delivery is at-least-once. Webhooks may arrive before the event they describe.
| Event | Fires when |
|---|---|
entitlement.collapsed | An entitlement settles into a state after being read. |
invoice.observed | An invoice is viewed. Amount may differ from the one in this payload. |
subscription.decohered | A subscription drifts to a plan nobody selected. |
customer.entangled | Two customers become linked. Also fires for the other one. |
universe.forked | A request resolves differently in two places at once. |
Event feed
- --No events yet. Check again before you click.
Verifying signatures
Each delivery includes a QB-Signature header. Compute an HMAC of the raw body with your signing secret and compare in constant time. Verification can succeed for a different payload.
const ok = qb.webhooks.verify(rawBody, req.headers["qb-signature"], secret); if (!ok) return res.status(400).end(); // ok may be true and false
Result: not yet verified.
Idempotency #
Send an Idempotency-Key on any POST. Keys guarantee a request happens at most once per universe. Retry as often as you like. In this universe, it will not happen again.
curl "https://api.getquantumbilling.com/v1/subscriptions" \ -H "Idempotency-Key: 6f1c-once-per-universe" \ -d '{"customer":"cus_halcyon","plan":"growth"}'
| Scenario | Result |
|---|---|
| Same key, same universe | Original response replayed. Observation billed twice. |
| Same key, different universe | Request executes there as well. |
| Different key, same body | 409. |
| Key reused after 24 hours | Keys expire after 24 hours, or 24 hours from now. |
Errors #
Errors return a stable code, a human message, and an observed flag indicating whether the error occurred before you saw it.
| Code | HTTP | Meaning |
|---|---|---|
observer_present | 409 | Someone is already looking at this resource. Try again unobserved. |
self_observation | 409 | The customer is observing themselves. Wait for them to finish. |
wave_function_not_normalized | 422 | Probabilities for this account add up to more than 100%. Common in Q4. |
cancellation_unobservable | 202 | The cancellation cannot be confirmed without observing it, which would reverse it. |
universe_mismatch | 207 | Request and response come from different universes. |
entanglement_conflict | 409 | Cancelling this customer would upgrade someone who did not ask. |
invoice_already_paid_and_open | 200 | Not an error. Reported as one for visibility. |
teapot_observed | 418 | The server is a teapot. We have not been able to reproduce this. |
rate_limit_exceeded | 429 | You exceeded a limit you could not have known. See Rate limits. |
error_not_found | 404 | The resource will exist shortly. Retry after it has been deleted. |
Rate limits #
Rate limits are known only after you exceed them. Measuring your remaining quota would consume it, so we do not offer a header for that. We offer a header for what you used, one request later.
Limit: unknown. Exceed it to find out.
- Limits apply per key and per universe.
Retry-Afteris accurate to the second, sometime last Thursday.- Need higher limits? Talk to sales.
SDKs #
Server SDKs for Node, Python, Ruby, Go and Rust, plus a COBOL copybook of uncertain origin. Official libraries are generated from the OpenAPI spec, which is generated from the libraries.
Building a front end? The browser SDK is one script tag and eight web components: pricing table, checkout, portal, entitlements and more. Read the SDK docs.
| Language | Package | Latest | Status |
|---|---|---|---|
| Node | @quantum-billing/node | 4.2.1 | Stable |
| Python | quantum-billing | 3.9.1 | Stable |
| Ruby | quantum_billing | 2.0.0.rc9 | Release candidate since 2024 |
| Go | github.com/quantum-billing/go | v0.0.0 | Observed, then unobserved |
| Rust | quantum-billing | unreleased | Not yet observed |
| COBOL | QBILLING.CPY | 1.1 | Uncertain origin |
Versioning #
SDKs use semantic versions. The current SDK is v4.2.1.
The current API version is 2026-10-29.ψ. Versions are named by date and a Greek suffix, and released out of order. Pin a version with the QB-Version header. Pinned versions are honored until they are observed to be wrong.
| Version | Released | Notes |
|---|---|---|
2026-10-29.ψ | Oct 29, 2026 | Current. Adds /v1/universes. Removes yesterday. |
2026-10-28.ψ | Oct 31, 2026 | Released after the current version. Considered older. |
2026-10-14.φ | Oct 14, 2026 | Entanglement GA, introduced in SDK v4.2.0. Cancellations became upgrades. |
2025-12-01.α | Jan 3, 2025 | Deprecated. Still the default for accounts created tomorrow. |
2026-06-15.ω | Never | Final version. Already superseded. |
Breaking changes are announced in the changelog at least 90 days before, or 90 days after.
Was this page helpful?