Contract amendments

Update contract terms through a structured approval process

Overview

The EOR contract amendment API lets you update contract terms through a structured approval process that follows predefined compliance rules.

An amendment is a change to one or more contract terms, referred to as data points, such as employment type, job title, scope, or salary. Instead of modifying the original contract document, the amendment is issued as a separate addendum to the employment agreement.

The contract entity in the database, including its ID, remains the same. Only specific values are updated with a new effective date.

Amendment flows

Amendments can be initiated by you or by Deel. The steps an amendment goes through differ depending on who initiates it.

Client-initiated amendments

1

Create the amendment

Use the Create amendment endpoint to start a new amendment.

2

Update fields

Modify fields as needed with the Update amendment endpoint.

3

Confirm the amendment

Finalize with the Confirm amendment endpoint.

After confirmation:

  • If the change is applied immediately, the API response includes the updated status.
  • If the change requires approval, Deel reviews it and sends it to the employee for signing.

Deel-initiated amendments

1

Deel creates the amendment

Deel initiates the amendment and notifies you.

2

Review and decide

Accept with the Accept amendment endpoint or cancel with the Cancel amendment endpoint.

3

Employee signature

If you accept, the employee reviews and signs with the Sign amendment endpoint.

When Deel creates amendments

Deel may create amendments in these cases:

  • At your request when a change requires Deel involvement.
  • To ensure compliance when a contract update is needed to meet legal requirements.
  • For restricted changes when updates are only available through admin amendments.

Webhook events

Webhooks provide automatic updates on amendment status changes.

EventDescription
EOR_AMENDMENT_V2_IN_REVIEWTriggered when you create an amendment
EOR_AMENDMENT_V2_CLIENT_SIGNTriggered when Deel creates an amendment
EOR_AMENDMENT_V2_EMPLOYEE_SIGNTriggered when you accept an amendment created by Deel
EOR_AMENDMENT_V2_CLIENT_ACTIVETriggered when an amendment becomes active after all approvals are complete
EOR_AMENDMENT_V2_CLIENT_REJECTEDTriggered when an amendment is canceled
EOR_AMENDMENT_V2_CLIENT_VOIDTriggered when an amendment is voided after the deadline passes

Amendment types

Each amendment has a type that determines its processing flow. The type is based on the amendment settings and the data points being amended.

  • INSTANT: Activated immediately after confirmation. No Deel review or employee signature required.
  • AUTOMATED: Activated once the employee signs. Deel review not required.
  • LEGAL or OPS: Requires Deel review because at least one data point requires internal review. After Deel completes the review, the amendment is sent to the employee for signature.
  • DISABLED: Contains at least one data point that is restricted from being changed.
  • CUSTOM: Manually created by a Deel admin.

If at least one data point requires Deel review (LEGAL or OPS), the amendment type is set to match. All data points follow the same review and activation flow.

Example: Instant amendment

In this Germany example, both holidays and timeOffType changes are instant.

1{
2 "type": "INSTANT",
3 "items": [
4 {
5 "data_point": "holidays",
6 "id": "59d9a2d5-9ea0-4f7f-8ac0-1db66e62d9fa",
7 "item": "holidaysIncrease",
8 "type": "INSTANT",
9 "previous_value": "6",
10 "new_value": "12"
11 },
12 {
13 "data_point": "timeOffType",
14 "id": "78743852-4dea-4b7c-bbac-44828a7d9b97",
15 "item": "timeOffType",
16 "type": "INSTANT",
17 "previous_value": "STANDARD",
18 "new_value": "SPECIFIC"
19 }
20 ]
21}

For Greece, the same data points require Deel review because one item has the LEGAL type.

1{
2 "type": "LEGAL",
3 "items": [
4 {
5 "data_point": "holidays",
6 "id": "f783003f-777f-425a-9a14-faf6457b7585",
7 "item": "holidaysIncrease",
8 "type": "INSTANT",
9 "previous_value": "6",
10 "new_value": "10"
11 },
12 {
13 "data_point": "timeOffType",
14 "id": "d9dffd0a-6443-4992-9aa7-d859bd9d4d4d",
15 "item": "timeOffType",
16 "type": "LEGAL",
17 "previous_value": "STANDARD",
18 "new_value": "SPECIFIC"
19 }
20 ]
21}

Retrieve contract information

To retrieve available amendment settings, you first need the contract ID.

Use the List of contracts endpoint to retrieve your contracts. You can filter and sort the list to find the correct contract_id.

$curl --location -g --request GET '{{host}}/rest/v2/contracts?limit=2&sort_by=worker_name&order_direction=desc' \
>--header 'Authorization: Bearer {{token}}'

Retrieve amendment settings

Once you have a contract ID, use it to retrieve valid amendment settings using the Get Amendment validation settings endpoint.

These settings are based on the contract and country-specific rules.

$curl --location -g --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/validation/settings' \
>--header 'Authorization: Bearer {{token}}'

The validation settings endpoint accepts an optional employment_state query parameter to provide more accurate validation rules based on the intended state or region.

Use this when you need to amend the employment_state and need validation rules specific to the new state.

For example, hourly rate minimum wages can vary by state. If not provided, the current contract’s employment state is used for validation rules.

Example with query parameters

$curl --location -g --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/validation/settings?employment_state=CA' \
>--header 'Authorization: Bearer {{token}}'

