> 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 a shift for a contract

POST https://api.letsdeel.com/rest/time-tracking/shifts
Content-Type: application/json

Records time a worker spent on a contract from an external time or workforce system, so the hours reach approval and payroll without manual entry. The shift goes through the same time tracking policy checks and approval flow as a shift entered by hand.

 **Token scopes**: `time-tracking:write`, `worker: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-13.

Reference: https://developer.deel.com/api/reference/endpoints/time-tracking-shifts/create-shift-v-2026-11-13

## 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) — Unique key for this write, up to 64 characters, kept for 24 hours. Repeating a successful request with the same key returns the first response instead of writing again; a failed request is not kept and can be retried with the same key. A request whose key is still in progress, or was used for a different request, gets 409.
- `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` (TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaData, required) — Fields for a new shift.

## Response

### 201

Shift created.

- `data` (TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaData, required) — A shift recorded on a contract.

## Errors

### 400 Bad Request Error

MALFORMED_REQUEST. The body is not valid JSON or lacks the data wrapper.

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 401 Unauthorized Error

The token is missing, invalid, inactive or revoked (INVALID_TOKEN, TOKEN_INACTIVE, TOKEN_REVOKED or UNAUTHORIZED).

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 403 Forbidden Error

INSUFFICIENT_SCOPES, APPROVED_STATUS_NOT_ALLOWED (APPROVED sent by a worker token), or ON_BEHALF_SUBMISSION_NOT_ALLOWED (the policy does not let clients submit on the worker's behalf).

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 404 Not Found Error

CONTRACT_NOT_FOUND. No such contract in the caller's organization, or a worker token sent a contract that is not theirs.

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 409 Conflict Error

IDEMPOTENCY_CONFLICT (a request with the same Idempotency-Key is still in progress; retry after the seconds in the retry-after header) or IDEMPOTENCY_KEY_REUSED (the key was already used for a different request).

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 422 Unprocessable Entity Error

The shift breaks one or more rules; every broken rule is listed. Codes: INVALID_FIELD, TIME_TRACKING_NOT_ENABLED, CONTRACT_TYPE_NOT_SUPPORTED (this API cannot yet write shifts on the contract's type), PROJECT_NOT_ON_CONTRACT, INVALID_SHIFT_ORIGIN, INVALID_SHIFT_TYPE, INVALID_DAY_TRACKING_DATA, CALLOUT_CONFLICT, OVERLAPPING_SHIFT, DAILY_CAP_EXCEEDED, SHIFT_CONTRACT_START_DATE, SHIFT_CONTRACT_COMPLETION_DATE, SHIFT_CONTRACT_IN_RESTRICTED_STATUS, DATE_OUTSIDE_ALLOWED_RANGE, FUTURE_DATED_SHIFT_SUBMISSION, BREAK_TYPE_NOT_AVAILABLE, BREAK_MAX_DURATION_EXCEEDED, BREAK_MISSED_OR_WAIVED, BREAK_DURATION_MISMATCH, MISSING_WORK_DESCRIPTION, SHIFT_MAX_WORKABLE_HOURS_VIOLATION, PUBLIC_HOLIDAY_VIOLATION, TIME_OFF_VIOLATION, SHIFT_CONTRACT_IN_TERMINATION_STATUS, ON_CALL_LATE_SUBMISSION, REMOTE_DAY_VIOLATION, INVALID_SHIFT_SUBMIT_TYPE, INVALID_SHIFT_KEEP_IN_TOUCH_DATE_INTERVAL, DAY_UNAVAILABLE, SHIFT_MAX_WORKING_DAYS_PER_YEAR_VIOLATION, SHIFT_MAX_CONSECUTIVE_DAYS_STREAK_VIOLATION, SHIFT_MAX_SATURDAYS_PER_YEAR_VIOLATION, LACTATION_BREAK_NOT_AVAILABLE, WORK_LOCATION_VIOLATION, OVERTIME_ACKNOWLEDGEMENT_REQUIRED (worker tokens only: the worker has not yet acknowledged the contract's overtime terms).

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 429 Too Many Requests Error

RATE_LIMITED. Over 5 requests per second for the organization.

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

### 500 Internal Server Error

INTERNAL_ERROR. Unexpected failure; safe to retry with the same Idempotency-Key.

- `errors` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems, required) — Every problem found, not only the first.

## Types

### TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaData

Fields for a new shift.

- `contract_id` (string, required) — Deel contract the shift is recorded on. Cannot change after the shift is created.
- `end` (string, optional, nullable) — Shift end as the local clock time where the work happened, without a UTC offset. Send with start; after start.
- `date` (string, optional) — Shift day, the local date the shift belongs to. Required for duration-only and DAY_TRACKING shifts; taken from start when omitted otherwise.
- `type` (enum, optional) — Kind of time the shift records. Which types a contract accepts depends on its time tracking policy.
  - Allowed values: `REGULAR`, `OVERTIME`, `ON_CALL`, `KEEP_IN_TOUCH`, `DAY_TRACKING`
- `start` (string, optional, nullable) — Shift start as the local clock time where the work happened, without a UTC offset (not UTC). Send with end; null or omitted for duration-only and DAY_TRACKING shifts. Stored as sent.
- `breaks` (list of TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaDataBreaksItems, optional) — Breaks inside the shift, without overlaps. Not accepted on duration-only shifts.
- `status` (enum, optional) — Approval status to set. PENDING sends the shift to approval. APPROVED is accepted from organization tokens only; worker tokens get 403.
  - Allowed values: `PENDING`, `APPROVED`
- `timezone` (string, optional, nullable) — IANA time zone the shift was worked in, stored as sent and not checked. When omitted or null, it is filled from the requester's profile, as in the app. Start and end are never converted to it.
- `call_outs` (list of TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaDataCallOutsItems, optional) — Call-outs inside an ON_CALL shift, without overlaps. Accepted only on ON_CALL shifts.
- `project_id` (string, optional, nullable) — Project the time was spent on. Must belong to the contract.
- `description` (string, optional, nullable) — What the worker did. Required when the time tracking policy requires a work description.
- `is_half_day` (boolean, optional) — Whether a DAY_TRACKING shift counts as half a day. Accepted only on DAY_TRACKING shifts.
- `worked_hours` (double, optional) — Hours worked. Required for duration-only shifts (no start or end); not accepted when start and end are sent, as Deel calculates it.
- `is_meal_break_waived` (boolean, optional) — Whether the worker waived the meal break. Accepted only when the time tracking policy allows waiving.

### TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaData

A shift recorded on a contract.

- `id` (string, required) — Deel ID of the shift; the shift_id path parameter.
- `end` (string, required, nullable) — Shift end as local clock time, without a UTC offset; null for duration-only and DAY_TRACKING shifts.
- `date` (string, required) — Shift day, the local date the shift belongs to.
- `type` (enum, required) — Kind of time the shift records. Which types a contract accepts depends on its time tracking policy.
  - Allowed values: `REGULAR`, `OVERTIME`, `ON_CALL`, `KEEP_IN_TOUCH`, `DAY_TRACKING`
- `start` (string, required, nullable) — Shift start as local clock time, without a UTC offset; null for duration-only and DAY_TRACKING shifts.
- `breaks` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaDataBreaksItems, required) — Breaks inside the shift; empty when there are none.
- `origin` (enum, required) — Channel the shift was entered through. PLATFORM is the Deel web app, ADMIN is Deel staff, AUTO_SUBMIT is automatic submission, INTERNAL_INTEGRATION is another Deel product, EXTERNAL_INTEGRATION is this API; null when the channel was not recorded.
  - Allowed values: `PLATFORM`, `MOBILE`, `ADMIN`, `AUTO_SUBMIT`, `INTERNAL_INTEGRATION`, `EXTERNAL_INTEGRATION`, `SLACK`
- `status` (enum, required) — Approval status of the shift. On a pay-as-you-go contract it follows the hourly report: APPROVED also covers hourly reports being processed, paid or marked not payable.
  - Allowed values: `PENDING`, `APPROVED`, `REJECTED`
- `timezone` (string, required, nullable) — IANA time zone the shift was worked in: as sent, or filled from the requester's profile when it was not sent; null when neither had one.
- `call_outs` (list of TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaDataCallOutsItems, required) — Call-outs inside an ON_CALL shift; empty for other types.
- `created_at` (string, required) — When the shift was created, in UTC.
- `project_id` (string, required, nullable) — Project the time was spent on; null when none.
- `updated_at` (string, required) — When the shift last changed, in UTC.
- `break_hours` (double, required) — Hours spent on breaks.
- `contract_id` (string, required) — Deel contract the shift is recorded on.
- `description` (string, required, nullable) — What the worker did; null when none.
- `total_hours` (double, required) — Hours from start to end, breaks included.
- `worked_hours` (double, required) — Hours worked, total hours minus break hours.
- `is_meal_break_waived` (boolean, required) — Whether the worker waived the meal break.
- `is_half_day` (boolean, optional) — Whether a DAY_TRACKING shift counts as half a day. Present only on DAY_TRACKING shifts.

### TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaErrorsItems

One problem with the request.

- `code` (string, required) — Stable machine-readable error code.
- `message` (string, required) — Human-readable explanation. May change; do not parse it.
- `field` (string, optional) — Request field the error refers to, when there is one.
- `details` (map from string to any, optional) — Extra data for the error code, such as the reason a shift is locked.

### TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaDataBreaksItems

A break taken inside the shift.

- `end` (string, required) — Break end, local time (no UTC offset). After start and not after the shift end.
- `type` (enum, required) — Kind of break. BREAK is a generic break; use MEAL_BREAK or REST_BREAK when known, and LACTATION_BREAK where the time tracking policy offers it.
  - Allowed values: `BREAK`, `MEAL_BREAK`, `REST_BREAK`, `LACTATION_BREAK`
- `start` (string, required) — Break start, local time where the work happened (no UTC offset).

### TimeTrackingShiftsPostRequestBodyContentApplicationJsonSchemaDataCallOutsItems

A period inside an on-call shift when the worker was called out to work.

- `end` (string, required) — Call-out end, local time (no UTC offset). After start and not after the shift end.
- `start` (string, required) — Call-out start, local time where the work happened (no UTC offset).

### TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaDataBreaksItems

A break taken inside the shift.

- `end` (string, required) — Break end, local time (no UTC offset). After start and not after the shift end.
- `type` (enum, required) — Kind of break. BREAK is a generic break; use MEAL_BREAK or REST_BREAK when known, and LACTATION_BREAK where the time tracking policy offers it.
  - Allowed values: `BREAK`, `MEAL_BREAK`, `REST_BREAK`, `LACTATION_BREAK`
- `start` (string, required) — Break start, local time where the work happened (no UTC offset).

### TimeTrackingShiftsPostResponsesContentApplicationJsonSchemaDataCallOutsItems

A period inside an on-call shift when the worker was called out to work.

- `end` (string, required) — Call-out end, local time (no UTC offset). After start and not after the shift end.
- `start` (string, required) — Call-out start, local time where the work happened (no UTC offset).

## Examples

**Request**

```json
{
  "data": {
    "contract_id": "m3x9k2p",
    "end": "2026-11-03T18:00:00",
    "type": "REGULAR",
    "start": "2026-11-03T09:00:00",
    "breaks": [
      {
        "end": "2026-11-03T13:00:00",
        "type": "MEAL_BREAK",
        "start": "2026-11-03T12:00:00"
      }
    ],
    "timezone": "America/Sao_Paulo",
    "project_id": "0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f",
    "description": "Warehouse night support"
  }
}
```

**Response**

```json
{
  "data": {
    "id": "9d2e4f6a-1b3c-4d5e-8f7a-2b4c6d8e0f1a",
    "end": "2026-11-03T18:00:00",
    "date": "2026-11-03",
    "type": "REGULAR",
    "start": "2026-11-03T09:00:00",
    "breaks": [
      {
        "end": "2026-11-03T13:00:00",
        "type": "MEAL_BREAK",
        "start": "2026-11-03T12:00:00"
      }
    ],
    "origin": "EXTERNAL_INTEGRATION",
    "status": "PENDING",
    "timezone": "America/Sao_Paulo",
    "call_outs": [
      {
        "end": "2026-11-03T16:30:00",
        "start": "2026-11-03T15:00:00"
      }
    ],
    "created_at": "2026-11-03T21:05:12Z",
    "project_id": "0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f",
    "updated_at": "2026-11-03T21:05:12Z",
    "break_hours": 1,
    "contract_id": "m3x9k2p",
    "description": "Warehouse night support",
    "total_hours": 9,
    "worked_hours": 8,
    "is_meal_break_waived": false,
    "is_half_day": false
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/time-tracking/shifts"

payload = { "data": {
        "contract_id": "m3x9k2p",
        "end": "2026-11-03T18:00:00",
        "type": "REGULAR",
        "start": "2026-11-03T09:00:00",
        "breaks": [
            {
                "end": "2026-11-03T13:00:00",
                "type": "MEAL_BREAK",
                "start": "2026-11-03T12:00:00"
            }
        ],
        "timezone": "America/Sao_Paulo",
        "project_id": "0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f",
        "description": "Warehouse night support"
    } }
headers = {
    "Idempotency-Key": "3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c",
    "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/time-tracking/shifts';
const options = {
  method: 'POST',
  headers: {
    'Idempotency-Key': '3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c',
    'X-Beta': 'true',
    Authorization: 'Bearer <token>',
    'Content-Type': 'application/json'
  },
  body: '{"data":{"contract_id":"m3x9k2p","end":"2026-11-03T18:00:00","type":"REGULAR","start":"2026-11-03T09:00:00","breaks":[{"end":"2026-11-03T13:00:00","type":"MEAL_BREAK","start":"2026-11-03T12:00:00"}],"timezone":"America/Sao_Paulo","project_id":"0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f","description":"Warehouse night support"}}'
};

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/time-tracking/shifts"

	payload := strings.NewReader("{\n  \"data\": {\n    \"contract_id\": \"m3x9k2p\",\n    \"end\": \"2026-11-03T18:00:00\",\n    \"type\": \"REGULAR\",\n    \"start\": \"2026-11-03T09:00:00\",\n    \"breaks\": [\n      {\n        \"end\": \"2026-11-03T13:00:00\",\n        \"type\": \"MEAL_BREAK\",\n        \"start\": \"2026-11-03T12:00:00\"\n      }\n    ],\n    \"timezone\": \"America/Sao_Paulo\",\n    \"project_id\": \"0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f\",\n    \"description\": \"Warehouse night support\"\n  }\n}")

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

	req.Header.Add("Idempotency-Key", "3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c")
	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/time-tracking/shifts")

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

request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c'
request["X-Beta"] = 'true'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"data\": {\n    \"contract_id\": \"m3x9k2p\",\n    \"end\": \"2026-11-03T18:00:00\",\n    \"type\": \"REGULAR\",\n    \"start\": \"2026-11-03T09:00:00\",\n    \"breaks\": [\n      {\n        \"end\": \"2026-11-03T13:00:00\",\n        \"type\": \"MEAL_BREAK\",\n        \"start\": \"2026-11-03T12:00:00\"\n      }\n    ],\n    \"timezone\": \"America/Sao_Paulo\",\n    \"project_id\": \"0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f\",\n    \"description\": \"Warehouse night support\"\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/time-tracking/shifts")
  .header("Idempotency-Key", "3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c")
  .header("X-Beta", "true")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"data\": {\n    \"contract_id\": \"m3x9k2p\",\n    \"end\": \"2026-11-03T18:00:00\",\n    \"type\": \"REGULAR\",\n    \"start\": \"2026-11-03T09:00:00\",\n    \"breaks\": [\n      {\n        \"end\": \"2026-11-03T13:00:00\",\n        \"type\": \"MEAL_BREAK\",\n        \"start\": \"2026-11-03T12:00:00\"\n      }\n    ],\n    \"timezone\": \"America/Sao_Paulo\",\n    \"project_id\": \"0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f\",\n    \"description\": \"Warehouse night support\"\n  }\n}")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.letsdeel.com/rest/time-tracking/shifts', [
  'body' => '{
  "data": {
    "contract_id": "m3x9k2p",
    "end": "2026-11-03T18:00:00",
    "type": "REGULAR",
    "start": "2026-11-03T09:00:00",
    "breaks": [
      {
        "end": "2026-11-03T13:00:00",
        "type": "MEAL_BREAK",
        "start": "2026-11-03T12:00:00"
      }
    ],
    "timezone": "America/Sao_Paulo",
    "project_id": "0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f",
    "description": "Warehouse night support"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
    'Idempotency-Key' => '3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c',
    'X-Beta' => 'true',
  ],
]);

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

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/time-tracking/shifts");
var request = new RestRequest(Method.POST);
request.AddHeader("Idempotency-Key", "3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c");
request.AddHeader("X-Beta", "true");
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"data\": {\n    \"contract_id\": \"m3x9k2p\",\n    \"end\": \"2026-11-03T18:00:00\",\n    \"type\": \"REGULAR\",\n    \"start\": \"2026-11-03T09:00:00\",\n    \"breaks\": [\n      {\n        \"end\": \"2026-11-03T13:00:00\",\n        \"type\": \"MEAL_BREAK\",\n        \"start\": \"2026-11-03T12:00:00\"\n      }\n    ],\n    \"timezone\": \"America/Sao_Paulo\",\n    \"project_id\": \"0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f\",\n    \"description\": \"Warehouse night support\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Idempotency-Key": "3f1c2b9e-7a4d-4e1b-9c2a-5d8e6f7a1b2c",
  "X-Beta": "true",
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["data": [
    "contract_id": "m3x9k2p",
    "end": "2026-11-03T18:00:00",
    "type": "REGULAR",
    "start": "2026-11-03T09:00:00",
    "breaks": [
      [
        "end": "2026-11-03T13:00:00",
        "type": "MEAL_BREAK",
        "start": "2026-11-03T12:00:00"
      ]
    ],
    "timezone": "America/Sao_Paulo",
    "project_id": "0b6f3c1e-2d4a-4f8b-9e7c-1a2b3c4d5e6f",
    "description": "Warehouse night support"
  ]] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/time-tracking/shifts")! 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()
```