Give bonus to contractors

Step-by-step guide to adding bonus payments to contractor invoices

Overview

This guide walks you through the complete process of paying a bonus to a contractor using the invoice adjustments API. You will learn how to create, review, and track a bonus payment from start to finish.

When to use this workflow

Use this workflow when you need to:

  • Reward contractors for exceptional performance
  • Pay project completion bonuses
  • Add end-of-year or holiday bonuses
  • Include sales or performance-based incentives
  • Compensate for work delivered ahead of schedule

Prerequisites

Before you begin, ensure you have:

  • A valid API token with invoice-adjustments:write scope
  • The contract_id of the contractor receiving the bonus
  • The bonus amount and reason for payment

Bonus payments are tied to payment cycles. Make sure the contract has an active payment cycle when creating the adjustment.

Step-by-step workflow

This example demonstrates paying a $1,500 performance bonus to a contractor who exceeded quarterly targets.

1

Identify the contract

First, retrieve the contract ID if you don’t already have it. You can list contracts and filter by worker email or external ID.

$curl --request GET 'https://api.letsdeel.com/rest/v2/contracts' \
>--header 'Authorization: Bearer {{token}}'

Response:

1{
2 "data": [
3 {
4 "id": "c3f9a1d2",
5 "title": "Senior Backend Engineer",
6 "type": "ongoing_time_based",
7 "worker_first_name": "John",
8 "worker_last_name": "Doe",
9 "status": "active",
10 "compensation_details": {
11 "amount": 8000.00,
12 "currency_code": "USD",
13 "frequency": "monthly"
14 }
15 }
16 ]
17}

Save the id field - this is your contract_id.

2

Create the bonus adjustment

Create the bonus adjustment with a clear description explaining why the bonus is being paid.

$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 1500.00,
> "contract_id": "c3f9a1d2",
> "description": "Q4 2025 performance bonus - exceeded sales targets by 140%",
> "date_submitted": "2026-01-27"
> }
>}'

Always include specific details in the description. This helps with approval tracking and provides context for the contractor and finance teams.

Response:

1{
2 "data": {
3 "id": "1a0aa359-ef15-4a47-9629-bcf36addbe41",
4 "status": "pending",
5 "created": true,
6 "created_at": "2026-01-27T10:15:00Z"
7 }
8}

The adjustment is now created with a pending status, waiting for review and approval.

3

Verify the adjustment

Check that the adjustment was created correctly by retrieving its details.

$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41' \
>--header 'Authorization: Bearer {{token}}'

Response:

1{
2 "data": {
3 "id": "1a0aa359-ef15-4a47-9629-bcf36addbe41",
4 "type": "bonus",
5 "status": "pending",
6 "contract": {
7 "id": "c3f9a1d2",
8 "type": "ongoing_time_based",
9 "title": "Senior Backend Engineer Contract"
10 },
11 "total_amount": "1500.00",
12 "currency_code": "USD",
13 "description": "Q4 2025 performance bonus - exceeded sales targets by 140%",
14 "created_at": "2026-01-27T10:15:00Z",
15 "date_submitted": "2026-01-27",
16 "reported_by": {
17 "id": "user_456789",
18 "full_name": "Sarah Johnson"
19 },
20 "payment_cycle": {
21 "start_date": "2026-01-01T00:00:00Z",
22 "end_date": "2026-01-31T23:59:59Z"
23 }
24 }
25}

The adjustment is associated with the correct contract and payment cycle.

4

Approve the bonus

Review and approve the bonus adjustment. This step moves it from pending to approved status.

$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41/reviews' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "status": "approved",
> "reason": "Performance verified by team lead. Bonus approved per Q4 incentive program."
> }
>}'

The reason field is optional but recommended. It creates an audit trail and helps explain approval decisions.

Response:

1{
2 "data": {
3 "created": true
4 }
5}
5

Confirm approval status

Retrieve the adjustment again to confirm it has been approved.

$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41' \
>--header 'Authorization: Bearer {{token}}'

Response:

1{
2 "data": {
3 "id": "1a0aa359-ef15-4a47-9629-bcf36addbe41",
4 "status": "approved",
5 "type": "bonus",
6 "total_amount": "1500.00",
7 "currency_code": "USD",
8 "description": "Q4 2025 performance bonus - exceeded sales targets by 140%",
9 "contract": {
10 "id": "c3f9a1d2",
11 "title": "Senior Backend Engineer Contract"
12 },
13 "reported_by": {
14 "id": "user_456789",
15 "full_name": "Sarah Johnson"
16 },
17 "reviewed_by": {
18 "id": "reviewer_123456",
19 "full_name": "Mike Chen",
20 "reviewed_at": "2026-01-27T15:30:00Z",
21 "remarks": "Performance verified by team lead. Bonus approved per Q4 incentive program."
22 },
23 "payment_cycle": {
24 "start_date": "2026-01-01T00:00:00Z",
25 "end_date": "2026-01-31T23:59:59Z"
26 }
27 }
28}

The bonus is now approved and will be included in the next invoice for this payment cycle.

6

Monitor payment status

The approved bonus will appear on the contractor’s next invoice. You can track when it is paid by checking the adjustment status.

$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41' \
>--header 'Authorization: Bearer {{token}}'

Once the invoice is paid, the status will change to paid:

1{
2 "data": {
3 "id": "1a0aa359-ef15-4a47-9629-bcf36addbe41",
4 "status": "paid",
5 "type": "bonus",
6 "total_amount": "1500.00",
7 "currency_code": "USD",
8 "invoice_id": "inv-987654321",
9 "payment_cycle": {
10 "start_date": "2026-01-01T00:00:00Z",
11 "end_date": "2026-01-31T23:59:59Z"
12 }
13 }
14}

The invoice_id field now contains the ID of the paid invoice that includes this bonus.

Alternative: Auto-approved bonus

For pre-authorized bonuses or recurring bonus programs, you can skip the manual approval step by using auto-approval.

Create and auto-approve in one step

$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 500.00,
> "contract_id": "c1234567-89ab-4def-0123-456789abcdef",
> "description": "Standard monthly performance bonus - contractually agreed",
> "date_submitted": "2026-01-27",
> "is_auto_approved": true
> }
>}'

Response:

1{
2 "data": {
3 "id": "1a0aa359-ef15-4a47-9629-bcf36addbe41",
4 "status": "approved",
5 "created": true,
6 "created_at": "2026-01-27T10:15:00Z"
7 }
8}

The adjustment is created with approved status immediately, bypassing the manual review workflow.

Only use auto-approval for bonuses that have already been authorized or are part of a standard program. Manual review provides an important control point for ad-hoc or large bonus payments.

Adding supporting documentation

For bonuses based on performance metrics or contract terms, attach supporting documentation.

Create bonus with performance report

$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 2000.00,
> "contract_id": "c1234567",
> "description": "Project completion bonus - delivered MVP 3 weeks ahead of schedule",
> "date_submitted": "2026-01-27",
> "attachment": {
> "key": "invoice_adjustment_attachments/2026/01/project_completion_report.pdf",
> "filename": "project_completion_report.pdf"
> }
> }
>}'

The attached document will be available to reviewers and will be linked to the adjustment for audit purposes.

Handling recurring bonuses

For bonuses that repeat every payment cycle, such as monthly sales commissions or standard performance incentives, use recurring adjustments.

Create recurring monthly bonus

$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments?recurring=true' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 750.00,
> "contract_id": "c1234567",
> "description": "Monthly sales commission - 5% of monthly sales target achievement",
> "date_submitted": "2026-01-27"
> }
>}'

This creates a recurring rule that automatically generates a new bonus adjustment for each payment cycle.

Recurring adjustments continue until you delete them. Each cycle creates a new adjustment with a unique ID that can be reviewed independently.

Stop recurring bonus

When the recurring bonus is no longer needed, delete the original adjustment to stop future occurrences.

$curl --request DELETE 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41' \
>--header 'Authorization: Bearer {{token}}'

Common scenarios

Scenario 1: Year-end bonus for all contractors

If you need to pay bonuses to multiple contractors, create separate adjustments for each contract.

$# Contractor 1
$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 1000.00,
> "contract_id": "contract-id-1",
> "description": "2025 Year-end performance bonus",
> "date_submitted": "2026-01-27"
> }
>}'
$
$# Contractor 2
$curl --request POST 'https://api.letsdeel.com/rest/v2/invoice-adjustments' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "type": "bonus",
> "amount": 1200.00,
> "contract_id": "contract-id-2",
> "description": "2025 Year-end performance bonus",
> "date_submitted": "2026-01-27"
> }
>}'

Automate this process by iterating through your contractor list and creating adjustments programmatically. Use batch processing to handle large numbers of contractors efficiently.

