API versioning & changelog policy
The partner API versions by date, Stripe-style: 2026-09-22, the current
version, is the baseline the whole app platform launched on.
Resolving a request’s version
Section titled “Resolving a request’s version”Three ways a request’s version is decided, in priority order:
- An explicit
OneBooks-Versionrequest header. - Your app’s pinned version, set in the console (defaults to unset).
- The current version, if neither of the above is set.
Every response echoes the resolved version back in an OneBooks-Version
header, so you can always confirm what you got — including from code that
didn’t set the header itself.
curl -s https://api.getonebooks.com/invoices \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "OneBooks-Version: 2026-09-22"A version that doesn’t exist, or one that’s past its sunset date, is rejected:
{ "statusCode": 400, "code": "UNSUPPORTED_API_VERSION", "message": "This OneBooks-Version is not supported. See the API versioning guide for the supported versions."}Pinning
Section titled “Pinning”New apps should pin explicitly once you’ve integrated against a version, rather than floating on “whatever is current” — that way a future breaking release doesn’t change your app’s behavior until you decide to move. Pin on your app’s Overview tab in the console, under API version (org admins only). Pinning is per-app, not per-request; the header is for cases like testing an upcoming version ahead of repinning.
A pin isn’t permanent: Follow the current version on the same panel
removes it, and your app goes back to following the current version, as a
new app does. Scripting it, that’s
PUT /developer/apps/:id/api-version with { "apiVersion": null } — the key
is required, so an empty body is a 400, not an unpin — which answers:
{ "apiVersion": "2026-09-22", "pinned": false, "current": "2026-09-22" }Send a supported version instead of null to pin one. API requests pick up a
pin change within a minute: each app’s pin is cached for up to 60 seconds. The
pin also sets the apiVersion stamped on your
webhook deliveries.
Hosted functions follow the same order.
ctx.api sends OneBooks-Version only when your app is pinned, with the
pinned version; an unpinned app’s function calls carry no version header and
resolve like any other request of your app. A OneBooks-Version your code
passes in init.headers overrides it for that call. Testing locally,
runLocally() sends
one only when you pass its apiVersion option.
What counts as breaking
Section titled “What counts as breaking”| Breaking (needs a new version) | Additive (ships without one) |
|---|---|
| Removing an operation, parameter or response property | A new endpoint |
| Making a previously-optional request field required | A new optional request/response field |
| Changing a field’s type or meaning | A new event type |
| Narrowing an enum’s accepted values | A new enum value appended to an existing one you’re not exhaustively switching on |
Every partner-surface change is checked against a frozen snapshot of the previous version before it ships, specifically to catch accidental breaks — so a version bump is a deliberate, documented decision, not something that happens quietly inside a patch release.
Support window
Section titled “Support window”A version stays fully supported for 12 months after its successor ships.
After that, requests pinned to it are rejected with UNSUPPORTED_API_VERSION
— migrate before the sunset date shown for your pinned version.
| Version | Released | Status | Sunsets |
|---|---|---|---|
2026-09-22 | 2026-09-22 | Current | — |
Where next
Section titled “Where next”Changelog tracks what shipped in each version, in prose.