Factuarea API

Versioning

Flat-versioned /v1 policy with Factuarea-Version header. Stability and deprecation commitments.

The Factuarea API follows a flat-versioned URL policy (/v1) combined with an optional date header for non-breaking evolution. The commitment is clear: once published, /v1 stays stable. Incompatible changes require /v2.

URL version

https://api.factuarea.com/v1/...

v1 is our first public version (May 2026). No prior versions are accessible.

When /v2 is designed:

  • /v1 and /v2 coexist for at least 12 months.
  • /v1 routes do not change in that window (no payloads, status codes, fields or semantics).
  • Email notices to developers with active keys, banner in the docs, headers on responses (see below).

Factuarea-Version header

Factuarea-Version: 2026-06-01

Date-versioning works the Stripe way. There is a registry of supported versions (YYYY-MM-DD dates); today there is a single one, 2026-06-01, which is also the latest. The version that applies to a request — the effective version — is resolved in this order:

  1. The Factuarea-Version request header, if you send one.
  2. Otherwise, the version pinned on your API key (set when the key is created; null means "always latest").
  3. Otherwise, the latest version in the registry.

The effective version is echoed on every response in the Factuarea-Version header, so you always know which calendar version served your request.

Factuarea-Version: 2026-06-01

Pinning a version (by header or on the key) freezes the behavior of the subset of endpoints that receive non-breaking incremental improvements (new response fields, new optional parameters). Without a header or a pin, you get the latest version.

The registry currently holds two dates: 2026-06-01 (the default, and what you get without a header or a pin) and 2026-09-01. Opting into the newer date changes two things, and nothing else:

Change in 2026-09-01What you get on 2026-06-01
Bulk-delete responses use the transversal partial-success shape {total, successful, failed, failures[{id, error_code, error_message}]}.The previous shape {object: "bulk_delete_result", deleted, failed[{id, reason}]}.
The five pre-existing payment-gate errors (payment_method_required, seat_charge_failed, gestoria_plan_required, employee_seat_payment_method_required, employee_seat_charge_failed) carry error.type: "payment_required_error".error.type: "invalid_request_error" for those five, exactly as before.

The error reclassification does not touch error.code, error.subcode or the HTTP status — they are 402 with the same code on every version. If you branch on code (which is what we recommend), nothing changes for you either way. addon_required is a newer code and always carries payment_required_error.

Errors

The header is validated against the registry:

  • Malformed value (not YYYY-MM-DD, e.g. 2026-05 or 15/05/2026) → 400 parameter_invalid_format with param: "Factuarea-Version".
  • Well-formed but unsupported (a valid date that is not in the registry) → 400 unsupported_api_version with param: "Factuarea-Version".

Omitting the header is never an error — it falls back to the key pin or the latest version.

What is breaking?

We consider breaking (forbidden in /v1):

  • Renaming / removing JSON response fields.
  • Changing a field's type (stringint).
  • Changing the type/code of an existing error envelope.
  • Changing status codes (e.g. returning 201 where it used to be 200).
  • Making a previously optional request field required.
  • Changing the format of an identifier (UUID v7 stays UUID v7).
  • Removing an endpoint without a documented replacement and migration window.
  • Changing the document state machine semantics.

We consider non-breaking (allowed without a new version):

  • Adding new fields in responses.
  • Adding optional parameters in requests.
  • Adding new endpoints.
  • Relaxing restrictions (raising a limit, accepting more formats).
  • Adding new enum values to fields that aren't critical to client-side state machines.
  • Improving error messages (changes message, not type/code).
  • Reclassifying the type of an existing error envelope behind a dated version: keys pinned to an earlier date keep receiving the previous type byte for byte, and code/subcode/status never move. This is how the five payment-gate errors were recategorised in 2026-09-01. Doing it without a dated version is the breaking case listed above.

Deprecation policy

When an endpoint or field is marked deprecated within /v1 (e.g. a legacy alias replaced by a canonical version):

  • Email notice to developers with active keys affected.
  • Banner on docs.factuarea.com with the changelog.
  • Headers on every response of the deprecated endpoint for at least 12 months before retirement (which only happens in /v2):
Deprecation: true
Sunset: Wed, 15 May 2027 00:00:00 GMT
Link: <https://docs.factuarea.com/changelog#v1-deprecations>; rel="deprecation"
Link: <https://docs.factuarea.com/guides/migration-from-holded>; rel="alternate"
  • In /v1 the endpoint keeps working until the launch of /v2. The headers warn.
  • In /v2 the endpoint is retired / replaced. The window between the first warning and /v2 is ≥ 12 months.

Migration between versions

Each migration (v1 → v2) ships with:

  • A dedicated guide at docs.factuarea.com/guides/migration-v1-v2.
  • Field-to-field and endpoint-to-endpoint mapping.
  • Operational recommendations (keep both keys, dual-write during the transition).
  • Webhooks: old events keep their shape; new events live in their own version declared in the payload.

Changelog

Every /v1 change (new field, deprecation, new event, validation fix) is published in Changelog with tags:

  • feature — new field / endpoint / event.
  • fix — bug fix.
  • deprecation — field or endpoint marked obsolete (still active in /v1).
  • breaking — only appears in /v2, never inside /v1.
  • security — fix with security implications. Read it first.

Subscribe to the RSS feed at https://docs.factuarea.com/changelog.rss or follow @factuarea on X for announcements.

Stability commitment

An integration built today against /v1 will keep working in /v1 for at least 24 months from today, without touching your code. Support window for v1 → minimum 12 months after launch of v2.

That's the guarantee. Any exception will be communicated with generous timelines.

On this page