Example response

1[
2 {
3 "data_point": "notice_period_type",
4 "rules": [
5 {
6 "nullable": false,
7 "is_editable": true,
8 "possible_options": ["STANDARD", "CUSTOM"],
9 "requires": {
10 "employment_type": "FULL_TIME"
11 }
12 },
13 {
14 "nullable": false,
15 "is_editable": true,
16 "possible_options": ["STANDARD", "CUSTOM"],
17 "requires": {
18 "employment_type": "PART_TIME"
19 }
20 }
21 ]
22 }
23]

Amendment settings structure

The response for amendment settings includes a list of configurable contract fields. Each field is described by a data_point object that defines how it can be changed.

Key elements

  • Each data_point represents an attribute in the contract that may be amended.
  • The requires object defines conditions that must be met for the change to be allowed. All fields in requires must match either the current contract or the amendment request.
  • Numeric fields include min and max constraints.
  • possible_options lists the allowed values for the data point.
  • is_editable indicates if the field can be updated.
  • additional_details may include validation notes or business constraints.
  • Date fields can include min_date and max_date, formatted as YYYY-MM-DD.

Rule examples

Require a field in the contract or request

You can only apply this rule if the contract or amendment request includes contract_term: "DEFINITE".

1{
2 "nullable": false,
3 "is_editable": true,
4 "min_date": "2025-06-02",
5 "requires": {
6 "contract_term": "DEFINITE"
7 }
8}

Employment type restriction

You can set employment_type to FULL_TIME only if contract_term is INDEFINITE.

1{
2 "nullable": false,
3 "is_editable": true,
4 "possible_options": ["FULL_TIME"],
5 "requires": { "contract_term": "INDEFINITE" }
6}

Numeric constraints

This rule allows minimum and maximum values when employment_type is FULL_TIME.

1{
2 "nullable": false,
3 "is_editable": true,
4 "min": 6,
5 "max": 12,
6 "requires": { "employment_type": "FULL_TIME" }
7}

External validation

This rule indicates that complete validation requires calling the validate amendment endpoint.

When external_validation: true, you can either call the validate endpoint for server-side validation or skip validation and let the create/update endpoints return validation errors.

1{
2 "nullable": false,
3 "is_editable": true,
4 "external_validation": true
5}

Amendment effective date

The effective date is when the amendment becomes active. It defines when changes take effect and appear in payroll, invoices, or other downstream processes.

Different amendment fields trigger different business logic. Based on what you are changing, Deel dynamically calculates a valid effective date range.

Use the Effective Date Limitations endpoint to retrieve the valid effective date limits for a specific amendment.

Amendments on contracts that are not yet active cannot have an effective date.

Fetching effective date limits

You must fetch the effective date limitations:

  • Immediately after creating or updating an amendment.
  • Before setting or submitting the effective date.
  • Before confirming the amendment if any changes were made after fetching the last effective date.

The valid effective date range is based on the specific changes in the amendment. Always fetch the date limits only after all changes to the amendment are finalized.

Status behavior by effective date

Effective dateWhat happens
Effective date in the futureThe amendment gets an upcoming status. It will not affect contract values immediately.
Effective date today or pastThe amendment becomes active as soon as it is processed and signed.
Effective date not providedThe amendment becomes active immediately after signing. Deel uses the date when all parties confirm as the effective date.

Amendments in upcoming status do not affect payroll, invoicing, or contract terms until they are activated by Deel’s internal job on the effective date.

High-level flow

The diagram below shows how the effective date influences the amendment lifecycle.

UI behavior

When you fetch effective date limitations, the response includes flags that guide you in rendering the field in your UI.

FieldClient-side behavior
is_hiddenSuggests that the field may be hidden from the user interface. You may decide whether to follow this.
is_disabledIf true, the field should not be editable. You must use default_effective_date.

If your use case involves applying an automatic default effective date, such as aligning it with the start of the payroll cycle, hiding the field might improve user experience.

Effective date validation rules

The validation logic for effective dates ensures that all amendments respect configuration limits.

ScenarioRequirement
is_disabled = true and is_hidden = trueField must not be included in the request.
is_disabled = true and default date is presentField must exactly match the default effective date.
min_effective_date, max_effective_date, or default_effective_date is presentA valid effective date must be provided and must fall within range.
No limits definedField is optional. System will automatically set it to when all parties confirm the amendment.

Validation runs at two points:

  • On create or update when you send the effective date in the request payload.
  • On confirmation when the effective date is always validated, regardless of draft status.
Draft amendments are validated only when you provide an effective date.

Create a draft amendment

Create a new draft amendment by specifying the contract_id. You can include all, some, or none of the data points you plan to amend.

This allows you to start with a basic amendment and add more details later.

Empty amendment

$curl --location -g --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> }
>}'

Amendment with data points

$curl --location -g --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "time_off_type": "SPECIFIC",
> "holidays": 12,
> "employment_type": "PART_TIME"
> }
>}'

Update existing draft amendment

Update an existing draft amendment by including the amendment_id returned when the amendment was created.

You can add additional data points, modify existing ones, or set the effective date. This endpoint allows you to build your amendment incrementally.

Updating an amendment replaces its full set of data points. Each update request must contain all the data points you want to keep, not just the one you are changing. If you only send the newly updated data point, any previously saved data points that are not included will be removed from the amendment.

