Using the APIVersioning

Using the API

Versioning

The major version is in the path. Within v1 we only add things, so your code keeps working. How to stay compatible and how deprecations are announced.

The API is versioned so that code you write today keeps working. The major version is part of every URL, /v1, and within a major version we only make changes that cannot break a well-behaved client. When something truly has to change in a breaking way, it goes into a new major version, announced well before anything is removed.

The version is in the path

https://api.freeinvoiceautomation.com/v1/documents

There is no version header to send and no date to pin. Every request to /v1 gets v1 behaviour.

What can change within v1

Only additive changes are made inside v1:

ChangeExampleWhat you need to do
New endpointsA new capability ships with a releaseNothing
New optional request fieldsA new optional setting on a documentNothing; leave it out until you need it
New response fieldsA new field on a clientIgnore fields you do not know
New enum valuesA new document status, payment rail or webhook event typeHandle unknown values gracefully
New error codesA new, more specific codeFall back to the HTTP status for codes you do not know

What will not change within v1

  • Removing an endpoint, a field or an enum value.
  • Renaming anything.
  • Making an optional request field required.
  • Changing a field's type or format, such as turning a money string into a number.
  • Changing the meaning of an existing error code.

A check in our build compares the OpenAPI document of every change with the published one and fails on any breaking change to /v1. A breaking change cannot ship by accident.

Write tolerant clients

To benefit from this promise, your code should accept additions:

  • Ignore unknown fields in responses and webhook payloads. Do not fail validation because a new field appeared.
  • Tolerate unknown enum values. A status, type or event type you have not seen should be logged and skipped, not crash your code. For example, new webhook events are added as features ship through 2027.
  • Branch on error.code, then on the HTTP status. If a code is new to you, the HTTP status still tells you the category.
  • Do not depend on field order in JSON objects, or on the order of webhook deliveries.
JavaScript
switch (event.type) {
  case "document.paid":
    await markPaid(event.data.object);
    break;
  case "document.voided":
    await markVoid(event.data.object);
    break;
  default:
    console.info("Ignoring event type", event.type); // new types are expected over time
}

Releases add capabilities

The product ships in steps through 2027: reminders and recurring invoices in January, schedules and reports later in January, Whop and the Shopify app in February, contracts and auto-charge in March, time and expenses in April, QuickBooks and Xero in May, and the ledger in June to July. Each release adds endpoints, MCP tools, CLI commands and webhook events to v1. Endpoints for later releases are already listed in this reference with a "Coming" badge, so you can plan ahead before they ship.

Deprecations

When an endpoint or field is going to be removed in a later major version:

  1. It is marked deprecated in this reference and in the OpenAPI document.
  2. Responses that use it carry a Deprecation header (proposed).
  3. It keeps working in v1, because v1 only ever grows. Removal happens only in a later major version.

Watch for the Deprecation header in your logs, and follow the Changelog for announcements.

Webhook payloads are versioned too

Every outgoing webhook payload carries "api_version": "v1". The same additive rules apply: new event types and new fields may appear, existing ones keep their meaning.

Webhook payload (start)
{
  "id": "0193f3c0-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
  "type": "document.sent",
  "api_version": "v1",
  "created_at": "2027-01-04T10:15:00Z"
}

The OpenAPI document

The OpenAPI document at GET https://api.freeinvoiceautomation.com/v1/openapi.json (proposed path) describes v1 exactly as it runs, because it is generated from the same definitions as the routes. You can diff it yourself between your deploys to see what was added. See Introduction.

The CLI and SDK follow the API

The CLI and the TypeScript SDK are generated from the same capability definitions. A new CLI version adds commands for new capabilities; existing commands keep working against v1.