Reference

Versioning and stability

The API is versioned in the path — every endpoint lives under /api/v1. Here is exactly what that promises.

What may change without warning

v1 evolves additively. Any of the following can appear in a response you are already handling, so your client must tolerate them:

  • New fields on any object. Ignore ones you do not recognise.
  • New endpoints and new optional request parameters.
  • New enum values — a new document type, or a new status. Handle the ones you care about and treat the rest as unknown rather than as an error.
  • New error codes within an existing type. Branch on the codes you handle and fall back to the type.
  • Reworded messages. The message field is for humans. Never parse it.
  • Rate-limit numbers, which are tied to plans and can be raised for an account. Read the X-RateLimit-* headers rather than hard-coding.

What will not change within v1

  • Removing or renaming a field on a response object.
  • Changing the type or meaning of an existing field, including which fields can be null.
  • Changing which HTTP status an error type maps to, or renaming a type or an existing code.
  • Tightening validation on an existing field, or making an optional request field required.
  • Removing an endpoint, or narrowing what a scope already grants.
  • Changing the meaning of an Idempotency-Key, or the webhook signature scheme.

Anything in that list would ship as v2, alongside v1, not in place of it.

Writing a client that survives both

javascript
// Tolerant: ignores what it does not know, reads only what it needs.
const { id, status } = await res.json();
if (status === "completed") await onCompleted(id);

// Fragile: breaks the day we add a field, or add a status.
const { id, status, ...rest } = await res.json();
if (Object.keys(rest).length) throw new Error("unexpected response shape");
switch (status) {
  case "completed": return onCompleted(id);
  default: throw new Error(`unknown status: ${status}`);
}

The rule is Postel’s: read only the fields you need, and treat unknown values as unknown rather than as failures. A client that validates responses against an exhaustive schema will break on our next additive release — which is a change we consider safe and will not announce.

Strict client generators need configuring

If you generate a client from the OpenAPI description, check how it handles unknown properties and unknown enum members. Several generators default to rejecting both. Configure them to be permissive, or regenerate on each release.

If we ever need to deprecate something

StageWhat happens
AnnouncementAn entry on the changelog describing the change and the migration path.
OverlapThe old and new behaviour both work. Nothing you have built stops functioning during this period.
Direct noticeWe contact the account owners of integrations still using the old behaviour, since we can see who those are.
RemovalOnly after the above, and only in a new version.

Nothing is deprecated today. This is the process we would follow, stated in advance so you can weigh it before you build.

Keeping up

  • The changelog records every change, newest first.
  • The OpenAPI description is the machine-readable version — diffing it between releases shows precisely what moved.
Versioning and stability · XOsign API docs