> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.deel.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.deel.com/_mcp/server.

# API versioning

> Understand how Deel uses date-based API versioning and endpoint lifecycle states

## Overview

The Deel API uses versioning to evolve endpoints while maintaining backward compatibility for existing integrations.

#### Current stable version

`2026-01-01` \

Expected deprecation: Jan 1, 2027

#### Versioning method

Header-based: `X-Version: 2026-01-01`

### Header versioning

The Deel API uses **header-based date versioning** as the standard for managing API changes. You specify a version date using the `X-Version` request header:

```
X-Version: 2026-01-01
```

### Key concepts

* Deel uses **date-based versioning** via the `X-Version` header (`YYYY-MM-DD` format)
* Every endpoint version follows a **lifecycle** with three states: Beta, Stable, and Deprecated
* New endpoints and new versions of existing endpoints **start in Beta** for three months before promotion to Stable
* Omitting the `X-Version` header routes your request to a **stable version** automatically
* **Beta** endpoints require an explicit `X-Beta: true` header
* Response headers communicate the **lifecycle state** of the version you called

All existing API endpoints are baselined to version `2026-01-01`. Existing integrations that do not send the `X-Version` header will continue to work with no changes.

### Version lifecycle timing

| Phase          | Duration       | Description                                                                                                                                                                                                  |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Beta**       | 3 months       | Every new endpoint and every new version of an existing endpoint starts here. Access requires `X-Beta: true`, the contract may still change, and the endpoint carries a **Beta** badge in the API reference. |
| **Stable**     | Minimum 1 year | The version is production-ready and will not receive breaking changes                                                                                                                                        |
| **Deprecated** | Fixed 1 year   | The version remains functional but a newer version is available. Migration is required before the sunset date.                                                                                               |
| **Sunset**     | —              | The version is removed. Requests return `410 Gone`.                                                                                                                                                          |

A new major version is expected approximately once per year. When a new version is released, it starts in Beta and the previous version enters deprecation with exactly one year of continued support before sunset.

## Specifying a version

Use the `X-Version` request header to pin your integration to a specific API version.

| Header      | Format       | Required | Description                                |
| ----------- | ------------ | -------- | ------------------------------------------ |
| `X-Version` | `YYYY-MM-DD` | No       | Pins the request to a specific API version |

**`Python`**

```python Python
import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
    "X-Version": "2026-01-01"
}

response = requests.get(
    "https://api.letsdeel.com/rest/contracts",
    headers=headers
)
```

**`Node.js`**

```javascript Node.js
const axios = require('axios');

const response = await axios.get(
  'https://api.letsdeel.com/rest/contracts',
  {
    headers: {
      'Authorization': `Bearer ${process.env.DEEL_API_TOKEN}`,
      'X-Version': '2026-01-01'
    }
  }
);
```

**`cURL`**

```bash cURL
curl -X GET 'https://api.letsdeel.com/rest/contracts' \
  -H 'Authorization: Bearer YOUR-TOKEN-HERE' \
  -H 'X-Version: 2026-01-01'
```

Sending an `X-Version` value that does not match any published version for the endpoint returns a `400` error. The API does not negotiate or suggest alternative versions.

### Default behavior (no header)

When `X-Version` is omitted, the API routes your request to a stable version automatically. Existing integrations continue to work with no changes required.

If you are building a new integration, Deel recommends explicitly setting `X-Version` to protect against future changes.

## Lifecycle states

Every endpoint version moves through a defined lifecycle. The `X-State` response header communicates the current state of the version you called.

```mermaid
stateDiagram-v2
    [*] --> Beta : New endpoint or new version introduced
    Beta --> Stable : Promoted after validation
    Stable --> Deprecated : Newer version available
    Deprecated --> Sunset : After deprecation period
    Sunset --> [*] : Endpoint removed (410 Gone)
```