$curl --location -g --request PATCH '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "time_off_type": "SPECIFIC",
> "holidays": 12,
> "employment_type": "PART_TIME",
> "effective_date": "2025-08-01"
> }
>}'

Amendment validation approaches

You have these options for validating amendment data points:

  • Client-side validation: Use the validation rules from the amendment settings endpoint to validate fields before submission.
  • Server-side validation: Use the validate amendment endpoint to validate fields before submission.
  • Hybrid approach: Use client-side validation for basic fields and server-side validation for complex fields with external_validation: true.
  • No pre-validation: Skip validation and let the create/update endpoints return validation errors.

The amendment submission endpoint always performs validation and returns errors, so pre-validation is optional.

However, for fields with external_validation: true, you may want to validate beforehand to provide better user experience or to perform AI job scope checks and job categorization.

Hybrid approach

The hybrid approach combines both validation methods for optimal performance and user experience:

  • Use client-side validation for fields with external_validation: false to provide immediate feedback.
  • Use server-side validation for fields with external_validation: true to get complete validation.

Validate amendment data points

Use the validate amendment endpoint to validate amendment data points before submission.

The /validate endpoint is deprecated. Use validate amendment for new implementations.

$curl --location --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/validate-amendment' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "job_title": "Senior Software Engineer",
> "scope": "Lead development of web applications"
> }
>}'

Response format

The response includes validation results with field-specific error mapping.

1{
2 "data": {
3 "is_valid": true,
4 "validation_error": [],
5 "disabled_amendments": [],
6 "ai_job_scope_and_title_check": {
7 "is_valid": true,
8 "ai_scope_check_public_id": "9f9e086f-2195-4ced-a641-c62d5cd388fc"
9 },
10 "job_categorization": {
11 "is_valid": true,
12 "job_categorization_log_id": "366681cd-fe16-4be7-9e45-692a4bbc91c0",
13 "job_category": "Software Engineer",
14 "job_code": "214129"
15 }
16 }
17}

Error response with field mapping

When validation fails, errors include a field parameter for easy frontend integration.

1{
2 "data": {
3 "is_valid": false,
4 "validation_error": [
5 {
6 "code": "AMENDMENT_ITEM_VALIDATION_FAILED",
7 "message": "Scope exceeds maximum length of 20,000 characters",
8 "field": "scope",
9 "details": {
10 "newValue": "Very long scope description...",
11 "previousValue": "Short scope"
12 }
13 }
14 ],
15 "disabled_amendments": [],
16 "ai_job_scope_and_title_check": null,
17 "job_categorization": null
18 }
19}

AI job scope check and job categorization

AI review check

When a job title or scope amendment is created or updated, an AI review check is triggered to ensure the new job title or scope aligns with the existing job description and responsibilities.

1

Trigger the AI review check

Call the validate amendment endpoint for the AI review check to be performed before creating or updating the job title or scope amendment.

2

Submit the amendment

You can submit the amendment regardless of the AI review outcome. If the AI review fails, the amendment will be flagged for manual review by Deel’s internal team.

3

Use the AI scope check ID

You will get ai_scope_check_public_id when using the validate amendment endpoint if the AI review succeeds. Send this ID in the amendment request to avoid manual review.

Example: Validate job title and scope

1{
2 "url": "https://api.letsdeel.com/rest/v2/eor/contracts/{{contract_id}}/amendments/validate-amendment",
3 "method": "POST",
4 "headers": {
5 "accept": "application/json",
6 "Content-Type": "application/json",
7 "Authorization": "Bearer {API_TOKEN}"
8 },
9 "body": {
10 "data": {
11 "job_title": "Senior Software Manager"
12 }
13 }
14}

Response:

1{
2 "data": {
3 "is_valid": true,
4 "validation_error": [],
5 "disabled_amendments": [],
6 "ai_job_scope_and_title_check": {
7 "is_valid": true,
8 "ai_scope_check_public_id": "9f9e086f-2195-4ced-a641-c62d5cd388fc"
9 },
10 "job_categorization": null
11 }
12}

Example: Create or update amendment with AI scope check ID

1{
2 "url": "https://api.letsdeel.com/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}",
3 "method": "PATCH",
4 "body": {
5 "job_title": "Senior Software Manager",
6 "additional_info": {
7 "ai_scope_check_public_id": "9f9e086f-2195-4ced-a641-c62d5cd388fc"
8 }
9 }
10}

Job categorization with AI recommendations

Job categorization is only available for specific countries. Every time a job title is amended, an AI job categorization is triggered to classify the new job title into a predefined job category and code.

CountryAI Generates
BulgariaJob code and category
LatviaJob code and category
RomaniaJob code and category
UkraineJob category

You can trigger the validate amendment endpoint for the AI job categorization to be performed before creating or updating the job title amendment.

You can submit the amendment regardless of the AI job categorization outcome. If the AI job categorization fails, the amendment will be flagged for manual review by Deel’s internal team.

You will get job_categorization_log_id, job_code, and job_category when using the validate amendment endpoint if the AI job categorization succeeds. Send these values in the create or update amendment request to avoid manual review.

Example: Validate job title for categorization

1{
2 "url": "https://api.letsdeel.com/rest/v2/eor/contracts/{{contract_id}}/amendments/validate-amendment",
3 "method": "POST",
4 "body": {
5 "data": {
6 "job_title": "Senior Software Manager"
7 }
8 }
9}

