> This page is for API, version 2026-01-01 (Stable) (default).
> For other versions, use one of these documentation indexes:
> - 2026-01-01 (Stable) (default): https://developer.deel.com/api/stable/llms.txt

> 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.

# Create an engagement

POST https://api.letsdeel.com/rest/engagements
Content-Type: application/json

Creates an IC contract, applies the client signature, and invites the worker, in one idempotent call. Retry with the same Idempotency-Key to resume after a partial failure.

 **Token scopes**: `contracts:write`

 **Beta**: this version requires the `X-Beta: true` request header and its contract may change before it is promoted to stable. It is scheduled to become stable on 2027-02-09.

Reference: https://developer.deel.com/api/reference/endpoints/contractors/create-engagement-v-2026-01-01

## Authentication

- `Authorization` header (bearer token, required) — ## Authentication The Deel API uses bearer tokens to authenticate requests. All API calls must be made over HTTPS — calls over plain HTTP or without authentication will fail. ```curl curl -X GET 'https://api.letsdeel.com/rest/v2/contracts' \ -H 'Authorization: Bearer YOUR-TOKEN-HERE' ``` [Learn more about authentication](/api/authentication)
- `Authorization` header (bearer token, required) — Standard OAuth2 security scheme based on https://swagger.io/docs/specification/authentication/

## Servers

- `https://api.letsdeel.com/rest` (Production, default)
- `https://api-staging.letsdeel.com/rest` (Demo)

## Request

### Headers

- `Idempotency-Key` (string, optional) — A v4 UUID. Reusing the same key with the same body resumes an in-progress or partially-failed engagement instead of creating a duplicate.
- `X-Beta` (enum, required, default: true) — Opts in to the beta version of this endpoint. Must be `true`.
  - Allowed values: `true`

### Body (application/json)

This endpoint expects an object.

- `data` (EngagementsPostRequestBodyContentApplicationJsonSchemaData, required) — POST /rest/contracts data (legal_entity_id/team_id flattened - a nested id property is rejected as a server-generated field; job_title omitted - undocumented for that endpoint), plus client_signature and actions. See each field below for whether it is required.

## Response

### 201

All requested steps completed.

- `data` (EngagementsPostResponsesContentApplicationJsonSchemaData, required)

### 202

A step failed after an earlier one succeeded. Retry with the same Idempotency-Key to resume.

- `data` (EngagementsPostResponsesContentApplicationJsonSchemaData, required)

## Errors

### 400 Bad Request Error

Validation error - missing required field, unsupported type, or missing client_signature.

- `errors` (list of EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error entries.

### 401 Unauthorized Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 403 Forbidden Error

Forbidden - the caller does not have permission to create a contract for this legal entity or team.

- `errors` (list of EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error entries.

### 404 Not Found Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

### 409 Conflict Error

Conflict - external_id is already used by another engagement.

- `errors` (list of EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error entries.

### 422 Unprocessable Entity Error

Unprocessable - the Idempotency-Key header was reused with a request body that does not match the original request.

- `errors` (list of EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error entries.

### 429 Too Many Requests Error

Too Many Requests - another request with the same Idempotency-Key is still in progress.

- `errors` (list of EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — List of error entries.

### 500 Internal Server Error

Operation failed.

- `request` (ApiErrorRequest, optional)
- `errors` (list of ApiError, optional)

## Types

### EngagementsPostRequestBodyContentApplicationJsonSchemaData

POST /rest/contracts data (legal_entity_id/team_id flattened - a nested id property is rejected as a server-generated field; job_title omitted - undocumented for that endpoint), plus client_signature and actions. See each field below for whether it is required.

- `type` (enum, required) — Same as POST /rest/contracts data.type. Only these 4 types are creatable there - `milestones` is a legacy read-only type.
  - Allowed values: `ongoing_time_based`, `pay_as_you_go_time_based`, `payg_tasks`, `payg_milestones`
- `title` (string, required) — Same as POST /rest/contracts data.title.
- `client` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataClient, required) — Same as POST /rest/contracts data.client, flattened to legal_entity_id/team_id - the gateway rejects a nested id property as a server-generated field.
- `worker` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataWorker, required) — Same as POST /rest/contracts data.worker. Required here (optional there) - an engagement always onboards a worker.
- `start_date` (string, required) — Same as POST /rest/contracts data.start_date.
- `compensation_details` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataCompensationDetails, required) — Same as POST /rest/contracts data.compensation_details - see that endpoint for the full shape per contract type (the cadence field is `frequency` for ongoing_time_based, `scale` for pay_as_you_go_time_based, and the invoicing cycle is either `payment_policy_id` or the individual frequency/cycle_end/cycle_end_type/payment_due_type/payment_due_days fields).
- `locale` (enum, optional, default: en) — Same as POST /rest/contracts/\{contract\_id}/invite data.locale. Only used when actions.should\_invite\_worker is true (the default).
  - Allowed values: `en`, `es`, `fr`, `de`, `it`, `pt`, `pl`, `nn`, `nl`, `da`, `deAT`, `fi`, `sv`, `nlBE`, `ja`
- `actions` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataActions, optional) — Which of the sign/invite steps to run. Not part of POST /rest/contracts.
- `message` (string, optional) — Same as POST /rest/contracts/\{contract\_id}/invite data.message. Only used when actions.should\_invite\_worker is true (the default).
- `external_id` (string, optional) — Same as POST /rest/contracts data.external_id. Client's own reference for this engagement.
- `notice_period` (double, optional) — Same as POST /rest/contracts data.notice_period.
- `scope_of_work` (string, optional) — Same as POST /rest/contracts data.scope_of_work.
- `client_signature` (string, optional) — Same as POST /rest/contracts/\{contract\_id}/signatures data.client\_signature. Required when actions.should\_sign\_as\_client is true (the default).
- `contract_template_id` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataContractTemplateId, optional, nullable) — Same as POST /rest/contracts data.contract_template_id. Null uses the default Deel contract template.

