What you’ll use
Models - candidate, application, job interview stageBefore you start
- The connector is an ATS connector. A connector token works for one API category, so an HRIS token on
/api/ats/v1/*returns403- see Authentication.
Steps
1
Read candidates
ids, remote_id, email_addresses, first_name, last_name, company and tag. A candidate exists once no matter how many roles they go for, and email_addresses, phone_numbers, locations, urls and tags are all lists.Result: People, with duplicates already removed by the ATS.2
Read applications
Result: One record per candidate-job pair.
3
Count the right model for the question
A candidate who applies to three roles is one candidate and three applications. Count applications to report pipeline headcount, and you’ll overcount by however many people applied more than once - which, if a company is hiring across several similar roles, can be a lot.Result: Numbers that actually mean what you think they mean.
4
Expand rather than fetching in a loop
expand returns related records inline. List them with commas, no spaces.5
Read the stages for a job
name, job and stage_order. Filter by job - read them without one and you get every stage of every job, which isn’t a pipeline.Result: One job’s process, in order.6
Order by stage_order, never by name
7
Resolve each application's position
current_stage skips a lookup per application. Join it against the ordered list from the last step to get a position instead of just a label.Result: Where each application sits, in a way you can compare.8
Treat rejection as separate from stage
An application that’s ended carries Count applications by stage without excluding rejected ones, and every stage looks more full than it really is.Result: Active pipeline kept separate from closed applications.
rejected_at and a reject_reason, and its current_stage shows wherever it stopped - not a “rejected” stage.9
Detect movement rather than polling for it
Subscribe to
connector_data_modified and re-read the applications that changed - see Choose Webhook Events.Change events carry IDs, not records - they tell you something changed, not what. To know an application moved, compare current_stage against your last stored copy.Result: Real stage transitions, not just “something changed.”Frequently Asked Questions
Every request returns 403
Every request returns 403
A connector token only works for one API category. An HRIS connector called on
/api/ats/v1/* returns 403 even with valid credentials.The same person appears more than once
The same person appears more than once
Some ATS platforms create a second candidate record instead of a second application when someone applies again, especially after a long gap or through a different source. Match on
email_addresses to catch it - see Record identity.Stages from different jobs are mixed together
Stages from different jobs are mixed together
job-interview-stages was read without the job filter. Stages belong to one job each, so an unfiltered read is every process at once.Stage counts are higher than the number of live candidates
Stage counts are higher than the number of live candidates
Rejected applications are being counted.
current_stage shows where an application stopped, not whether it’s still moving - filter on rejected_at.Related
- Recruiting - the models and how they link
- Record identity - detecting duplicate candidates
- Pagination - walking a large pipeline