Response:

1{
2 "data": {
3 "is_valid": true,
4 "validation_error": [],
5 "disabled_amendments": [],
6 "ai_job_scope_and_title_check": {
7 "is_valid": false,
8 "message": "Job scope is too short"
9 },
10 "job_categorization": {
11 "is_valid": true,
12 "job_categorization_log_id": "366681cd-fe16-4be7-9e45-692a4bbc91c0",
13 "job_category": "Manager, Software Development",
14 "job_code": "13306011"
15 }
16 }
17}

Example: Update amendment with job categorization

1{
2 "url": "https://api.letsdeel.com/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}",
3 "method": "PATCH",
4 "body": {
5 "job_title": "Senior Software Manager",
6 "additional_info": {
7 "job_categorization_log_id": "366681cd-fe16-4be7-9e45-692a4bbc91c0"
8 },
9 "job_category": "Manager, Software Development",
10 "job_code": "13306011"
11 }
12}

Combined AI check and job categorization

When you trigger the validate amendment endpoint for job title amendments:

  • In countries where job categorization is supported, both AI check and job categorization run. You must send ai_scope_check_public_id and job_categorization_log_id together with job_code and job_category to avoid manual review.
  • In countries where job categorization is not supported, only AI check runs.
1{
2 "url": "https://api.letsdeel.com/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}",
3 "method": "PATCH",
4 "body": {
5 "job_title": "Senior Software Manager",
6 "additional_info": {
7 "ai_scope_check_public_id": "9f9e086f-2195-4ced-a641-c62d5cd388fc",
8 "job_categorization_log_id": "366681cd-fe16-4be7-9e45-692a4bbc91c0"
9 },
10 "job_category": "Manager, Software Development",
11 "job_code": "13306011"
12 }
13}

Seniority ID

To amend seniority_id:

  1. Retrieve the list of available levels using the Get Seniority List endpoint.
  2. Include the selected seniority_id in your amendment request.

Effective date limitations

1

Create an amendment

Use the Create Amendment endpoint.

2

Call the effective date limitations endpoint

Use the Get Effective Date Limitations endpoint.

3

Set the effective date in the UI

Use the returned rules to set the effective date in the UI.

4

Submit the amendment

If required, submit the amendment with an effective date.

Validation errors and disabled amendments

Amendment requests can fail if validation rules are not met. In these cases, the API returns an error response that includes details about validation errors and disabled data points.

Standard error format

All error responses follow a consistent format, making them easier to interpret and integrate.

Each response includes a code and a message field, while the field attribute remains optional.

Mandatory fields

FieldTypeDescriptionExample
errorsarrayArray of error objects[{...}]
errors[].codestringError code identifier"VALIDATION_ERROR"
errors[].messagestringHuman-readable error message"Internal validation error occurred"

Optional fields

FieldTypeDescriptionExample
errors[].fieldstringField name that caused the error"effective_date"
errors[].detailsobjectAdditional error context in free-form object structure{"previousValue": "96000", "newValue": "3000"}

Common amendment error codes

Error CodeDescriptionHTTP Status
VALIDATION_ERROR, AMENDMENT_ERRORRequest validation failed400
NOT_FOUND, CONTRACT_NOT_FOUND, AMENDMENT_NOT_FOUNDResource not found404
AMENDMENT_CREATION_FAILED, AMENDMENT_UPDATE_FAILED, AMENDMENT_ITEM_DISABLED, AMENDMENT_ITEM_VALIDATION_FAILEDField validation failed422
FORBIDDENInsufficient permissions403
CHANGE_REQUEST_CONFIRMED, RESOURCE_CONFLICTResource conflict409
INTERNAL_ERRORServer error500

Error response examples

Request validation errors

These errors occur when the request payload fails general validation checks.

1{
2 "errors": [
3 {
4 "code": "VALIDATION_ERROR",
5 "message": "Internal validation error occurred"
6 }
7 ]
8}

General amendment errors

These errors indicate that the amendment request cannot proceed due to one or more issues.

1{
2 "errors": [
3 {
4 "message": "Amendment already in progress with ID: 5ea6c745-3f40-4fc8-864e-026ccae666e1",
5 "code": "AMENDMENT_ERROR"
6 }
7 ]
8}

Amendment field validation errors

These errors appear when specific fields are invalid or disabled for the requested amendment.

1{
2 "errors": [
3 {
4 "message": "Job title is not enabled for white label API",
5 "code": "AMENDMENT_ITEM_DISABLED",
6 "field": "jobTitle"
7 },
8 {
9 "message": "Minimum salary for United Kingdom is $30,312.07",
10 "code": "AMENDMENT_ITEM_VALIDATION_FAILED",
11 "field": "salary",
12 "details": {
13 "previousValue": "96000.0000",
14 "newValue": "3000"
15 }
16 }
17 ]
18}

Amendment processing failed errors

These errors occur when an amendment cannot be updated or confirmed.

1{
2 "errors": [
3 {
4 "code": "AMENDMENT_UPDATE_FAILED",
5 "message": "Failed to update amendment",
6 "field": "amendment"
7 }
8 ]
9}
1{
2 "errors": [
3 {
4 "code": "CHANGE_REQUEST_CONFIRMED",
5 "message": "Change request is already confirmed",
6 "field": "changeRequestId"
7 }
8 ]
9}

