Adjustments

Adjustments allow you to add or subtract amounts from a worker’s payroll outside of their regular compensation. Use adjustments to handle bonuses, deductions, allowances, reimbursements, or any one-time payment that affects net pay.

The Adjustments API provides endpoints to create, retrieve, and manage adjustments programmatically. Each adjustment is linked to a specific contract and payroll cycle, ensuring accurate processing and compliance with local tax rules.

Key concepts

Adjustment types

Adjustments are categorized by purpose. Each category determines how the adjustment is processed and reported.

Common adjustment categories include:

  • Bonuses: Performance bonuses, sign-on bonuses, or retention payments
  • Deductions: Loan repayments, garnishments, or advance deductions
  • Allowances: Housing allowances, transportation stipends, or meal allowances
  • Reimbursements: Expense reimbursements for business-related costs

Use the GET /adjustments/categories endpoint to retrieve all available categories for your organization.

Adjustment status

Adjustments move through different statuses depending on the contract type and approval workflow.

Global Payroll (GP) statuses:

  • OPEN: Adjustment created but not yet submitted
  • PENDING_APPROVAL: Submitted and awaiting approval
  • SUCCESS: Approved and processed in payroll
  • FAILED: Processing failed due to validation errors
  • OVERWRITTEN: Replaced by a newer adjustment
  • AI_CHECK_IN_PROGRESS: Under automated review

Employer of Record (EOR) statuses:

  • DRAFT: Adjustment created but not finalized
  • PENDING: Submitted for processing
  • APPROVED: Approved and ready for disbursement
  • DENIED: Rejected by approver
  • DISBURSE_SCHEDULED: Scheduled for payment
  • REIMBURSED: Payment completed
  • UNDER_REVIEW: Manual review in progress
  • ERRORS_FOUND: Validation errors detected
  • PENDING_DEEL_REVIEW: Awaiting internal Deel review

Payroll cycles

Adjustments are tied to specific payroll cycles. Each adjustment has:

  • date_of_adjustment: The date the adjustment should apply
  • cycle_reference: The payroll cycle identifier
  • actual_start_cycle_date: Start date of the payroll cycle
  • actual_end_cycle_date: End date of the payroll cycle

If move_next_cycle is set to true, the adjustment can be moved to the next payroll cycle if it misses the current cutoff.

Creating an adjustment

Use the POST /adjustments endpoint to create a new adjustment.

Required fields

FieldTypeDescription
contract_idstringThe identifier of the contract this adjustment applies to
titlestringA descriptive title for the adjustment
amountstringThe adjustment amount (positive for additions, negative for deductions)
adjustment_category_idstringThe category ID from /adjustments/categories
date_of_adjustmentstringThe date the adjustment should apply (ISO 8601 date format)

Optional fields

FieldTypeDescription
descriptionstringAdditional context or notes about the adjustment
fileobjectAttachment supporting the adjustment (e.g., receipt, approval document)
cycle_referencestringSpecific payroll cycle identifier
move_next_cyclebooleanAllow moving to next cycle if current cycle is closed

Example request

1import requests
2import os
3
4url = "https://api.letsdeel.com/rest/v2/adjustments"
5
6headers = {
7 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
8 "Content-Type": "application/json"
9}
10
11payload = {
12 "contract_id": "m3jk2j",
13 "title": "Q4 Performance Bonus",
14 "amount": "2500.00",
15 "adjustment_category_id": "c9cf4c2c0165f48f494415390c3b49",
16 "date_of_adjustment": "2024-12-31",
17 "description": "Year-end performance bonus",
18 "move_next_cycle": False
19}
20
21response = requests.post(url, json=payload, headers=headers)
22print(response.json())

Response structure

A successful request returns a 201 Created status with the adjustment details:

1{
2 "data": {
3 "id": "123e4567-e89b-12d3-a456-426614174000",
4 "contract_id": "m3jk2j",
5 "title": "Q4 Performance Bonus",
6 "amount": "2500.00",
7 "status": "OPEN",
8 "adjustment_category_id": "c9cf4c2c0165f48f494415390c3b49",
9 "date_of_adjustment": "2024-12-31",
10 "description": "Year-end performance bonus",
11 "move_next_cycle": false,
12 "cycle_reference": "2024-12",
13 "actual_start_cycle_date": "2024-12-01T00:00:00.000Z",
14 "actual_end_cycle_date": "2024-12-31T23:59:59.000Z",
15 "file": null,
16 "created_at": "2024-12-15T10:30:00.000Z",
17 "updated_at": "2024-12-15T10:30:00.000Z"
18 }
19}

