> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Edge Function API Versioning Guide

> Edge Functions support application-level API versioning via the X-API-Version header. Callers request a specific version (e.g. v1, v2); the withVersioning midd…

**Spec:** PF-89 — API Versioning & Edge Function Lifecycle\
**Last Updated:** 2026-03-25

***

## Overview

Edge Functions support **application-level API versioning** via the `X-API-Version` header. Callers request a specific version (e.g. `v1`, `v2`); the `withVersioning` middleware routes to the correct handler. If no header is sent, the **latest stable version** (highest major key) is used.

Versioning is **opt-in** per function and gated by `ENABLE_API_VERSIONING`.

***

## Quick Start — Adding Versioning to a Function

### 1. Define a contract

Create `supabase/functions/_shared/contracts/my-function.contract.ts`:

```typescript theme={null}
/** V1 request */
export interface MyFunctionV1Request {
  organization_id: string;
  name: string;
}

/** V1 response */
export interface MyFunctionV1Response {
  success: boolean;
  id: string;
}
```

Re-export from `_shared/contracts/index.ts`.

### 2. Wrap with `withVersioning`

```typescript theme={null}
import { withVersioning } from '../_shared/versioning.ts';

async function v1Handler(req: Request): Promise<Response> {
  // existing logic
}

Deno.serve(withVersioning('my-function', { v1: v1Handler }));
```

### 3. (Optional) Add a v2

```typescript theme={null}
async function v2Handler(req: Request): Promise<Response> {
  // new logic
}

Deno.serve(
  withVersioning('my-function', { v1: v1Handler, v2: v2Handler }, {
    deprecated: {
      v1: { sunset: '2026-09-01', successor: 'v2' },
    },
  }),
);
```

***

## How It Works

1. Caller sends `X-API-Version: v1` header.
2. `withVersioning` looks up `handlers['v1']`.
3. If found → executes handler; if deprecated → merges `Deprecation` / `Sunset` / `Link` headers.
4. If not found → returns 400 with migration guidance (PF-07 error envelope).
5. If no header → defaults to highest version key.

### Feature Flag

Set `ENABLE_API_VERSIONING=true` in Supabase Edge Function secrets. When unset/false, all requests pass through to the default (latest) handler with no version negotiation.

***

## Contract Conventions

* File: `_shared/contracts/{function-name}.contract.ts`
* Naming: `{FunctionName}V{N}Request`, `{FunctionName}V{N}Response`
* Major-only semver surface: `v1`, `v2` — minor/patch changes stay backward-compatible
* Re-export all contracts from `_shared/contracts/index.ts`

***

## Deprecation Headers

When a version is marked deprecated, responses include:

| Header        | Example                                                |
| ------------- | ------------------------------------------------------ |
| `Deprecation` | `@1711929600` (Unix timestamp)                         |
| `Sunset`      | `Sat, 01 Sep 2026 00:00:00 GMT`                        |
| `Link`        | `</functions/v1/my-function>; rel="successor-version"` |

Callers should monitor for `Deprecation` headers and plan migration before `Sunset`.

***

## CI Contract Validation

Run `npx tsx scripts/edge-contracts/diff-contracts.ts` to detect breaking changes (removed exports) in contract files. This runs automatically on PRs touching `*.contract.ts`.

* **Additions** (new exports): non-breaking ✅
* **Removals** (deleted exports): breaking ❌ — bump major version

***

## Consumer Obligations

1. Send `X-API-Version` header or accept the default (latest stable).
2. Handle `400` responses with migration guidance when a version is unsupported.
3. Respect `Sunset` dates by migrating before the removal deadline.
4. Monitor `Deprecation` headers in responses.

***

## Related Documents

* [PF-89 Spec](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/specs/PF-89-api-versioning-edge-function-lifecycle.md)
* [PF-89 Integration](/architecture/integrations/api-versioning-edge-function-lifecycle-integration)
* [API Contracts](/architecture/integrations/API_CONTRACTS)
* [Event Contracts](/architecture/integrations/EVENT_CONTRACTS)