Amendment statuses

Amendments pass through multiple statuses from creation to completion. These statuses are returned in an array within the API response.

Check the most recent status to determine the amendment’s current state.

Amendment status structure

Amendment statuses are hierarchical and can be read at multiple levels of detail. Each status has two key properties:

  • NAME: Machine-readable identifier
  • FRIENDLY_NAME: Human-readable label

Status stages

Draft stage

Amendments that are still being prepared and can be modified.

NAMEFRIENDLY_NAMEDESCRIPTIONCLIENT ACTIONNEXT STEP
DRAFTDRAFTDraftClient can edit or submitMoves to Preparing Documents

Preparing documents stage

Statuses related to document preparation and internal review. Documents are being created, reviewed, or paused for input before signatures can begin. No action required by you in this case, fetch the amendments to get the latest status.

NAMEFRIENDLY NAMEDESCRIPTIONCLIENT ACTIONNEXT STEP
PREPARING_DOCUMENTSPREPARING_DOCUMENTSUnder review-Await Deel/legal review
PREPARING_DOCUMENTS.AMENDMENT_REQUESTEDAMENDMENT_REQUESTED
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.CUSTOM_REVIEWCUSTOM_REVIEW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.CUSTOM_REVIEW.APPROVED_CUSTOMAPPROVED_CUSTOM
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.CUSTOM_REVIEW.CUSTOM_REVIEWCUSTOM_REVIEW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.CUSTOM_REVIEW.CUSTOM_SKIPPEDCUSTOM_SKIPPED
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.CUSTOM_REVIEW.INIT_CUSTOMINIT_CUSTOM
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EAEA
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EA.DOCUMENTS_READYDOCUMENTS_READY
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EA.INIT_EAINIT_EA
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EA.PENDING_DOCUMENT_SUBMITAWAITING_REVIEW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EA.READYREADY
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.EA.SKIPPEDSKIPPED
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOWSOW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.DOCUMENTS_READYDOCUMENTS_READY
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.INIT_SOWINIT_SOW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.PENDING_DOCUMENT_SUBMITAWAITING_REVIEW
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.READYREADY
PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.SKIPPEDSKIPPED
PREPARING_DOCUMENTS.PAUSEDPAUSEDMoved to Paused for legal inputsLegal team will review it
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEWAWAITING_LEGAL_INPUT
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.DECLINEDDECLINED
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.IN_PROGRESSIN_PROGRESS
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.SOLVEDSOLVED
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.TO_DOTO_DO
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.WAITING_FOR_ANOTHER_TEAMWAITING_FOR_ANOTHER_TEAM
PREPARING_DOCUMENTS.PAUSED.LEGAL_REVIEW.WAITING_FOR_CLIENT_FEEDBACKWAITING_FOR_CLIENT_FEEDBACK
PREPARING_DOCUMENTS.PAUSED.MOBILITY_INPUTAWAITING_MOBILITY_INPUT
PREPARING_DOCUMENTS.PAUSED.PAUSED_BY_HRXPAUSED_BY_HRX
PREPARING_DOCUMENTS.PREPARING_DONEPREPARING_DONE
PREPARING_DOCUMENTS.WAITING_HRX_ACTIONWAITING_HRX_ACTIONSent to HRX to process it after legal reviewHRX will complete the amendment process and sends for signing
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.CUSTOM_REVIEWCUSTOM_REVIEW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.CUSTOM_REVIEW.APPROVED_CUSTOMAPPROVED_CUSTOM
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.CUSTOM_REVIEW.CUSTOM_REVIEWCUSTOM_REVIEW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.CUSTOM_REVIEW.CUSTOM_SKIPPEDCUSTOM_SKIPPED
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.CUSTOM_REVIEW.INIT_CUSTOMINIT_CUSTOM
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EAEA
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EA.DOCUMENTS_READYDOCUMENTS_READY
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EA.INIT_EAINIT_EA
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EA.PENDING_DOCUMENT_SUBMITAWAITING_REVIEW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EA.READYREADY
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.EA.SKIPPEDSKIPPED
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOWSOW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOW.DOCUMENTS_READYDOCUMENTS_READY
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOW.INIT_SOWINIT_SOW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOW.PENDING_DOCUMENT_SUBMITAWAITING_REVIEW
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOW.READYREADY
PREPARING_DOCUMENTS.WAITING_HRX_ACTION.SOW.SKIPPEDSKIPPED

Signature stage

These statuses indicate the amendment is awaiting or in the process of being signed.

NAMEFRIENDLY NAMEDESCRIPTIONCLIENT ACTIONNEXT STEP
AWAITING_SIGNATUREAWAITING_SIGNATUREAwaiting signature-Either Deel or Client/Employee will sign
AWAITING_SIGNATURE.EA.INITINIT--
AWAITING_SIGNATURE.EA.PENDING_COUNTERSIGNPENDING_EA_COUNTERSIGNWaiting for Deel counter sign-Deel countersigns after employee has signed
AWAITING_SIGNATURE.EA.PENDING_EMPLOYEE_SIGNATUREPENDING_EMPLOYEE_SIGNATUREWaiting for employee signEmployee must sign-
AWAITING_SIGNATURE.EA.SIGNEDSIGNED--
AWAITING_SIGNATURE.EA.SKIPPEDSKIPPED--
AWAITING_SIGNATURE.SOW.INITINIT--
AWAITING_SIGNATURE.SOW.PENDING_CLIENT_SIGNATUREAWAITING_CLIENT_ACCEPTANCEWaiting for client signClient must sign-
AWAITING_SIGNATURE.SOW.PENDING_COUNTERSIGNPENDING_SOW_COUNTERSIGNWaiting for Deel counter sign-Deel countersigns after client has signed
AWAITING_SIGNATURE.SOW.SIGNEDSIGNED--
AWAITING_SIGNATURE.SOW.SKIPPEDSKIPPED--

