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

# Versioning

> Pin an API version with the Api-Version header, and upgrade when you choose

Every partner API request must declare which API version it targets. That lets
Endl ship new versions and change behaviour without breaking existing
integrations: you pin a version, and it keeps working.

|            |                           |
| ---------- | ------------------------- |
| Header     | `Api-Version`             |
| Applies to | All `/api/v0/*` endpoints |
| Required   | Yes                       |
| Latest     | `2026-09.1`               |

## The header

You send it on the request; Endl echoes it back on the response.

```bash Request — you send theme={null}
Api-Version: 2026-09.1
Api-Key: pk_live_xxxxxxxx
```

```bash Response — Endl echoes theme={null}
Api-Version: 2026-09.1
X-Request-ID: req_...
```

The echoed value is the version that **actually served** the request, so you can
assert on it in monitoring and tests rather than assuming.

<Warning>
  **`Api-Version` is not `Api-Key`.** One carries the API version, the other
  carries your credential. They are two separate headers and you send both.
</Warning>

## Format

`YYYY-MM.<release>` — the year and month the version was cut, plus a release
number within that month.

| Part        | Example | Meaning                          |
| ----------- | ------- | -------------------------------- |
| `YYYY`      | `2026`  | Year                             |
| `MM`        | `09`    | Month                            |
| `<release>` | `1`     | Release number within that month |

Validated against `^\d{4}-\d{2}\.\d+$`.

## Supported versions

| Version     | Status     | Notes           |
| ----------- | ---------- | --------------- |
| `2026-09.1` | **Latest** | Current release |

New versions are added here as they ship. Pin the version you built against —
older supported versions keep their behaviour.

## Validation and errors

The header is validated once, centrally, for the whole partner surface.

| Outcome                                                                      | Result                                                          |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------- |
| Supported and well-formed                                                    | The request proceeds, and the version is echoed on the response |
| **Missing** — no `Api-Version` header                                        | `400`                                                           |
| **Malformed** — does not match `YYYY-MM.<release>`, such as `v1` or `2026-9` | `400`                                                           |
| **Unsupported** — well-formed but not a recognised version                   | `400`                                                           |

```json 400 theme={null}
{
  "code": "bad_request",
  "message": "The 'Api-Version' header is required",
  "name": "Api-Version"
}
```

<Note>
  **CORS preflight is exempt.** An `OPTIONS` request needs no version header.
</Note>

## Examples

A valid request carries both headers:

```bash theme={null}
curl https://api-sandbox.endl.io/api/v0/quotes/cus_9f2c/generate \
  -H "Api-Key: pk_live_xxxxxxxx" \
  -H "Api-Version: 2026-09.1" \
  -H "Content-Type: application/json" \
  -d '{
    "payoutRail": "BANK_TRANSFER",
    "source": { "amount": 100, "currency": "USD" },
    "destination": { "currency": "PHP" }
  }'
```

```http Response theme={null}
HTTP/2 200
Api-Version: 2026-09.1
```

Omit the header and the call is refused before anything is processed:

```bash theme={null}
curl https://api-sandbox.endl.io/api/v0/quotes/cus_9f2c/generate \
  -H "Api-Key: pk_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ … }'
```

```json 400 theme={null}
{
  "code": "bad_request",
  "message": "The 'Api-Version' header is required",
  "name": "Api-Version"
}
```

## Why it works this way

**Non-breaking evolution.** New request and response shapes ship under a new
version. The version you pinned is untouched.

**An explicit contract.** Every call states the version it expects, so an upgrade
is a deliberate change on your side rather than a surprise on ours.

**Confirmable.** The response echoes the version that served it, so you can
assert on it in monitoring and tests.

## Upgrading

When a new version ships, test your integration against it, then bump the
`Api-Version` value you send. Nothing in your code path changes until you do.

<Note>
  This is separate from the **webhook payload** `schemaVersion`, which is also
  calendar-versioned but pinned per subscription rather than per request. See
  [payload schema versions](/webhooks/reference#payload-schema-versions).
</Note>