### EngagementsPostResponsesContentApplicationJsonSchemaData

- `pending_actions` (list of enum, required) — Orchestration steps not yet completed. Empty when every requested action succeeded. Distinct from the payable-gating requirements[] planned for a later phase.
  - Allowed values: `create_contract`, `sign_contract`, `invite_worker`
- `engagement_status` (enum, required) — Current step of the engagement orchestration. Distinct from the contract's own status field above.
  - Allowed values: `draft`, `contract_created`, `client_signed`, `worker_invited`
- `engagement_created_at` (string, required) — When the engagement was created. Distinct from the contract's own created_at field above.
- `engagement_updated_at` (string, required) — When the engagement was last updated.
- `id` (string, optional) — The created contract's own id, passed through from its create-contract response. Absent if the create step has not yet succeeded.
- `created_at` (string, optional) — The created contract's own created_at, passed through from its create-contract response. Absent if the create step has not yet succeeded.

### EngagementsPostResponsesContentApplicationJsonSchemaErrorsItems

- `code` (string, required) — Machine-readable error code.
- `message` (string, required) — Human-readable error message.

### ApiErrorRequest

- `method` (string, optional) — The HTTP method of the failed request
- `url` (string, optional) — The relative URL of the failed request
- `status` (double, optional) — The status code of the response
- `api_req_id` (string, optional) — The request ID of the failed request
- `docs` (string, optional) — A link to the official documentation for the requested endpoint resource
- `source` (string, optional) — The source handler which produced the returned error
- `code` (double, optional) — The code of the source handler which produced the returned error

### ApiError

- `message` (string, optional) — A description of the returned error
- `path` (string, optional) — The JSON path where input validation failed

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataClient

Same as POST /rest/contracts data.client, flattened to legal_entity_id/team_id - the gateway rejects a nested id property as a server-generated field.

- `team_id` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataClientTeamId, required) — Existing team id. Required in V1 - org-default-team resolution is not yet implemented.
- `legal_entity_id` (EngagementsPostRequestBodyContentApplicationJsonSchemaDataClientLegalEntityId, required) — Existing legal entity id.

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataWorker

Same as POST /rest/contracts data.worker. Required here (optional there) - an engagement always onboards a worker.

- `first_name` (string, required) — Worker's first name.
- `expected_email` (string, required) — Worker's email address, used to send the invite when actions.should_invite_worker is true.
- `last_name` (string, optional, nullable) — Worker's last name.

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataCompensationDetails

Same as POST /rest/contracts data.compensation_details - see that endpoint for the full shape per contract type (the cadence field is `frequency` for ongoing_time_based, `scale` for pay_as_you_go_time_based, and the invoicing cycle is either `payment_policy_id` or the individual frequency/cycle_end/cycle_end_type/payment_due_type/payment_due_days fields).

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataActions

Which of the sign/invite steps to run. Not part of POST /rest/contracts.

- `should_invite_worker` (boolean, optional, default: true) — Whether to invite the worker to sign, once the contract is signed by the client. Requires actions.should_sign_as_client to also be true - inviting without a client-signed contract is rejected.
- `should_sign_as_client` (boolean, optional, default: true) — Whether to apply client_signature to the contract after creating it.

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataContractTemplateId

Same as POST /rest/contracts data.contract_template_id. Null uses the default Deel contract template.

- double
- string

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataClientTeamId

Existing team id. Required in V1 - org-default-team resolution is not yet implemented.

- string
- double

### EngagementsPostRequestBodyContentApplicationJsonSchemaDataClientLegalEntityId

Existing legal entity id.

- string
- double

## Examples

### Example 1

**Request**

```json
{
  "data": {
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": {
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    },
    "worker": {
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    },
    "start_date": "2026-09-01",
    "compensation_details": {
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    },
    "actions": {
      "should_invite_worker": true,
      "should_sign_as_client": true
    },
    "client_signature": "Jane Doe"
  }
}
```

**Response**

```json
{
  "data": {
    "pending_actions": [
      "create_contract"
    ],
    "engagement_status": "worker_invited",
    "engagement_created_at": "2026-09-01T00:00:00.000Z",
    "engagement_updated_at": "2026-09-01T00:00:00.000Z",
    "id": "9b1f7e3a-2c4d-4e5f-8a6b-1c2d3e4f5a6c",
    "created_at": "2026-09-01T00:00:00.000Z"
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/engagements"

payload = { "data": {
        "type": "ongoing_time_based",
        "title": "Data Labeler",
        "client": {
            "team_id": "tm_8817",
            "legal_entity_id": "le_acme_us"
        },
        "worker": {
            "first_name": "Ana",
            "expected_email": "ana@x.com",
            "last_name": "Rivera"
        },
        "start_date": "2026-09-01",
        "compensation_details": {
            "amount": 3000,
            "currency_code": "USD",
            "cycle_end": 31,
            "cycle_end_type": "DAY_OF_MONTH",
            "frequency": "monthly"
        },
        "actions": {
            "should_invite_worker": True,
            "should_sign_as_client": True
        },
        "client_signature": "Jane Doe"
    } }
headers = {
    "Idempotency-Key": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "X-Beta": "true",
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/engagements';
const options = {
  method: 'POST',
  headers: {
    'Idempotency-Key': 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
    'X-Beta': 'true',
    Authorization: 'Bearer <token>',
    'Content-Type': 'application/json'
  },
  body: '{"data":{"type":"ongoing_time_based","title":"Data Labeler","client":{"team_id":"tm_8817","legal_entity_id":"le_acme_us"},"worker":{"first_name":"Ana","expected_email":"ana@x.com","last_name":"Rivera"},"start_date":"2026-09-01","compensation_details":{"amount":3000,"currency_code":"USD","cycle_end":31,"cycle_end_type":"DAY_OF_MONTH","frequency":"monthly"},"actions":{"should_invite_worker":true,"should_sign_as_client":true},"client_signature":"Jane Doe"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/engagements"

	payload := strings.NewReader("{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
	req.Header.Add("X-Beta", "true")
	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d'
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.letsdeel.com/rest/engagements")
  .header("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.letsdeel.com/rest/engagements', [
  'body' => '{
  "data": {
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": {
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    },
    "worker": {
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    },
    "start_date": "2026-09-01",
    "compensation_details": {
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    },
    "actions": {
      "should_invite_worker": true,
      "should_sign_as_client": true
    },
    "client_signature": "Jane Doe"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
    'Idempotency-Key' => 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
    'X-Beta' => 'true',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d");
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Idempotency-Key": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "X-Beta": "true",
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["data": [
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": [
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    ],
    "worker": [
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    ],
    "start_date": "2026-09-01",
    "compensation_details": [
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    ],
    "actions": [
      "should_invite_worker": true,
      "should_sign_as_client": true
    ],
    "client_signature": "Jane Doe"
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Example 2

**Request**

```json
{
  "data": {
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": {
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    },
    "worker": {
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    },
    "start_date": "2026-09-01",
    "compensation_details": {
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    },
    "actions": {
      "should_invite_worker": true,
      "should_sign_as_client": true
    },
    "client_signature": "Jane Doe"
  }
}
```

**Response**

```json
{
  "data": {
    "pending_actions": [
      "create_contract"
    ],
    "engagement_status": "worker_invited",
    "engagement_created_at": "2026-09-01T00:00:00.000Z",
    "engagement_updated_at": "2026-09-01T00:00:00.000Z",
    "id": "9b1f7e3a-2c4d-4e5f-8a6b-1c2d3e4f5a6c",
    "created_at": "2026-09-01T00:00:00.000Z"
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/engagements"

payload = { "data": {
        "type": "ongoing_time_based",
        "title": "Data Labeler",
        "client": {
            "team_id": "tm_8817",
            "legal_entity_id": "le_acme_us"
        },
        "worker": {
            "first_name": "Ana",
            "expected_email": "ana@x.com",
            "last_name": "Rivera"
        },
        "start_date": "2026-09-01",
        "compensation_details": {
            "amount": 3000,
            "currency_code": "USD",
            "cycle_end": 31,
            "cycle_end_type": "DAY_OF_MONTH",
            "frequency": "monthly"
        },
        "actions": {
            "should_invite_worker": True,
            "should_sign_as_client": True
        },
        "client_signature": "Jane Doe"
    } }
headers = {
    "Idempotency-Key": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "X-Beta": "true",
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/engagements';
const options = {
  method: 'POST',
  headers: {
    'Idempotency-Key': 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
    'X-Beta': 'true',
    Authorization: 'Bearer <token>',
    'Content-Type': 'application/json'
  },
  body: '{"data":{"type":"ongoing_time_based","title":"Data Labeler","client":{"team_id":"tm_8817","legal_entity_id":"le_acme_us"},"worker":{"first_name":"Ana","expected_email":"ana@x.com","last_name":"Rivera"},"start_date":"2026-09-01","compensation_details":{"amount":3000,"currency_code":"USD","cycle_end":31,"cycle_end_type":"DAY_OF_MONTH","frequency":"monthly"},"actions":{"should_invite_worker":true,"should_sign_as_client":true},"client_signature":"Jane Doe"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.letsdeel.com/rest/engagements"

	payload := strings.NewReader("{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
	req.Header.Add("X-Beta", "true")
	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.letsdeel.com/rest/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d'
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.letsdeel.com/rest/engagements")
  .header("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.letsdeel.com/rest/engagements', [
  'body' => '{
  "data": {
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": {
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    },
    "worker": {
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    },
    "start_date": "2026-09-01",
    "compensation_details": {
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    },
    "actions": {
      "should_invite_worker": true,
      "should_sign_as_client": true
    },
    "client_signature": "Jane Doe"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
    'Idempotency-Key' => 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
    'X-Beta' => 'true',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Idempotency-Key", "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d");
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"data\": {\n    \"type\": \"ongoing_time_based\",\n    \"title\": \"Data Labeler\",\n    \"client\": {\n      \"team_id\": \"tm_8817\",\n      \"legal_entity_id\": \"le_acme_us\"\n    },\n    \"worker\": {\n      \"first_name\": \"Ana\",\n      \"expected_email\": \"ana@x.com\",\n      \"last_name\": \"Rivera\"\n    },\n    \"start_date\": \"2026-09-01\",\n    \"compensation_details\": {\n      \"amount\": 3000,\n      \"currency_code\": \"USD\",\n      \"cycle_end\": 31,\n      \"cycle_end_type\": \"DAY_OF_MONTH\",\n      \"frequency\": \"monthly\"\n    },\n    \"actions\": {\n      \"should_invite_worker\": true,\n      \"should_sign_as_client\": true\n    },\n    \"client_signature\": \"Jane Doe\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Idempotency-Key": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "X-Beta": "true",
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["data": [
    "type": "ongoing_time_based",
    "title": "Data Labeler",
    "client": [
      "team_id": "tm_8817",
      "legal_entity_id": "le_acme_us"
    ],
    "worker": [
      "first_name": "Ana",
      "expected_email": "ana@x.com",
      "last_name": "Rivera"
    ],
    "start_date": "2026-09-01",
    "compensation_details": [
      "amount": 3000,
      "currency_code": "USD",
      "cycle_end": 31,
      "cycle_end_type": "DAY_OF_MONTH",
      "frequency": "monthly"
    ],
    "actions": [
      "should_invite_worker": true,
      "should_sign_as_client": true
    ],
    "client_signature": "Jane Doe"
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```