Active or upcoming stage

Statuses when an amendment is in effect or scheduled for the future.

NAMEFRIENDLY NAMEDESCRIPTION
ACTIVEACTIVEThe amendment has taken effect and its terms are now legally applied on the contract.
UPCOMINGUPCOMINGThe amendment has been approved and scheduled but is not yet effective.

Cancelled, rejected, or void stage

Statuses for amendments that were canceled, rejected, or voided.

NAMEFRIENDLY NAMEDESCRIPTION
CANCELLEDCANCELLEDThe amendment was cancelled, either by the client or internally, before completion.
REJECTEDREJECTEDThe amendment was reviewed and explicitly rejected by Deel.
VOIDVOIDThe amendment has been voided, making it invalid. This may happen if it is superseded or due to compliance reasons.

How to read amendment statuses

Amendment statuses are structured in a hierarchical format, where each level provides increasing detail about the amendment’s progress.

Parent phase

Represents the overall stage of the amendment, for example PREPARING_DOCUMENTS. Indicates the broad area of progress.

Sub-step

A more specific action within the parent phase, for example PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.

Detailed checkpoint

Provides the most detailed level of the amendment’s status, for example PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.PENDING_DOCUMENT_SUBMIT.

By reading an amendment status from left to right, you can move from the broad phase to the precise checkpoint, making it easy to understand exactly where the amendment stands.

Why this matters

  • Each nested level gives increasing detail about the amendment’s progress.
  • The high-level phase always represents the current overall state of the amendment.
  • Sub-steps and detailed checkpoints record the lifecycle progression. This is useful for auditing, troubleshooting, and tracking how the amendment evolved.

The parent status is the single source of truth for the amendment’s current state. The history should not be used to infer the current status.

Example status array

In this example:

  • The amendment is in the PREPARING_DOCUMENTS phase.
  • The request is logged as PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.
  • The amendment is waiting for Deel review. Further actions are required before it can proceed.
1[
2 {
3 "name": "PREPARING_DOCUMENTS",
4 "friendly_name": "PREPARING_DOCUMENTS",
5 "_amendment_flow_status": {
6 "created_at": "2025-03-19T17:15:02.053Z"
7 }
8 },
9 {
10 "name": "PREPARING_DOCUMENTS.AMENDMENT_REQUESTED",
11 "friendly_name": "AMENDMENT_REQUESTED",
12 "_amendment_flow_status": {
13 "created_at": "2025-03-19T17:15:02.053Z"
14 }
15 },
16 {
17 "name": "PREPARING_DOCUMENTS.AMENDMENT_REQUESTED.SOW.PENDING_DOCUMENT_SUBMIT",
18 "friendly_name": "AWAITING_REVIEW",
19 "_amendment_flow_status": {
20 "created_at": "2025-03-19T17:15:02.053Z"
21 }
22 }
23]

Confirm an amendment

To confirm a draft amendment, use the contract_id and amendment_id. Only draft amendments can be confirmed.

After confirmation, the flow depends on the amendment type. If the type is instant, the amendment becomes active immediately. If it requires signatures, Deel or the employee must approve it first.

$curl --location -g --request PUT '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/confirm' \
>--header 'Authorization: Bearer {{token}}'

Cancel an amendment

To cancel an amendment, use the contract_id and amendment_id. You can cancel an amendment any time before the employee signs it.

After cancellation, you can delete it if needed.

$curl --location -g --request DELETE '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'Authorization: Bearer {{token}}'

Download an amendment PDF

Retrieve the download URL for the Statement of Work (Employee Agreement, EA) of a confirmed amendment. The URL is available only after the amendment is confirmed and the contract is in progress.

The download URL expires after 15 minutes.
$curl --location -g --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/pdf' \
>--header 'Authorization: Bearer {{token}}'

Accept an amendment

Use this endpoint to accept an amendment submitted by a Deel admin.

After acceptance, the amendment either becomes active immediately or moves to the signature step, depending on its type.

$curl --location -g --request PUT '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/accept' \
>--header 'Authorization: Bearer {{token}}'

Sign an approved amendment

An employee can sign an amendment approved by both the client and admin. After signing, the amendment becomes active.

$curl --location -g --request PUT '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/sign' \
>--header 'Authorization: Bearer {{token}}'

Retrieve the list of amendments

Retrieve all amendments for a specific contract.

$curl --location -g --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments' \
>--header 'Authorization: Bearer {{token}}'

Retrieve a specific amendment

Retrieve details of a specific amendment.

$curl --location -g --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'Authorization: Bearer {{token}}'

Custom amendment items

Custom amendment items are used when you request changes that:

  • Involve data points not supported or not available in the standard amendment flow.
  • Modify general employment agreement wording for active contracts.
  • Include other ad-hoc or unique change requests not covered by standard items.

