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

# Update a shift

PATCH https://api.letsdeel.com/rest/time_tracking/shifts/{external_id}
Content-Type: application/json

Applies a partial update to an existing shift, modifying only the fields supplied in the request body. Fields omitted from the request are left unchanged. Correction shifts cannot be updated through this endpoint, the update is blocked once the payroll cycle the shift belongs to has closed, and `summary.shift_rate_external_id` cannot be repointed to a shift rate of a different type than the shift currently has.

 **Token scopes**: `time-tracking:write`

Reference: https://developer.deel.com/api/endpoints/time-tracking-shifts/update-time-tracking-shift-by-external-id

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

### Path parameters

- `external_id` (string, required) — Unique identifier of the shift to be updated.

### Body (application/json)

This endpoint expects an object.

- `data` (TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaData, required)

## Response

### 200

Shift updated successfully.

- `data` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaData, required)

## Errors

### 401 Unauthorized Error

Operation failed.

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

### 500 Internal Server Error

Operation failed.

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

## Types

### TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaData

- `summary` (TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaDataSummary, optional)
- `description` (string, optional) — The updated description of the shift.
- `date_of_work` (string, optional) — The updated date of the shift, in YYYY-MM-DD format.
- `payroll_cycle_ref` (TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaDataPayrollCycleRef, optional) — Payroll cycle reference

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaData

- `created_at` (string, required) — Date when the shift was created
- `shift_type` (enum, required) — Type of the shift
  - Allowed values: `REGULAR`, `CORRECTION_ABSOLUTE`, `CORRECTION_DELTA`, `TIME_OFF_QUALIFYING`
- `updated_at` (string, required) — Date when the shift was last updated
- `contract_id` (string, required) — Associated contract ID for the shift
- `description` (string, required) — Description of the shift
- `external_id` (string, required) — ID specified by the client for uniquely identifying the shift
- `date_of_work` (string, required) — Date when the shift takes place, in YYYY-MM-DD format
- `meta` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMeta, optional)
- `summary` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataSummary, optional)
- `payroll_cycle_ref` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataPayrollCycleRef, optional) — Payroll cycle reference
- `shift_reference_id` (string, optional) — External ID of the original shift this one references (set on correction shifts).

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

### TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaDataSummary

- `time_amount` (double, optional) — The amount of time for the shift. Part of the unit-amount summary group, required when the shift rate is PER_UNIT_FLAT_RATE (or MULTIPLIER_PERCENTAGE/omitted, where either group is accepted). Mutually exclusive with `shift_duration_hours`/`total_break_hours`/`payable_break_hours`/`total_payable_hours` — do not send both groups.
- `total_break_hours` (double, optional) — Total break duration in hours. Part of the hours-based summary group (see `shift_duration_hours`).
- `payable_break_hours` (double, optional) — Break hours that are payable. Part of the hours-based summary group (see `shift_duration_hours`).
- `total_payable_hours` (double, optional) — Total payable working hours after break deductions. Part of the hours-based summary group (see `shift_duration_hours`).
- `shift_duration_hours` (double, optional) — Total duration of the shift in hours. Part of the hours-based summary group, used when the shift rate is PER_HOUR_FLAT_RATE (or MULTIPLIER_PERCENTAGE/omitted, where either group is accepted). Mutually exclusive with `time_amount`/`time_unit` — do not send both groups.
- `shift_rate_external_id` (string, optional) — External ID of the shift rate associated with this shift. Its type (PER_UNIT_FLAT_RATE, PER_HOUR_FLAT_RATE, or MULTIPLIER_PERCENTAGE) determines which of the two field groups below is required — see the group descriptions.

### TimeTrackingShiftsExternalIdPatchRequestBodyContentApplicationJsonSchemaDataPayrollCycleRef

Payroll cycle reference

- `date` (string, required) — date in ISO

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMeta

- `end` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaEnd, required)
- `start` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaStart, required)
- `breaks` (list of TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItems, optional)
- `approval_date` (string, optional) — Approval date for the shift, in ISO format

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataSummary

- `shift_rate_external_id` (string, required) — External ID of the shift rate associated with this shift
- `time_unit` (enum, optional) — The unit of time for the shift (DAY, HOUR, MONTH, WEEK)
  - Allowed values: `DAY`, `HOUR`, `MONTH`, `WEEK`
- `time_amount` (double, optional) — The amount of time for the shift
- `total_break_hours` (double, optional) — Total break duration in hours
- `payable_break_hours` (double, optional) — Break hours that are payable
- `total_payable_hours` (double, optional) — Total payable working hours after break deductions
- `shift_duration_hours` (double, optional) — Total duration of the shift in hours

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataPayrollCycleRef

Payroll cycle reference

- `date` (string, required) — date in ISO

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaEnd

- `date` (string, required) — Shift end date
- `time` (string, required) — Shift end time in HH:mm format
- `is_rest_day` (boolean, required) — Indicates if it is a rest day
- `is_public_holiday` (boolean, required) — Indicates if it is a public holiday

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaStart

- `date` (string, required) — Shift start date
- `time` (string, required) — Shift start time in HH:mm format
- `is_rest_day` (boolean, required) — Indicates if it is a rest day
- `is_public_holiday` (boolean, required) — Indicates if it is a public holiday

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItems

- `end` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItemsEnd, required)
- `start` (TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItemsStart, required)
- `is_paid` (boolean, optional) — Indicates if the break is paid

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItemsEnd

- `date` (string, required) — Break end date
- `time` (string, required) — Break end time in HH:mm format