Scenario 2: Tiered performance bonus

For bonuses based on performance tiers, calculate the amount before creating the adjustment.

1// Example: Calculate tiered bonus
2const performanceScore = 142; // 142% of target
3let bonusAmount = 0;
4
5if (performanceScore >= 150) {
6 bonusAmount = 2000;
7} else if (performanceScore >= 125) {
8 bonusAmount = 1500;
9} else if (performanceScore >= 100) {
10 bonusAmount = 1000;
11}
12
13// Create adjustment with calculated amount
14const adjustment = {
15 type: "bonus",
16 amount: bonusAmount,
17 contract_id: "c1234567",
18 description: `Q4 performance bonus - achieved ${performanceScore}% of target`,
19 date_submitted: "2026-01-27"
20};

Scenario 3: Correcting a bonus amount

If you need to correct a bonus amount before it is paid, update the pending adjustment.

$curl --request PATCH 'https://api.letsdeel.com/rest/v2/invoice-adjustments/1a0aa359-ef15-4a47-9629-bcf36addbe41' \
>--header 'Authorization: Bearer {{token}}' \
>--header 'Content-Type: application/json' \
>--data-raw '{
> "data": {
> "amount": 1750.00,
> "description": "Q4 2025 performance bonus - exceeded sales targets by 140% (corrected amount)"
> }
>}'

You can only update adjustments in pending status. Once approved or paid, adjustments cannot be modified. If you need to correct an approved adjustment, create a new adjustment with the difference amount.

Tracking bonus payments

List all bonuses for a contractor

Retrieve all bonus adjustments for a specific contract to track historical payments.

$curl --request GET 'https://api.letsdeel.com/rest/v2/contracts/c1234567-89ab-4def-0123-456789abcdef/invoice-adjustments?types=bonus' \
>--header 'Authorization: Bearer {{token}}'

List bonuses by status

Filter bonuses by status to see what is pending approval or already paid.

$# Pending bonuses
$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments?types=bonus&statuses=pending' \
>--header 'Authorization: Bearer {{token}}'
$
$# Approved bonuses waiting for payment
$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments?types=bonus&statuses=approved' \
>--header 'Authorization: Bearer {{token}}'
$
$# Paid bonuses
$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments?types=bonus&statuses=paid' \
>--header 'Authorization: Bearer {{token}}'

List bonuses by date range

Track bonuses paid within a specific time period for reporting purposes.

$curl --request GET 'https://api.letsdeel.com/rest/v2/invoice-adjustments?types=bonus&start_date=2026-01-01&end_date=2026-01-31' \
>--header 'Authorization: Bearer {{token}}'

Best practices

Clear descriptions

Always include:

  • The reason for the bonus (performance, completion, sales, etc.)
  • The time period or achievement being rewarded
  • Any relevant metrics or benchmarks met

Good examples:

  • “Q4 2025 performance bonus - exceeded sales targets by 140%”
  • “Project completion bonus - delivered MVP 3 weeks ahead of schedule”
  • “Annual loyalty bonus - 2 years of exceptional service”

Bad examples:

  • “Bonus”
  • “Extra payment”
  • “Additional compensation”

Timing considerations

  • Create bonuses early in the payment cycle to ensure they appear on the current invoice
  • Late submissions may roll over to the next payment cycle
  • Check payment cycle dates before creating adjustments

Documentation

  • Attach performance reports, project completion documents, or contract references
  • Keep records of approval decisions for compliance and audit purposes
  • Document the bonus calculation methodology for recurring programs

Approval workflow

  • Use manual approval for one-time or large bonuses
  • Use auto-approval only for pre-authorized standard bonuses
  • Assign appropriate reviewers with authority to approve bonus payments
  • Include clear approval reasons for audit trails

Troubleshooting

Check that the bonus is approved and that the payment cycle includes the submission date. If the invoice has already been generated, the bonus will appear on the next invoice.

Bonuses can only be updated while in pending status. If already approved, you must create a new adjustment for the difference amount or decline the original and create a new one.

Each recurring cycle creates a new adjustment. If you see duplicates, check if multiple recurring rules were created. Delete extra rules to stop duplicate generation.

Bonuses use the contract currency and cannot be changed. If you need to pay in a different currency, use off-cycle payments instead of invoice adjustments.

Notifications are sent when the invoice is generated, not when the adjustment is created. Check the invoice generation date and ensure the adjustment was approved before that date.

Next steps