Retrieving adjustments

Retrieve a specific adjustment

Use GET /adjustments/{id} to fetch details of a single adjustment.

1import requests
2import os
3
4adjustment_id = "123e4567-e89b-12d3-a456-426614174000"
5url = f"https://api.letsdeel.com/rest/v2/adjustments/{adjustment_id}"
6
7headers = {
8 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}"
9}
10
11response = requests.get(url, headers=headers)
12print(response.json())

List adjustments by contract

Use GET /contracts/{contract_id}/adjustments to retrieve all adjustments for a specific contract.

This endpoint returns all adjustments associated with a contract, allowing you to track the complete history of bonuses, deductions, and other modifications.

1import requests
2import os
3
4contract_id = "m3jk2j"
5url = f"https://api.letsdeel.com/rest/v2/contracts/{contract_id}/adjustments"
6
7headers = {
8 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}"
9}
10
11response = requests.get(url, headers=headers)
12adjustments = response.json()
13
14for adjustment in adjustments['data']:
15 print(f"{adjustment['title']}: {adjustment['amount']} ({adjustment['status']})")

Retrieving adjustment categories

Before creating an adjustment, retrieve the available categories for your organization using GET /adjustments/categories.

Each category has a unique identifier, name, and unit type that determines how the adjustment is processed.

1import requests
2import os
3
4url = "https://api.letsdeel.com/rest/v2/adjustments/categories"
5
6headers = {
7 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}"
8}
9
10response = requests.get(url, headers=headers)
11categories = response.json()
12
13for category in categories['data']:
14 print(f"{category['name']} (ID: {category['id']}, Type: {category['unit_type']})")

Response structure

1{
2 "data": [
3 {
4 "id": "c0431543f64c448e5ba4b525a50291",
5 "name": "Performance Bonus",
6 "label": "Performance Bonus",
7 "unit_type": "currency"
8 },
9 {
10 "id": "d1542654g75d559f6cb5c636b61402",
11 "name": "Loan Repayment",
12 "label": "Loan Repayment",
13 "unit_type": "currency"
14 }
15 ]
16}

Error handling

The API returns standard HTTP status codes and error messages to help you diagnose issues.

Common errors

Status CodeErrorCauseSolution
400Bad RequestMissing required fields or invalid data formatVerify all required fields are present and correctly formatted
401UnauthorizedInvalid or missing API tokenCheck that your API token is valid and included in the Authorization header
403ForbiddenInsufficient permissionsEnsure your token has the adjustments:write scope
404Not FoundAdjustment or contract ID does not existVerify the ID is correct and the resource exists
500Internal Server ErrorServer-side issueRetry the request or contact Deel support if the issue persists

Example error response

1{
2 "errors": [
3 {
4 "message": "contract_id is required"
5 }
6 ]
7}

Always validate adjustment amounts before submission. Negative amounts represent deductions and must be prefixed with a minus sign (e.g., “-150.00”).

Authentication and scopes

All adjustment endpoints require authentication using either an API token or OAuth2.

Required scopes:

  • adjustments:read - Read adjustment data
  • adjustments:write - Create and modify adjustments

For detailed information on authentication methods and token management, see the Authentication guide.