### TimeTrackingShiftsExternalIdPatchResponsesContentApplicationJsonSchemaDataMetaBreaksItemsStart

- `date` (string, required) — Break start date
- `time` (string, required) — Break start time in HH:mm format

## Examples

**Request**

```json
{
  "data": {
    "summary": {
      "total_break_hours": 0.5,
      "payable_break_hours": 0.5,
      "total_payable_hours": 7.5,
      "shift_duration_hours": 8,
      "shift_rate_external_id": "shift-rate-id-789"
    },
    "description": "Night shift at warehouse",
    "date_of_work": "2024-02-12"
  }
}
```

**Response**

```json
{
  "data": {
    "created_at": "2024-02-01T00:00:00.000Z",
    "shift_type": "REGULAR",
    "updated_at": "2024-02-10T00:00:00.000Z",
    "contract_id": "contract-id-456",
    "description": "Night shift at warehouse",
    "external_id": "external-id-123",
    "date_of_work": "2024-02-12",
    "meta": {
      "end": {
        "date": "2024-02-12",
        "time": "16:00",
        "is_rest_day": false,
        "is_public_holiday": false
      },
      "start": {
        "date": "2024-02-12",
        "time": "08:00",
        "is_rest_day": false,
        "is_public_holiday": false
      }
    },
    "summary": {
      "shift_rate_external_id": "shift-rate-id-789",
      "time_unit": "HOUR",
      "time_amount": 8,
      "total_break_hours": 0.5,
      "payable_break_hours": 0.5,
      "total_payable_hours": 7.5,
      "shift_duration_hours": 8
    },
    "payroll_cycle_ref": {
      "date": "2024-02-11T12:00:00.000Z"
    }
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.letsdeel.com/rest/time_tracking/shifts/12345678g"

payload = { "data": {
        "summary": {
            "total_break_hours": 0.5,
            "payable_break_hours": 0.5,
            "total_payable_hours": 7.5,
            "shift_duration_hours": 8,
            "shift_rate_external_id": "shift-rate-id-789"
        },
        "description": "Night shift at warehouse",
        "date_of_work": "2024-02-12"
    } }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript
const url = 'https://api.letsdeel.com/rest/time_tracking/shifts/12345678g';
const options = {
  method: 'PATCH',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"data":{"summary":{"total_break_hours":0.5,"payable_break_hours":0.5,"total_payable_hours":7.5,"shift_duration_hours":8,"shift_rate_external_id":"shift-rate-id-789"},"description":"Night shift at warehouse","date_of_work":"2024-02-12"}}'
};

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/12345678g"

	payload := strings.NewReader("{\n  \"data\": {\n    \"summary\": {\n      \"total_break_hours\": 0.5,\n      \"payable_break_hours\": 0.5,\n      \"total_payable_hours\": 7.5,\n      \"shift_duration_hours\": 8,\n      \"shift_rate_external_id\": \"shift-rate-id-789\"\n    },\n    \"description\": \"Night shift at warehouse\",\n    \"date_of_work\": \"2024-02-12\"\n  }\n}")

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

	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/12345678g")

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

request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"data\": {\n    \"summary\": {\n      \"total_break_hours\": 0.5,\n      \"payable_break_hours\": 0.5,\n      \"total_payable_hours\": 7.5,\n      \"shift_duration_hours\": 8,\n      \"shift_rate_external_id\": \"shift-rate-id-789\"\n    },\n    \"description\": \"Night shift at warehouse\",\n    \"date_of_work\": \"2024-02-12\"\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.patch("https://api.letsdeel.com/rest/time_tracking/shifts/12345678g")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"data\": {\n    \"summary\": {\n      \"total_break_hours\": 0.5,\n      \"payable_break_hours\": 0.5,\n      \"total_payable_hours\": 7.5,\n      \"shift_duration_hours\": 8,\n      \"shift_rate_external_id\": \"shift-rate-id-789\"\n    },\n    \"description\": \"Night shift at warehouse\",\n    \"date_of_work\": \"2024-02-12\"\n  }\n}")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://api.letsdeel.com/rest/time_tracking/shifts/12345678g', [
  'body' => '{
  "data": {
    "summary": {
      "total_break_hours": 0.5,
      "payable_break_hours": 0.5,
      "total_payable_hours": 7.5,
      "shift_duration_hours": 8,
      "shift_rate_external_id": "shift-rate-id-789"
    },
    "description": "Night shift at warehouse",
    "date_of_work": "2024-02-12"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

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

```csharp
using RestSharp;

var client = new RestClient("https://api.letsdeel.com/rest/time_tracking/shifts/12345678g");
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"data\": {\n    \"summary\": {\n      \"total_break_hours\": 0.5,\n      \"payable_break_hours\": 0.5,\n      \"total_payable_hours\": 7.5,\n      \"shift_duration_hours\": 8,\n      \"shift_rate_external_id\": \"shift-rate-id-789\"\n    },\n    \"description\": \"Night shift at warehouse\",\n    \"date_of_work\": \"2024-02-12\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["data": [
    "summary": [
      "total_break_hours": 0.5,
      "payable_break_hours": 0.5,
      "total_payable_hours": 7.5,
      "shift_duration_hours": 8,
      "shift_rate_external_id": "shift-rate-id-789"
    ],
    "description": "Night shift at warehouse",
    "date_of_work": "2024-02-12"
  ]] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://api.letsdeel.com/rest/time_tracking/shifts/12345678g")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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()
```