Manage candidates and applications
End-to-end guide to creating candidates, submitting applications, and advancing through the interview pipeline
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:readandats:writescopes - An existing job ID and its corresponding
job_employment_type_id. See Manage jobs. - Your
hris_organization_user_id, required for advancing pipeline stages. See Getting started.
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.
Store the candidate.id. You need it in the next step.
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), and the candidate_id.
Store the application.id. You need it to advance stages and add notes.
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 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.
Repeat this step for each subsequent stage. Set is_current_stage: true on the stage you want to mark as the current active stage.
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.
Tag a candidate
Tags help categorize candidates across jobs. Create a tag on a candidate for filtering and reporting.
Retrieve available tag IDs with GET /ats/tags.
Retrieve application status
Check the full application record at any point to see the current stage, all stage history, and offer details.
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.
Common scenarios
Sourcing a candidate externally
When a candidate applies via an external job board and you want to push the record into Deel:
- Create the candidate with
POST /ats/candidates - Create the application with
source_slug: "EXTERNAL_CAREER_PAGE"in the request if the field is available, or with the relevantjob_posting_id - Advance the stage immediately to
LEADcategory 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. Optionally provide a candidate_archivation_email_template_id to send a rejection notification.
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. 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 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 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 filtered by job_id for job-specific stage filtering.