Best practices

  • Submit adjustments early: Create adjustments well before the payroll cutoff to ensure processing
  • Monitor cycle dates: Check actual_start_cycle_date and actual_end_cycle_date to confirm timing
  • Use move_next_cycle carefully: Only enable this if the adjustment can be delayed to the next cycle
  • Validate cycle references: Ensure the cycle_reference matches an active payroll cycle
  • Use string format: Always pass amounts as strings (e.g., “1234.56”) to preserve precision
  • Include decimals: Specify two decimal places for currency values
  • Negative for deductions: Use negative amounts (e.g., “-500.00”) for deductions
  • Validate before submission: Check that amounts match your payroll records
  • Retrieve categories first: Always call /adjustments/categories before creating adjustments
  • Use correct category IDs: Map your internal adjustment types to Deel’s categories
  • Check unit_type: Ensure the category matches the adjustment purpose (currency vs. other units)
  • Cache category data: Store category mappings to reduce API calls
  • Include supporting documents: Attach receipts, approvals, or invoices when applicable
  • Use descriptive titles: Make adjustment titles clear and searchable
  • Add context in descriptions: Provide additional details that explain the adjustment
  • Track adjustment IDs: Store adjustment IDs in your system for reconciliation
  • Handle validation errors: Check for 400 status codes and display helpful messages
  • Implement retry logic: Retry failed requests with exponential backoff
  • Log adjustment attempts: Keep audit trails of all adjustment creation attempts
  • Monitor status changes: Poll adjustment status if approval workflows are involved

Common use cases

Scenario 1: Monthly performance bonuses

Submit performance bonuses at the end of each month for eligible employees.

1import requests
2import os
3
4def create_performance_bonus(contract_id, amount, month):
5 url = "https://api.letsdeel.com/rest/v2/adjustments"
6
7 headers = {
8 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
9 "Content-Type": "application/json"
10 }
11
12 payload = {
13 "contract_id": contract_id,
14 "title": f"Performance Bonus - {month}",
15 "amount": str(amount),
16 "adjustment_category_id": "c0431543f64c448e5ba4b525a50291",
17 "date_of_adjustment": f"2024-{month}-31",
18 "description": f"Monthly performance bonus for {month}/2024"
19 }
20
21 response = requests.post(url, json=payload, headers=headers)
22
23 if response.status_code == 201:
24 return response.json()
25 else:
26 raise Exception(f"Failed to create bonus: {response.json()}")
27
28# Create bonus for December
29bonus = create_performance_bonus("m3jk2j", 1500.00, "12")
30print(f"Bonus created: {bonus['data']['id']}")

Scenario 2: Expense reimbursements

Reimburse employees for business expenses like travel, meals, or equipment.

1import requests
2import os
3
4def create_expense_reimbursement(contract_id, amount, description, receipt_file=None):
5 url = "https://api.letsdeel.com/rest/v2/adjustments"
6
7 headers = {
8 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
9 "Content-Type": "application/json"
10 }
11
12 payload = {
13 "contract_id": contract_id,
14 "title": "Expense Reimbursement",
15 "amount": str(amount),
16 "adjustment_category_id": "d1542654g75d559f6cb5c636b61402",
17 "date_of_adjustment": "2024-12-20",
18 "description": description
19 }
20
21 # Attach receipt if provided
22 if receipt_file:
23 payload["file"] = receipt_file
24
25 response = requests.post(url, json=payload, headers=headers)
26 return response.json()
27
28# Reimburse travel expenses
29reimbursement = create_expense_reimbursement(
30 contract_id="m3jk2j",
31 amount=345.67,
32 description="Client meeting travel - December 2024"
33)
34print(f"Reimbursement created: {reimbursement['data']['id']}")

Scenario 3: Loan deductions

Process recurring loan deductions from employee paychecks.

1import requests
2import os
3
4def create_loan_deduction(contract_id, amount, loan_reference):
5 url = "https://api.letsdeel.com/rest/v2/adjustments"
6
7 headers = {
8 "Authorization": f"Bearer {os.getenv('DEEL_API_TOKEN')}",
9 "Content-Type": "application/json"
10 }
11
12 payload = {
13 "contract_id": contract_id,
14 "title": f"Loan Repayment - {loan_reference}",
15 "amount": f"-{amount}", # Negative for deduction
16 "adjustment_category_id": "e2653765h86e660g7dc6d747c72513",
17 "date_of_adjustment": "2024-12-31",
18 "description": f"Monthly loan repayment for {loan_reference}",
19 "move_next_cycle": False
20 }
21
22 response = requests.post(url, json=payload, headers=headers)
23 return response.json()
24
25# Deduct monthly loan payment
26deduction = create_loan_deduction(
27 contract_id="m3jk2j",
28 amount=250.00,
29 loan_reference="LOAN-2024-001"
30)
31print(f"Deduction created: {deduction['data']['id']}")

Next steps