BillKit/DocsConsole
Policies

Versioning and compatibility

The v1 API changes only in ways a correctly written integration absorbs. This page is the contract that says which changes those are, and what your code has to tolerate in return.

Updated Oct 14, 2026·OpenAPI v1.0.0

BillKit has one version of its API, v1, and it is the path prefix on every request. There is no version header to send and nothing is pinned per account, so every key talks to the same API. What keeps that safe is a compatibility contract: v1 only grows. Anything that would break a correctly written integration is either not made, or made under the deprecation policy with notice.

The contract took effect with 1.0, on 14 October 2026, the release in which the SDKs and the billkit CLI reached 1.0.0. The changes listed under 1.0 in the API changelog are the last ones made outside it.

What the contract covers

SurfaceCovered
REST APIEvery /v1 operation in the published OpenAPI document: paths, methods, parameters, request bodies, response bodies, status codes and the error envelope.
WebhooksThe event envelope, the event types and their data objects, the delivery headers, and the BillKit-Signature scheme.
SDKsThe documented, exported surface of each of the six SDKs: client construction, resource methods and their parameters, error classes, and the webhook verification helpers.
CLIThe billkit commands, their flags, the environment variables they read, exit codes, and what goes to stdout versus stderr.

Not covered: the console, the billing portal, the embedded checkout iframe’s own routes, and any route absent from the published OpenAPI document. Those serve BillKit’s own front ends and change with them. SDK internals are not covered either: anything not exported from the package entry point, any module or member whose name starts with an underscore, and anything marked internal in its documentation. The CLI’s human-readable stderr wording is not covered; parse stdout, which carries only the command’s output: the API’s JSON for every command that calls the API, and the formats the CLI reference lists for the rest.

Changes that can happen at any time

These are additive. They ship without notice and without a new version, and an integration that follows the rules further down keeps working through all of them.

  • New endpoints, and new HTTP methods on existing paths.
  • New optional request parameters, and new optional fields inside request bodies.
  • New fields on response objects, including on nested objects and inside data on events. A field added after 1.0 is published as optional in the OpenAPI document even though new responses always carry it, because older events and replays may lack it (see below).
  • New event types, and new types in the webhook endpoint catalogue. The event type list in the webhooks reference is the current list, not a complete one; an integration must not treat it as exhaustive.
  • New values in any enum. That includes every status, every payment method, type, code and reason on errors, refusal and failure reasons, and the values of any other field documented as a fixed set.
  • New response headers, and new webhook delivery headers.
  • New expansions for ?expand=.
  • Longer object ids. The prefix is stable; the length and the characters after it are not.
  • A different order of keys in a JSON object, and of headers in a response.
  • Wording of message on errors and of any other human-readable text.
  • The values of rate limits. Rate limits and the X-RateLimit-* headers always state the current ones.

Changes that will not happen in v1

None of these is made to the covered surface without a deprecation under the deprecation policy, and most cannot be made in v1 at all.

  • Removing or renaming a field, an endpoint, an event type, a request parameter or an error code.
  • Changing a field’s type, including integer to string and object to array.
  • Changing whether a field is null or absent. A field documented as always present and nullable stays that way; a field documented as omitted when empty stays omitted.
  • Making an optional request parameter required, or adding a new required one.
  • Narrowing the values a request parameter accepts, or tightening its validation, except where the old value was already documented as invalid.
  • Changing the meaning of an existing enum value. A past_due subscription keeps meaning what Subscriptions says it means.
  • Changing the error envelope, the list envelope (object, data, has_more) or cursor pagination.
  • Changing an object id prefix, such as cus_ or evt_.
  • Changing what the v1 signature in BillKit-Signature signs or how it is computed.

What your integration has to do

The contract runs both ways. The additive changes above are only harmless to code that tolerates them, and each rule below names the change it protects you from.

RuleWhy
Ignore response fields you do not recognise.New fields arrive without notice. Do not validate responses against a closed schema, and do not fail deserialisation on an unknown key.
Treat a field added after 1.0 as optional.An event is stored once and sent as it was recorded: a webhook retried for up to three days, GET /v1/events and a replay of the event stream return older events in their older shape, and an idempotent replay returns the response stored on the first call for 24 hours. A field added after 1.0 can be missing from all of those. The OpenAPI document says so: fields added after 1.0 are optional in the schema, and every field that was in 1.0 stays required.
Treat every enum as open.A status, method, code or reason you have never seen must fall into a default branch, not throw. Log it and handle it as the most cautious case.
Ignore event types you do not handle.New event types are additive and ship without notice, so do not treat the list of types as exhaustive or reject a type you do not know. Answer 2xx to any event type you do not recognise. A non-2xx answer makes BillKit retry the delivery until its retry window runs out, and records every attempt as a failure.
Ignore signature schemes you do not recognise.BillKit-Signature may carry entries other than t and v1 in future. Verify the v1 entries and skip the rest. The SDK helpers already do.
Branch on code, then reason; never on message.Codes are stable identifiers. Messages are English prose and are reworded freely. For a code you do not know, fall back on the HTTP status class.
Deduplicate events by id.Delivery is at least once. The same evt_ id can arrive more than once, and should be processed once.
Do not rely on webhook ordering.Deliveries are not ordered. Read the object from the API, or compare timestamps, when order matters.
Do not parse ids.Store them as opaque strings of up to 255 characters. Only the prefix is meaningful.

Build a robust integration turns these rules into a webhook handler.

Exceptions

Two kinds of change can break the contract without the usual notice.

  • Security fixes. If keeping a behaviour would expose your data or your customers’ money, it is changed as soon as the fix is ready. Where possible the change is narrowed to the unsafe case.
  • Behaviour that contradicts the documentation. Where the API does something the reference says it does not, the API is corrected to match the documentation. Where the documentation is the thing that is wrong, the documentation is corrected instead and the behaviour stays.

Both are recorded in the API changelog when they ship, with what changed and what to do about it.

How it is enforced

From 1.0, CI compares the published OpenAPI document, webhook payloads included, against a frozen baseline of the 1.0 v1 surface on every change. A change that is not additive against that baseline fails CI, and has to be made additive or taken through the deprecation policy. The check fails on:

  • a removed operation or webhook event type, a removed response or event payload field, required or optional, or a removed webhook delivery header such as BillKit-Signature;
  • a field whose type changes, or a required response field made optional or nullable;
  • a new required request field or query parameter, or a removed one;
  • a narrowed request parameter: an enum value removed, a maximum lowered, a pattern added;
  • a changed or removed default on a request parameter or request body field;
  • a changed authentication requirement or operationId on an operation;
  • a removed or renamed schema, a removed error status on an operation, or a renamed path parameter, each of which renames or removes something a generated SDK exports;
  • a value removed from an open enum, a rename included;
  • a change to the API-key scope an operation requires (each operation publishes it as x-required-scope).

Some of the promises above are not visible in an OpenAPI document, and those are kept by review rather than by the check: the meaning of a field or enum value, object id prefixes, the BillKit-Signature scheme, validation tightened in code without a schema change, and the SDK and CLI surfaces.

The snapshots on the OpenAPI page are named by version. The 1.0.0 snapshot is the 1.0 release, and every later snapshot of v1 is compatible with it in the sense this page defines. The older dated snapshot is 0.x, from before the contract, and is not compatible with 1.0.