Once the amendment is confirmed, these custom items are reviewed by internal Deel teams.

Lifecycle and behavior

  • Custom amendment items are part of an amendment, just like standard amendment items, and follow the same overall amendment lifecycle: created → confirmed → reviewed
  • Custom items also have a separate internal lifecycle. They have their own statuses and can be approved or rejected independently of the overall amendment.
  • If an amendment includes both standard and custom items, and only the custom items are rejected, the amendment may still proceed with the standard changes.
  • Exception: If the amendment contains only custom items and they are rejected, the entire amendment will be rejected.

Custom amendment item types

If a specific data point is not available in the standard amendment flow, you can use one of the predefined custom item types to request the change.

TypeDescription
START_DATERequest to change the employee’s contract start date.
END_DATERequest to update the employee’s contract end date.
BENEFITSAdd or update benefits such as health insurance or allowances.
PROBATION_PERIODUpdate the probation period length or terms.
VARIABLE_COMPENSATIONSAdjust variable pay components such as bonuses or commissions.
INCENTIVE_PLANModify or add incentive plans.
SALARYRequest a change to the base salary.
FIXED_ALLOWANCESAdd or update fixed allowances, for example bonus or housing.
JOB_TITLEChange the employee’s official job title.
SENIORITY_IDUpdate job seniority level.
SENIORITY_DATEUpdate the date of previous employment before the employee transfers.
JOB_CODEUpdate the internal job code classification.
JOB_CATEGORYReclassify into a different internal job category.
JOB_SCOPEChange the scope of responsibilities in the role.
EMPLOYMENT_TYPEUpdate employment type, for example full-time or part-time.
PERSONAL_DATARequest updates to employee personal information.
OTHERFor unique or ad-hoc requests not covered by the predefined types.

Use the OTHER custom amendment type for ad-hoc or unique changes that are not covered by the predefined types.

Example: Custom items with amendment

$curl --location -g --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "time_off_type": "SPECIFIC",
> "holidays": 12,
> "employment_type": "PART_TIME",
> "custom": [
> {
> "description": "Change start date to the 1st of November 2026",
> "type": "START_DATE"
> },
> {
> "description": "Add fixed allowances to the contract with these details.",
> "type": "FIXED_ALLOWANCES"
> },
> {
> "description": "Change the contract term to Part time",
> "type": "OTHER"
> }
> ]
> }
>}'

Amendment general rules and settings

Amendments follow certain global rules and configuration options. These settings define how specific data points behave across different contract types and countries.

Probation period settings

The probation_period data point supports multiple rule types and constraints, depending on the contract type and country-specific settings.

Probation period values are returned with their applicable time unit in the additional_details.time_unit field of the validation rules response. Time units can vary by country and employment type and may be DAY, WEEK, or MONTH. Always check the time_unit field to correctly interpret the min and max values for probation period.

Rule-based configuration

Set the probation period based on a rule and cap value.

1{
2 "rule": "ONE_QUARTER_OF_CONTRACT_DURATION",
3 "cap": 100,
4 "time_unit": "DAY"
5}

Tenure-based configuration

Other configurations define probation periods based on the employee’s expected duration of employment.

1{
2 "minEmploymentDuration": 6,
3 "maxEmploymentDuration": 12,
4 "employmentDurationType": "MONTH",
5 "probationPeriod": 90
6}

Employment terms configuration

  • For INDEFINITE contracts, the probation period must be between 90 and 180 days, regardless of whether the employment type is FULL_TIME or PART_TIME.
  • For DEFINITE contracts, the minimum probation period is 20 days. The maximum value is calculated dynamically.

Dynamic calculation for definite contracts

When the contract term is DEFINITE, the API calculates the maximum probation period using contract_duration_in_days and the country-specific rule eor_country_data.max_probation_type_for_definite.

Available rule types:

HALF_OF_CONTRACT_DURATION

Maximum probation period is half the contract duration. Example: A 180-day contract allows up to 90 days.

ONE_QUARTER_OF_CONTRACT_DURATION

Maximum probation period is one-quarter of the contract duration. Example: A 180-day contract allows up to 45 days.

ONE_THIRD_OF_CONTRACT_DURATION (Default)

If no country rule is defined, the fallback is one-third of the contract duration. Example: A 180-day contract allows up to 60 days.

Cap on maximum probation period

The API may apply a cap to limit the maximum probation period, even when it uses a duration-based rule.

  • If additional_details includes a cap value, the system uses the lower value between the calculated maximum and the cap.
  • The cap applies only when the probation period is based on HALF_OF_CONTRACT_DURATION, ONE_QUARTER_OF_CONTRACT_DURATION, or ONE_THIRD_OF_CONTRACT_DURATION.

Example:

If the contract duration is 180 days and the rule is HALF_OF_CONTRACT_DURATION, the calculated maximum is 90 days. However, if a cap of 60 days exists in additional_details, the maximum probation period is limited to 60 days.

probation_period settings for DEFINITE contracts only support the rule-based configurations listed above.

Notice period settings

The notice period defines how far in advance either party must give notice to end the contract. Different rules apply depending on probation and contract configuration.

Notice period values are returned with their applicable time unit in the additional_details.time_unit field of the validation rules response. Time units can vary by country but are typically WEEK. Always check the time_unit field to correctly interpret the min and max values for notice period.