| State          | `X-State`    | Action required                                        |
| -------------- | ------------ | ------------------------------------------------------ |
| **Beta**       | `beta`       | Opt in with `X-Beta: true`; do not use in production   |
| **Stable**     | `stable`     | Safe for production use                                |
| **Deprecated** | `deprecated` | Plan migration; check `Sunset` header for removal date |
| **Sunset**     | N/A (`410`)  | Migrate to a newer version                             |

#### Beta

Beta endpoints provide early access to upcoming API changes. They require the `X-Beta: true` header and may introduce breaking changes before promotion to Stable.

* Every new endpoint and every new version of an existing endpoint starts in Beta for **three months**
* Beta endpoints are **not recommended for production** workloads
* Beta endpoints carry a **Beta** badge in the API reference; when a Stable version of the same endpoint exists, the reference documents the Stable contract and notes the Beta version
* A new endpoint that has no Stable version yet still enforces `X-Beta: true`. A request without the header gets the same beta-access error as any other beta version (see [Error handling](#error-handling)), not a generic not-found response
* An endpoint that is also exposed as an [MCP tool](/mcp/introduction) goes through the same Beta window. MCP clients cannot set custom request headers, so they cannot send `X-Beta: true` — the tool stays unusable through MCP until the endpoint is promoted to Stable, and the beta-access error is what a direct REST call against it returns in the meantime
* The Deel team that owns the endpoint communicates the contract and any changes to participating clients during the beta period
* The API returns `X-State: beta` in the response headers
* Once promoted, the endpoint transitions to Stable and no longer requires the `X-Beta` header

#### Stable

Stable is the default production-ready state. Endpoints in this state are backward-compatible within the same version date.

* No special headers are required
* The API returns `X-State: stable` in the response headers
* Breaking changes are only introduced through a new version date

#### Deprecated

Deprecated endpoints remain functional but have a scheduled removal date. The API signals deprecation through response headers.

* The `Deprecation` response header is set to `true`
* The `Sunset` response header provides the exact removal date in UTC format
* The API returns `X-State: deprecated` in the response headers
* You should begin migrating to the newer version before the sunset date

#### Sunset

After the sunset date passes, the endpoint is permanently removed. Requests to a sunset version return a `410 Gone` response with details to help you migrate.

* The response body includes `latest_stable_version` to guide migration
* The response body includes the `sunset_date` for reference
* No further requests to this version will succeed

## Response headers

The API includes versioning-related headers in every response to communicate the current state of the endpoint you called.

| Header         | Value                                                   | When present                                 |
| -------------- | ------------------------------------------------------- | -------------------------------------------- |
| `X-State`      | `beta`, `stable`, or `deprecated`                       | Every successful response                    |
| `Deprecation`  | `true`                                                  | When the version has a scheduled sunset date |
| `Sunset`       | UTC date string (e.g., `Thu, 01 Jan 2028 00:00:00 GMT`) | When deprecation is active                   |
| `X-Request-ID` | UUID                                                    | Every response                               |

Monitor the `X-State` and `Deprecation` headers in your integration. When you see `deprecated`, begin planning your migration to avoid disruption at sunset.

**`Python`**

```python Python
import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
    "X-Version": "2026-01-01"
}

response = requests.get(
    "https://api.letsdeel.com/rest/contracts",
    headers=headers
)

state = response.headers.get("X-State")
is_deprecated = response.headers.get("Deprecation") == "true"
sunset_date = response.headers.get("Sunset")

if is_deprecated:
    print(f"Warning: This API version is deprecated. Sunset date: {sunset_date}")
```

**`Node.js`**

```javascript Node.js
const axios = require('axios');

const response = await axios.get(
  'https://api.letsdeel.com/rest/contracts',
  {
    headers: {
      'Authorization': `Bearer ${process.env.DEEL_API_TOKEN}`,
      'X-Version': '2026-01-01'
    }
  }
);

const state = response.headers['x-state'];
const isDeprecated = response.headers['deprecation'] === 'true';
const sunsetDate = response.headers['sunset'];

if (isDeprecated) {
  console.warn(`This API version is deprecated. Sunset date: ${sunsetDate}`);
}
```

## Beta access

Beta endpoints provide early access to upcoming API changes before they are promoted to Stable. Access requires the `X-Beta` header.

Every new endpoint and every new version of an existing endpoint spends its first three months in Beta. During this period the owning Deel team can still change the request and response contract based on client feedback. The API reference marks these endpoints with a **Beta** badge and states the date on which the version is scheduled to become Stable.

Beta endpoints are experimental and may change without notice. Do not rely on them for production workloads.

```bash
curl -X GET 'https://api.letsdeel.com/rest/contracts' \
  -H 'Authorization: Bearer YOUR-TOKEN-HERE' \
  -H 'X-Beta: true'
```

The `X-Beta` header and `X-Version` header follow strict mutual exclusivity rules:

| `X-Beta` | `X-Version` | Result                                 |
| -------- | ----------- | -------------------------------------- |
| Omitted  | Omitted     | Stable version (default)               |
| Omitted  | Stable date | That specific stable version           |
| `true`   | Omitted     | Beta version (if available)            |
| `true`   | Beta date   | That specific beta version             |
| Omitted  | Beta date   | **400 error** — beta access required   |
| `true`   | Stable date | **400 error** — version is not in beta |

The `X-Beta` header accepts only `true` or `false` (case-insensitive). Any other value returns a `400` error.

## Backward compatibility and migration

Deel follows a predictable versioning cadence to give you time to plan and execute migrations.

* **Baseline version**: All existing endpoints are set to `2026-01-01`, stable until at least Jan 1, 2027
* **New endpoints**: Newly released endpoints start in Beta for three months. Access requires `X-Beta: true` until the endpoint is promoted to Stable.
* **New versions**: Breaking changes are introduced as new date versions (e.g., `2026-06-15`) that start in Beta for three months. The previous version remains available throughout its lifecycle.
* **Major versions**: A new major version is expected approximately once per year, rolling up the latest changes
* **Stability guarantee**: Each version remains stable for a minimum of one year from release
* **Deprecation period**: Superseded versions receive exactly one year of continued support before sunset

### Migration checklist

#### Monitor response headers

Watch for `Deprecation: true` and the `Sunset` date header in your API responses. These signal that your current version is scheduled for removal.

#### Review the changelog

Check the [changelog](/api/changelog) for details on what changed in the new version, including any breaking changes to request or response schemas.

#### Update X-Version in sandbox

Set `X-Version` to the new date in your [sandbox](/api/sandbox) environment and run your integration test suite.

#### Test thoroughly

Pay attention to changed response shapes, removed fields, and updated validation rules. Verify that your error handling covers the new version.

#### Roll out to production

Update `X-Version` in your production environment. Monitor logs and response headers to confirm the new version is active.

## Error handling

The API returns specific error messages for versioning-related issues.

| Status | Condition                          | Error message                                                                                         |
| ------ | ---------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `400`  | Malformed `X-Version`              | "Invalid X-Version header format. Expected YYYY-MM-DD format (e.g. 2026-01-01)"                       |
| `400`  | Version not found                  | "The provided X-Version value is invalid for the requested endpoint."                                 |
| `400`  | Beta version without `X-Beta` flag | "This API version is in beta. Please include the X-Beta: true header to access beta versions."        |
| `400`  | `X-Beta` flag on non-beta version  | "This API version is not in beta. Please do not include the X-Beta header to access stable versions." |
| `400`  | Invalid `X-Beta` format            | "Invalid X-Beta header format. Expected 'true' or 'false'."                                           |
| `410`  | Sunset version requested           | See response body below                                                                               |

The beta-access error also applies to a brand-new endpoint that has no Stable version yet: calling it without `X-Beta: true` returns this `400` error rather than a not-found response. For an endpoint that is also exposed as an [MCP tool](/mcp/introduction), this is the error a direct REST call returns while the endpoint is in Beta, since the MCP client itself cannot set the header.

### Sunset response (410 Gone)

When you request a sunset version, the API returns a `410 Gone` response with migration guidance:

**`Example 410 response`**

```json Example 410 response
{
  "errors": [
    {
      "code": "endpoint_sunset",
      "message": "This API version has been sunset and is no longer available.",
      "details": {
        "requested_version": "2026-01-01",
        "latest_stable_version": "2027-01-01",
        "sunset_date": "2028-01-01T00:00:00.000Z"
      }
    }
  ]
}
```

Use `latest_stable_version` from the response to update your `X-Version` header.

**`Python`**

```python Python
import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
    "X-Version": "2026-01-01"
}

response = requests.get(
    "https://api.letsdeel.com/rest/contracts",
    headers=headers
)

if response.status_code == 410:
    error_data = response.json()
    details = error_data["errors"][0]["details"]
    print(f"Version {details['requested_version']} has been sunset.")
    print(f"Migrate to version: {details['latest_stable_version']}")
elif response.status_code == 400:
    print(f"Version error: {response.json()}")
```

**`Node.js`**

```javascript Node.js
const axios = require('axios');

try {
  const response = await axios.get(
    'https://api.letsdeel.com/rest/contracts',
    {
      headers: {
        'Authorization': `Bearer ${process.env.DEEL_API_TOKEN}`,
        'X-Version': '2026-01-01'
      }
    }
  );
} catch (error) {
  if (error.response?.status === 410) {
    const details = error.response.data.errors[0].details;
    console.error(`Version ${details.requested_version} has been sunset.`);
    console.error(`Migrate to version: ${details.latest_stable_version}`);
  } else if (error.response?.status === 400) {
    console.error('Version error:', error.response.data);
  }
}
```

## Troubleshooting

#### 400 error with X-Version header

**Common causes:**

* The `X-Version` value is not in `YYYY-MM-DD` format
* The version date does not exist for this endpoint

**Solutions:**

* Verify the header value matches the exact format: `X-Version: 2026-01-01`
* Check the [changelog](/api/changelog) for available version dates
* Remove the header to use the default stable version

#### 400 error accessing a beta endpoint

**Common causes:**

* The `X-Beta: true` header is missing when requesting a beta version
* The `X-Beta: true` header is present but the version is not in beta

**Solutions:**

* Include `X-Beta: true` when accessing a beta version
* Remove `X-Beta` when accessing a stable or deprecated version
* Verify whether the endpoint is still in beta or has been promoted to stable

#### 410 Gone response

**Cause:**

* The requested version has been sunset and is no longer available

**Solution:**

* Read the `latest_stable_version` from the response body
* Update your `X-Version` header to the suggested version
* Test the new version in [sandbox](/api/sandbox) before deploying to production

#### Not sure which version I am using

**Solution:**

* Check the `X-State` response header on any API call
* If you are not sending the `X-Version` header, you are using a stable version
* Use the `X-Request-ID` response header when contacting support for version-related issues

## Legacy Path Versioning

The Deel API previously used **URL path versioning** with a `/v2/` prefix in the URL:

```
https://api.letsdeel.com/rest/v2/people
```

This pattern is **legacy but remains backward-compatible**. Existing integrations that use the `/v2/` URL prefix will continue to work without changes.

For new integrations, Deel recommends using header-based date versioning with the `X-Version` header instead of relying on the URL path prefix. Header versioning provides more granular control over which API version your integration uses.

When both the `/v2/` URL prefix and the `X-Version` header are present, the header takes precedence for version resolution.

## Next steps

#### [Authentication](/api/authentication)

Learn how to authenticate API requests

#### [Rate limits](/api/rate-limits)

Understand API rate limits and best practices

#### [Changelog](/api/changelog)

Review changes across API versions

#### [Sandbox](/api/sandbox)

Test version pinning in the sandbox environment