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

# Manage candidates and applications

## Overview

This guide walks through the complete application workflow in Deel's ATS API: creating a candidate record, submitting an application to a specific job, and advancing the application through interview plan stages until a hiring decision is reached. Each step depends on the previous one. You must have a candidate before you can create an application, and an application before you can advance stages.

## When to use this workflow

Use this workflow when you need to:

* Push candidates from an external sourcing tool into Deel's ATS
* Automate application creation as part of a recruitment integration
* Advance pipeline stages programmatically in response to hiring decisions
* Sync application status from Deel into an external HR system

## Prerequisites

Before starting, ensure you have:

* A valid API token with `ats:read` and `ats:write` scopes
* An existing job ID and its corresponding `job_employment_type_id`. See [Manage jobs](/api/ats-guides/manage-jobs).
* Your `hris_organization_user_id`, required for advancing pipeline stages. See [Getting started](/api/ats-guides/getting-started).

> **Note**
>
> If you do not have an interview plan attached to your job, you can still create candidates and applications. You cannot call the stage advancement endpoint until you configure an interview plan in the Deel application.

## Step-by-step workflow

The following example follows a single hire: Jane Doe, a Senior Software Engineer candidate applying to job `job_01hxyzpqrstu`.

### Create a candidate

A candidate record stores the person's contact information. Create a candidate before creating any application for them.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/candidates' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane.doe@example.com",
      "phone_number": "+1 555 000 1234",
      "linkedin_profile_url": "https://linkedin.com/in/jane-doe"
    }
  }'
```

#### Response

```json
{
  "data": {
    "id": "cand_01hxyzabcdef",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane.doe@example.com",
    "phone_number": "+1 555 000 1234",
    "applications": [],
    "candidate_tags": [],
    "total_applications_count": 0,
    "created_at": "2026-05-04T10:00:00Z",
    "updated_at": "2026-05-04T10:00:00Z"
  }
}
```

Store the `candidate.id`. You need it in the next step.

> **Tip**
>
> A candidate's email address must be unique within your organization. If a candidate with the same email already exists, the request will fail. Check for existing candidates using `GET /ats/candidates?search=jane.doe@example.com` before creating a new record.

### Create an application

An application links a candidate to a specific job and employment type. You need the `job_id`, the `job_employment_type_id` (the join record ID from [`GET /ats/jobs`](/api/ats-endpoints/ats-jobs/retrieve-a-list-of-ats-jobs)), and the `candidate_id`.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/applications' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "candidate_id": "cand_01hxyzabcdef",
      "job_id": "job_01hxyzpqrstu",
      "job_employment_type_id": "jet_01hxyz333bcd",
      "notes": [
        {
          "richtext_content": "<p>Referred by the engineering team. Strong background in distributed systems.</p>"
        }
      ]
    }
  }'
```

#### Response

```json
{
  "data": {
    "id": "app_01hxyzghijkl",
    "candidate": {
      "id": "cand_01hxyzabcdef",
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane.doe@example.com"
    },
    "job": {
      "id": "job_01hxyzpqrstu",
      "title": "Senior Software Engineer"
    },
    "job_employment_type": {
      "id": "jet_01hxyz333bcd",
      "employment_type": {
        "id": "et_01hxyz789ghi",
        "name": "Full-time"
      }
    },
    "current_application_interview_plan_stage": null,
    "created_at": "2026-05-04T10:05:00Z",
    "updated_at": "2026-05-04T10:05:00Z"
  }
}
```

Store the `application.id`. You need it to advance stages and add notes.

> **Warning**
>
> The `job_employment_type_id` is the ID of the join record between the job and the employment type (e.g. `jet_01hxyz333bcd`), not the employment type ID itself (e.g. `et_01hxyz789ghi`). Retrieve it from [`GET /ats/jobs`](/api/ats-endpoints/ats-jobs/retrieve-a-list-of-ats-jobs) under `job_employment_types[].id`.

### Advance the application through an interview plan stage

Move the candidate's application to the first active stage of the interview plan. You need the `interview_plan_stage_id` from the job's `interview_plan_stages` array, and your own `hris_organization_user_id` as the `creator_id`.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/applications/app_01hxyzghijkl/interview-plan-stages' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "interview_plan_stage_id": "ips_01hxyzmnopqr",
      "creator_id": "hrou_01hxyz222pqr",
      "is_current_stage": true
    }
  }'
```

#### Response

```json
{
  "data": {
    "id": "apps_01hxyzstuvwx",
    "application_id": "app_01hxyzghijkl",
    "interview_plan_stage": {
      "id": "ips_01hxyzmnopqr",
      "name": "Technical interview",
      "default_type_slug": "technical_interview",
      "category_type_slug": "ACTIVE"
    },
    "status": "ACTIVE",
    "created_at": "2026-05-04T10:10:00Z"
  }
}
```

Repeat this step for each subsequent stage. Set `is_current_stage: true` on the stage you want to mark as the current active stage.

> **Tip**
>
> To trigger scheduled activities (such as sending a candidate self-scheduling email), include the `applicable_job_activities` array with the activity IDs and any custom participant assignments.

### Add a note to an application

Use notes to record decisions, feedback, or context during the hiring process.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/applications/app_01hxyzghijkl/notes' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "richtext_content": "<p>Technical interview completed. Strong systems design skills. Recommend advancing to final round.</p>"
    }
  }'
```