Notice period general rules

These rules apply only when notice_period_type is set to CUSTOM.

  • The min and max notice period values range from 0 to 12 weeks.
  • Rules vary for FULL_TIME and PART_TIME employees.
  • The notice period before probation must always be shorter than the notice period after probation.

Tenure-based notice period

Only notice_period_after_probation supports tenure-based rules. These rules depend on the contract duration and define different notice period values for different tenure ranges.

Example rule definition

1{
2 "data_point": "notice_period_after_probation",
3 "rules": [
4 {
5 "nullable": true,
6 "min": 0,
7 "max": 12,
8 "is_editable": true,
9 "requires": {
10 "notice_period_type": "CUSTOM",
11 "employment_type": "FULL_TIME"
12 },
13 "additional_details": {
14 "tenure_based_rules": [
15 {
16 "maxEmploymentDuration": 24,
17 "minEmploymentDuration": 12,
18 "noticeValue": 30,
19 "employmentDurationType": "MONTH"
20 },
21 {
22 "maxEmploymentDuration": 34,
23 "minEmploymentDuration": 25,
24 "noticeValue": 50,
25 "employmentDurationType": "MONTH"
26 }
27 ],
28 "time_unit": "WEEK",
29 "note": "Notice period before probation should be less than notice period after probation"
30 }
31 }
32 ]
33}

Complete workflow example

This example demonstrates the complete amendment creation and processing workflow.

1

Retrieve amendment settings

$curl --location --request GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/validation/settings' \
>--header 'accept: application/json' \
>--header 'Content-Type: application/json' \
>--header 'Authorization: Bearer {{token}}'
2

Create amendment

$curl --location POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments' \
>--header 'accept: application/json' \
>--header 'Content-Type: application/json' \
>--header 'Authorization: Bearer {{token}}' \
>--data '{
> "data": {
> }
>}'
3

Update the amendment (optional)

$curl --location PATCH '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'accept: application/json' \
>--header 'Content-Type: application/json' \
>--header 'Authorization: Bearer {{token}}' \
>--data '{
> "data": {
> "probation_period": 20
> }
>}'
4

Fetch effective date limits (optional)

$curl --location GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/effective-date-limitations' \
>--header 'Authorization: Bearer {{token}}'
5

Set the effective date (optional)

$curl --location PATCH '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'accept: application/json' \
>--header 'Content-Type: application/json' \
>--header 'Authorization: Bearer {{token}}' \
>--data '{
> "data": {
> "effective_date": "2025-09-30",
> "probation_period": 20
> }
>}'
6

Confirm the amendment

$curl --location --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/confirm' \
>--header 'accept: application/json' \
>--header 'Authorization: Bearer {{token}}'
7

Monitor amendment status

$curl --location GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'accept: application/json' \
>--header 'Authorization: Bearer {{token}}'

Or use the webhook to get the status:

1{
2 "data": {
3 "meta": {
4 "event_type": "eor.amendment.status.updated",
5 "event_type_id": "de688244-7869-46db-8ac7-00083965cc9b",
6 "organization_id": "9c09a153-1418-4127-8c44-e99483e7c321",
7 "organization_name": "20TT65OV",
8 "tracking_id": "d09a72b0002191b65de3a453d177f1a7"
9 },
10 "resource": {
11 "amendment_flow_id": "116fdec2-d8b6-4c64-82d9-089cccf92731",
12 "organization_id": "9c09a153-1418-4127-8c44-e99483e7c321",
13 "status": "EOR_AMENDMENT_V2_CLIENT_ACTIVE"
14 }
15 },
16 "timestamp": "2025-02-07T12:36:16.360Z"
17}
8

Download the EA document (optional)

$curl --location GET '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/pdf' \
>--header 'accept: application/json' \
>--header 'Authorization: Bearer {{token}}'
9

Cancel the amendment (optional)

You can cancel amendments as long as they are not active:

$curl --location --request DELETE '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}' \
>--header 'accept: application/json' \
>--header 'Authorization: Bearer {{token}}'
10

Employee signature

Once reviewed by Deel, the employee needs to sign:

$curl --location --request POST '{{host}}/rest/v2/eor/contracts/{{contract_id}}/amendments/{{amendment_id}}/sign' \
>--header 'accept: application/json' \
>--header 'Authorization: Bearer {{token}}'

If the amendment requires countersignature by Deel, it will be reviewed by the internal team.

Once signed, the amendment will either become active immediately or be scheduled to take effect on the specified effective date.

FAQ

Yes. You can include multiple data points in a single amendment request. All changes will be processed together and follow the same approval flow.

You must fetch the effective date limits again after making changes to the amendment. The valid date range may change based on the updated data points.

No. Once the employee signs the amendment, it cannot be canceled. You can only cancel amendments before they reach the signature stage.

For most use cases, the hybrid approach works best. Use client-side validation for fields with external_validation: false and server-side validation for fields with external_validation: true. This provides immediate feedback for simple fields while ensuring complete validation for complex fields.

Custom items are reviewed separately by Deel’s internal team. If only custom items are rejected, the amendment may still proceed with standard changes. However, if the amendment contains only custom items and they are rejected, the entire amendment will be rejected.

No. The effective date is optional. If you do not provide one, the system automatically sets it to when all parties confirm the amendment. However, some amendments may require an effective date based on the data points being changed.