Integration · People operations
How to build an ATS to HRIS sync
An offer is signed on Thursday and somebody rekeys it into the HRIS on Monday, so provisioning starts three days late. This is the design behind a clean handover, the prompts that build it, and what production adds.
Built with Tray Headless
- System Greenhouse
- Step Signed offer
- Step Map to worker
- Step Create record
- System Workday
Signature is the trigger and the worker record is created immediately, so onboarding has a start date to schedule against days earlier.
The short answer
What is an ATS to HRIS sync?
An ATS to HRIS sync has four moving parts: the signed offer as the trigger rather than a manual handover, a field mapping that fails loudly on anything unmapped, a boundary that leaves recruitment data behind, and onboarding triggered from the start date once the record exists. The part teams get wrong is carrying everything across. Interview feedback and rejection reasons belong to recruitment, and copying them into the HR record makes them visible to managers who should never see them.
What matters here
- Trigger on the signed offer. Every day between signature and the worker record is a day onboarding cannot start.
- Leave recruitment data behind. Interview scores and rejection reasons should never reach the HR record.
- Fail loudly on an unmapped field. A silently dropped start date is discovered on somebody first day.
- Create the worker record before the start date, not on it. Provisioning needs lead time.
- Reconcile hires against worker records weekly. A signed offer with no record is somebody arriving to nothing.
Who this is for
You run people operations or HR systems. Offers are signed in the ATS and typed into the HRIS by hand, and every delay pushes provisioning later.
How it works in practice
What has to happen between an offer being signed and somebody being ready to start.
- 1
The signed offer fires the sync
Not a weekly handover meeting, because every day of delay is a day onboarding cannot begin.
- 2
Fields map explicitly, and unmapped fails
A dropped start date discovered on day one is the failure this prevents.
- 3
Recruitment data stays in the ATS
Feedback, scorecards and rejection reasons are not HR record material.
- 4
The worker record is created with a future start date
So provisioning has lead time instead of starting on the morning.
- 5
Onboarding provisioning triggers from that record
One trigger, no second handover.
- 6
Hires and records are reconciled weekly
Because a signed offer with no worker record is somebody arriving to nothing.
What the sync is made of
Four, and the third is a privacy boundary instead of a technical choice.
Signature as the trigger
The signed offer, immediately. A handover meeting adds days at exactly the point where lead time is most valuable.
A strict field mapping
Every field mapped explicitly, unmapped fields failing loudly instead of being dropped silently.
A data boundary
Recruitment data stays in the ATS. Interview feedback in an HR record is visible to people who should never see it.
Onboarding from the record
The worker record with a future start date is what provisioning schedules against, so it must exist early.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Start here: decide what must not cross
The boundary matters more than the mapping.
Headless skills
build-workflowUse build-workflow. The systems in play are Greenhouse and Workday, or whatever we run in those seats. I need the candidate and offer objects with every field, and the worker record with its mandatory fields and picklist values. Then decide what must not cross. My starting position: interview scorecards, interviewer feedback, rejection reasons, salary negotiation history, and any demographic data collected for diversity monitoring. Those belong to recruitment. Copying them into an HR record makes them visible to managers and HR business partners who should never see them, and once they are there nobody removes them.
- 2
Trigger on signature, map explicitly
A silently dropped start date is discovered on somebody first day.
Headless skills
build-workflowUse build-workflow. Trigger on the offer reaching signed, not on a stage change or a weekly export. Map every field explicitly: legal name, preferred name, personal email for pre-start contact, start date, job profile, level, department, cost centre, manager, location, employment type, and compensation. Fail loudly on anything unmapped or invalid. Do not create a partial worker record and do not silently drop a field. A dropped start date produces somebody arriving with no provisioning. A dropped cost centre produces a payroll problem in the first cycle. Both are discovered by the new joiner rather than by us, which is the worst way to find out.
Picklist mismatches are the most common failure. The ATS job title is free text and the HRIS job profile is a controlled list, and they will not agree.
- 3
Create the record early, with a future start date
Provisioning needs lead time it currently does not get.
Create the worker record as soon as the offer is signed, with a future start date, rather than on the day they start. That record is what onboarding provisioning schedules against: hardware ordered, identity created and disabled, access sequenced against day one. Every day earlier it exists is a day of lead time provisioning gets. Handle the pre-start period explicitly: the person is not an employee yet, they should not appear in the directory, and they should not receive company communications until their start date. Where the HRIS cannot hold a pre-start worker, use the ATS record as the provisioning trigger and reconcile once the worker record exists.
- 4
Handle the changes that happen before day one
Offers change more often than anybody plans for.
Headless skills
tray-gotchasUse tray-gotchas, then handle these: Start date moves, which is common. Update the record and replan every scheduled provisioning step instead of firing the missed ones. Offer withdrawn or declined after acceptance. Remove the worker record, reverse anything provisioned, and confirm the reversal. Compensation renegotiated after signing. Update, and flag for payroll if it crosses a threshold. A rehire, where a worker record already exists. Never create a duplicate, and never silently reactivate the old record with its historical access. A contractor converting to employee, which is a change instead of a new hire and needs their tenure preserved.
- 5
Reconcile weekly
A signed offer with no worker record is somebody arriving to nothing.
Reconcile weekly between the ATS and the HRIS: Signed offers with no worker record. This should be zero and it is the one that produces a person arriving to nothing. Worker records with no corresponding hire, which is usually a manual creation bypassing the process Start dates that disagree between systems Anybody starting in the next fortnight whose provisioning has not begun Report: time from signature to worker record, time from signature to provisioning complete, sync failures by field, and first-day incidents traced back to a sync failure. That last number is the one that matters to the new joiner, and it is the only one anybody outside the team ever hears about.
- 6
Prove it works, then hand the mapping over
Because job profiles and levels change constantly.
Run the per-step schema checks and the whole-workflow audit before this touches production. Run it alongside the manual process for a few hires and compare every field. Then open the same workflow in Tray Build so people operations can maintain the field mapping and the job profile translation in the visual canvas. New roles and levels appear constantly and none should need an engineer.
What it connects to
Recruitment hands over to HR, and provisioning waits on the result.
Greenhouse
Read the signed offer with its start date, level, compensation and manager. Recruitment data stays behind.
Reads
Workday
Create the worker record with a future start date, which is what provisioning schedules against.
Reads and writes
Okta
Read the manager and department for validation, so a record is not created against somebody who has left.
Reads
Slack
Tell the hiring manager and IT that a record exists and provisioning has started, with the start date.
Writes
DocuSign
Confirm the offer was actually signed rather than marked signed, so the trigger has evidence behind it.
Reads
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Google BigQuery, Microsoft Teams, Azure Active Directory, SAP SuccessFactors, Databricks or Google Chat.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This creates the employment record everything downstream depends on. A field dropped here surfaces on somebody first day.
It runs where production runs, not on a laptop
Offers are signed at any hour and the record is created immediately, instead of waiting for the next working morning.
The data boundary is enforced, not intended
Recruitment data does not cross. Interview feedback in an HR record is visible to people who should never see it and nobody ever removes it.
Managed credentials, not secrets in a config file
Creating worker records and reading compensation are among the most sensitive permissions in the company. Scoped, in your workspace, separately rotatable.
People operations own the mapping
Field mapping and job profile translation open in Tray Build, because new roles and levels appear constantly.
Nothing partial is created
An unmapped or invalid field fails the sync loudly. A partial worker record is discovered by the new joiner on their first day.
Questions people ask
Why trigger on signature?
Because every day between signature and the worker record is a day provisioning cannot start. A weekly handover meeting routinely costs three of them.
What should not cross into the HRIS?
Interview scorecards, interviewer feedback, rejection reasons and negotiation history. In an HR record they become visible to managers who should never see them, and nobody removes them afterwards.
Why create the record before the start date?
Because provisioning schedules against it. Hardware ordering, identity creation and access sequencing all need lead time, and a record created on day one gives them none.
What is the most common failure?
Picklist mismatches. The ATS job title is free text and the HRIS job profile is a controlled list, and a silently dropped or defaulted value surfaces in the first payroll cycle.
What should be reconciled?
Signed offers with no worker record. It should be zero, and every instance is somebody arriving on their first day to nothing being ready.
Vibe-coding app guides
Vibe-code an entire app with Helix
This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.
How to build an interview scorecard app (opens helix.tray.ai in a new tab)
Related guides
People operations
How to build employee onboarding provisioning
Drive it from the HRIS, derive access from the role instead of a copied colleague, sequence around the start date, and prove it happened. The prompts that build it.
People operations
How to build an HRIS to payroll sync
Sync effective-dated changes, respect the payroll cutoff, hold anything ambiguous instead of guessing, and reconcile every cycle. The prompts that build it.
Last reviewed September 2026.