### Tag a candidate

Tags help categorize candidates across jobs. Create a tag on a candidate for filtering and reporting.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/candidates/cand_01hxyzabcdef/tags' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "tag_ids": ["tag_01hxyz999zzz"]
    }
  }'
```

Retrieve available tag IDs with [`GET /ats/tags`](/api/ats-endpoints/ats-tags/list-tags-v-2026-02-27).

### Retrieve application status

Check the full application record at any point to see the current stage, all stage history, and offer details.

#### Request

```bash
curl --request GET 'https://api.letsdeel.com/rest/ats/applications/app_01hxyzghijkl' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE'
```

The response includes `current_application_interview_plan_stage`, the full `all_application_interview_plan_stages` history, and any associated `offers`. When an application reaches a `COMPLETED` stage with an accepted offer, it is ready for contract creation. See [From candidate to contract](/api/ats-common-use-cases/from-candidate-to-contract).

## Common scenarios

### Sourcing a candidate externally

When a candidate applies via an external job board and you want to push the record into Deel:

1. Create the candidate with [`POST /ats/candidates`](/api/ats-endpoints/ats-candidates/create-ats-candidate-v-2026-01-01)
2. Create the application with `source_slug: "EXTERNAL_CAREER_PAGE"` in the request if the field is available, or with the relevant `job_posting_id`
3. Advance the stage immediately to `LEAD` category to start the screening process

### Multiple applications per candidate

A candidate can apply to more than one job. Each application is independent. Create separate application records using the same `candidate_id` and different `job_id` values. The candidate's `total_applications_count` increments with each new application.

### Archiving an application

To archive an application (candidate not progressing), advance it to a `COMPLETED` category stage and provide a `candidate_archivation_reason_id`. Retrieve available reasons with [`GET /ats/reasons`](/api/ats-endpoints/ats-reasons/retrieve-paginated-list-of-ats-rejection-archivation-reasons-v-2026-01-01). Optionally provide a `candidate_archivation_email_template_id` to send a rejection notification.

#### Request

```bash
curl --request POST 'https://api.letsdeel.com/rest/ats/applications/app_01hxyzghijkl/interview-plan-stages' \
  --header 'Authorization: Bearer YOUR-TOKEN-HERE' \
  --header 'Content-Type: application/json' \
  --data '{
    "data": {
      "interview_plan_stage_id": "ips_01hxyz_rejected",
      "creator_id": "hrou_01hxyz222pqr",
      "is_current_stage": true,
      "candidate_archivation_reason_id": "reason_01hxyz_overqualified"
    }
  }'
```

## Troubleshooting

#### 422 error on application creation: job_employment_type_id not found

You are using the `employment_type.id` instead of the `job_employment_type_id`. The `job_employment_type_id` is the ID of the join record (`jet_...`) returned under `job_employment_types[].id` in [`GET /ats/jobs`](/api/ats-endpoints/ats-jobs/retrieve-a-list-of-ats-jobs). These are different values.

#### Candidate creation fails with duplicate email error

Each candidate email must be unique within your organization. Use `GET /ats/candidates?search=email@example.com` to check if the candidate already exists. If they do, retrieve their `id` and create a new application directly without creating a new candidate record.

#### Stage advancement fails with invalid creator_id

The `creator_id` must be the `hris_organization_user_id` of a hiring member in your organization, not the candidate ID or application ID. Retrieve your hiring members with [`GET /ats/hiring-members`](/api/ats-endpoints/ats-hiring-members/retrieve-ats-hiring-members) and use the `hris_organization_user_id` field.

#### Application has no interview plan stages to advance to

The job must have an interview plan attached (`interview_plan_id`) before you can advance applications. Attach an interview plan in the Deel application under the job settings. You can also retrieve available stage IDs from [`GET /ats/jobs`](/api/ats-endpoints/ats-jobs/retrieve-a-list-of-ats-jobs) under `interview_plan_stages`.

#### GET /ats/candidates returns unexpected results when filtering by stage

The `current_stage_category_type_slugs` and `current_stage_default_type_slugs` filters apply to the candidate's most recent application stage across all their applications, not to a specific job. Use [`GET /ats/applications`](/api/ats-endpoints/ats-applications/retrieve-a-list-of-ats-applications-v-2026-01-01) filtered by `job_id` for job-specific stage filtering.

## Next steps

#### [From candidate to contract](/api/ats-common-use-cases/from-candidate-to-contract)

Connect an accepted offer to a Deel EOR or IC contract.

#### [Manage jobs](/api/ats-guides/manage-jobs)

Review job creation and the employment type join record IDs.

#### [Webhooks](/api/webhooks/introduction)

Set up webhooks to receive notifications on application events.

#### [Authentication](/api/authentication)

Learn how to generate and manage API tokens.