API stability
How the public API changes and what stays stable — the published OpenAPI contract is the source of truth, and additive evolution is the default.
The published contract is the API: if a field, endpoint, or event is in the OpenAPI reference and on these pages, you can depend on it; if it is not, it is not part of the public surface.
There is no URL version
The public API does not use a version segment in its resource paths. There is no /v1/ to pin, and you do not select a version per request.
The base URL is the production Edge Functions host — https://chgrkvftjfibufoopmav.supabase.co/functions/v1. The functions/v1 here is the platform's function runtime prefix, not an API resource version; the resources themselves (scim-users, webhook-dispatcher, and so on) are unversioned. Treat the host and path you are given as stable, and do not parse a version out of the URL.
What is versioned is the contract document itself. The published openapi.yaml carries an info.version (currently 1.0.0) that moves as the surface evolves. That number describes the document, not a routing prefix.
The contract is the source of truth
apps/public/public/openapi.yaml is generated from the production deployment, not written by hand. Every path it lists is verified to exist in production before it ships; anything outside it is not part of the public API and may change without notice.
This has a practical consequence for how you build:
- Depend only on what is documented. Fields, query parameters, status codes, and events shown in the reference and on these pages are the contract. Undocumented response fields, internal endpoints, and incidental behavior are not, even if you can observe them.
- Read defensively. Tolerate unknown fields in responses and webhook payloads rather than rejecting them. Additive changes (see below) ship without warning, and a strict parser turns a non-breaking change into an outage on your side.
What counts as a breaking change
A change is breaking if a correct, defensively written integration could stop working because of it. These are the changes the API avoids making without a deliberate migration path:
- Removing an endpoint, a response field, or a webhook event type.
- Renaming a field, an event type, or a query parameter.
- Changing the type or format of an existing field (for example, a string becoming an object).
- Making a previously optional request parameter required.
- Tightening validation so input that used to be accepted is now rejected.
- Changing authentication, the signature scheme, or the meaning of an existing status code.
What counts as a non-breaking change
These ship continuously and do not require any action on your part:
- Adding a new endpoint or a new webhook event type.
- Adding a new optional field to a response or a webhook payload's
data. - Adding a new optional, defaulted request parameter.
- Adding a new accepted value to an open-ended field.
- Relaxing a previous limit, or fixing a bug so behavior matches the documented contract.
This is why both the webhook events reference and the consumption guidance tell you to ignore unrecognized event types and unknown fields: that tolerance is what makes additive changes safe to receive.
Limits and quotas are tuned, not frozen
Rate limits are operational values, not part of the contract. They can be tuned up or down without a version change, which is why that page tells you to treat a 429 and its Retry-After header as authoritative rather than hard-coding a threshold. Build to the response, not to a number you copied once.
How a deprecation would be communicated
When a breaking change becomes necessary, it is announced before it lands, not discovered after. The mechanism is the changelog: removals and migrations are recorded there with the affected surface and what to do, ahead of the change taking effect. Watch the changelog if you maintain an integration; it is the one place breaking changes are surfaced.
The most resilient integration reads only documented fields, tolerates unknown ones, treats rate-limit responses as authoritative, and watches the changelog. Built that way, additive changes never reach you as incidents.

