Lever to Ashby migration requires translating an opportunity-centric model to application-centric. Watch for Ashby's 200 OK error trap and multi-opportunity candidate splitting.
There is no native one-click migration path from Lever to Ashby for custom builds. Lever is opportunity-centric — a single Contact has multiple Opportunities flowing through pipelines. Ashby separates this into distinct Candidate, Application, and Job records with structured interview plans and feedback forms. The fundamental gap is architectural: Lever treats every interaction as a fluid Opportunity, while Ashby enforces structured evaluation with rigid interview stages. Translating between these models requires splitting records, deduplicating contacts, and navigating two different API styles — REST vs. RPC. Every custom migration must handle Ashby's deceptive 200 OK error responses, multi-opportunity candidate splitting, timestamp format conversion, and pre-configured feedback form requirements.
Read this first
Pair-specific gotchas that catch teams out. Each one has cost somebody a weekend.
Keep two immutable source keys throughout the project
one for the person (contactId in Lever) and one for the candidacy (opportunityId). Ashby requires separate candidate.create and application.create calls — if you flatten them into a single row, you cannot rebuild the relationship chain.
Lever stores timestamps as Unix epoch milliseconds
Ashby expects ISO 8601 strings. Every date field needs explicit conversion during the transform phase.
Lever API keys created without confidential data access cannot retrieve confidential
Lever API keys created without confidential data access cannot retrieve confidential postings, opportunities, or candidates. You must grant confidential access at key creation time — it cannot be added later. If your extraction script misses confidential records, you'll have a silent gap in your migration.
Use Lever's expand parameter aggressively
Expanding applications, stage, sourcedBy, and owner inline reduces the total number of API calls by 4–5x compared to fetching each relationship separately.
Always load in dependency order
If you try to create an Application before its Job exists in Ashby, the call will return 200 OK with success: false and a requested_job_not_found error — which your script won't catch unless you're checking the response body.
The runbook
Work top to bottom. Tick steps as you go — your progress is saved in this browser.
01 Discovery Scope candidates, pipelines and the compliance obligations that come with them.
Objective Agreed scope across candidates, applications, jobs and interview history, with legal signed up on retention.
Keep these open
-
Inventory every object in Lever
Count candidates, applications (a candidate can have many), jobs and requisitions, interviews, scorecards, offers, and resume files. Applications and scorecards usually outnumber candidates several times over, and resume files dominate storage.
Data Profiler Get real record counts instead of estimating from memory -
Settle retention and consent with legal
Candidate data is heavily regulated: GDPR right-to-erasure, EEOC/OFCCP record-keeping, and per-region retention windows that conflict with each other. Decide what may be migrated at all before you scope anything else — this frequently shrinks scope substantially.
Migrating candidate records whose consent has lapsed or whose retention window has expired creates a new compliance breach in the target system.
-
Map the hiring pipeline and agree the target stages
Document every job's pipeline, stage, and rejection reason, then agree the Ashby model with talent leadership. Stage definitions drive every funnel metric you report, so changing them silently rewrites your hiring analytics.
-
Catalogue integrations and the job-board estate
List job boards, careers-site integration, HRIS, background check, assessment platforms, calendar and email. The careers site and job boards are customer-facing, so their cutover needs its own plan and its own testing.
-
Build the business case and choose the window
Model licence delta, effort and recruiter productivity dip. Time the window against your hiring cycle: a migration during peak graduate recruitment or a hiring surge will fail on people, not technology.
Vendor Evaluator Score Ashby against alternatives on weighted criteria -
Rebuild interview plans
Lever's pipeline stages don't automatically map to Ashby's structured interview plans. Configure interview stages, feedback forms, and scorecard templates in Ashby for each job.
Lever → Ashby specifics
- All-in-one consolidation
- Lever requires separate tools for scheduling, CRM/sourcing, and analytics. Ashby bundles ATS, CRM, scheduling, and analytics into a single platform, reducing vendor sprawl and per-seat add-on costs.
- Built-in analytics
- Lever's reporting is functional but limited. Ashby ships with out-of-the-box dashboards across all jobs, automated Slack/email reporting, and custom alerts for SLA enforcement — capabilities that require third-party tools or manual exports in Lever.
- Modern UX and AI features
- Ashby's interface includes natural-language candidate search, AI-personalized outreach tokens, and AI-summarized interview feedback as native features, not bolt-on integrations.
- Relationship-chain preservation
- that keeps Candidate → Application → Feedback links intact
Don't move on until
- Counts confirmed for candidates, applications, jobs and offers
- Retention and consent obligations confirmed with legal
- Hiring-stage model agreed with talent leadership
02 Data Audit Audit candidate data with compliance sitting next to you.
Objective Profiled exports with duplicates, expired records and resume files all quantified and triaged.
Keep these open
-
Export and profile candidates, applications and jobs
Profile each object separately and reconcile against API counts. Watch the candidate-to-application ratio: a mismatch usually means applications have been silently truncated by pagination.
Data Profiler Profile the Lever export for nulls, outliers and type drift -
Quantify duplicate candidates and agree survivorship
The same person applies repeatedly over years with different emails and name spellings. Measure the duplicate rate and agree survivorship rules — which record wins and what happens to the application history attached to the losers.
Merging candidates without agreed survivorship rules destroys application and interview history that you may be legally required to retain.
Data Cleaner Strip empty rows, stray whitespace and dead columns -
Identify records outside their retention window
Flag candidates whose consent has expired, who have exercised erasure, or who fall outside regional retention. Exclude them from scope and document the exclusion — you need to show the decision was deliberate.
PII & Compliance Scanner Find regulated fields before they land in a new system -
Inventory resume files and attachments
Count files, total volume and MIME types, and check every attachment still resolves to a live URL. Expiring signed download URLs are the classic reason a resume migration completes with a large fraction of empty files.
Resume download URLs are often short-lived signed links. Fetch files close to load time or they will 404 mid-migration.
-
Verify relationship integrity
Confirm every application links to a live candidate and a live job, and every scorecard to a real interview. Orphaned applications produce a funnel report that does not tie to anything.
-
Clean, normalise and produce masked test data
Normalise emails, phone formats and locations, standardise timestamps to UTC, and generate a masked dataset for the sandbox. Real candidate data in a sandbox is a compliance breach in most jurisdictions.
PII Masker Generate a safe copy for sandbox and vendor testing
Lever → Ashby specifics
- Postings
- (GET /postings) — needed to map to Ashby Jobs
- Opportunities
- (GET /opportunities?expand=applications,stage,sourcedBy,owner) — the core data
- Feedback
- (GET /opportunities/{id}/feedback) — interview feedback per opportunity
- Resumes/Files
- (GET /opportunities/{id}/resumes) — binary file downloads
- Automated rate limit handling
- for Lever's 10 req/sec and Ashby's 1,000 req/min, including 429 retry logic
Don't move on until
- Duplicate candidate rate quantified with a merge policy agreed
- Records outside retention identified and excluded
- Resume and attachment inventory complete with total volume
03 Field Mapping Map the candidate-application-job triangle before anything else.
Objective A signed mapping covering objects, stages, rejection reasons, scorecards and EEO fields.
Keep these open
-
Map the candidate, application and job model
ATS platforms differ on whether a person or an application is the primary record. Establish this first: getting it wrong means one candidate becomes five, or five applications collapse into one, and the entire field map has to be redone.
Candidate-centric and application-centric models are not interchangeable. Confirm which Ashby uses before mapping any field.
Schema Mapper Opens pre-loaded with the Lever → Ashby field pair -
Map pipeline stages and rejection reasons exhaustively
Enumerate every stage and rejection reason across all jobs, including retired values on historical applications, and map each explicitly. Unmapped rejection reasons are both a reporting gap and, in regulated hiring, a compliance one.
-
Decide EEO and diversity data handling
These fields are separately regulated and often legally required to be stored apart from the candidate record. Confirm with legal whether they migrate at all, and how Ashby isolates them.
EEO data usually cannot be migrated into ordinary custom fields without breaching the segregation rules that govern it.
-
Map interviews, scorecards and feedback
Structured scorecards rarely have a native equivalent. Decide whether to reconstruct them, flatten them into notes, or keep them only in the archive — and be explicit that flattening loses the ability to report on them.
JSON to CSV Converter Flatten nested API responses into a reviewable sheet -
Plan resume and file migration
Confirm size limits, MIME support and whether Ashby re-parses resumes on upload. Re-parsing can overwrite carefully curated candidate fields with worse machine-extracted values, so test it deliberately.
-
Set load order and freeze the spec
Users, then jobs, then candidates, then applications, then interviews and scorecards, then files. Keep source IDs in custom fields, then version and sign off the spec.
Lever → Ashby specifics
- Custom field mapping and stage matching
- with explicit documentation when the target schema forces a compromise
Don't move on until
- Candidate/application/job model mapped and reviewed
- Every stage and rejection reason explicitly mapped
- EEO and diversity field handling agreed with legal
04 Test Migration Pilot whole candidate journeys, not isolated records.
Objective A sandbox pilot where candidate journeys, funnel metrics and resume files all verify.
Keep these open
-
Configure the Ashby sandbox with the agreed pipelines
Create jobs, pipeline stages, scorecard templates, user roles and custom fields first. Loading applications before the stages exist puts every candidate in a default stage and invalidates the pilot.
-
Select complete candidate journeys as the pilot slice
Take 100-200 candidates with all their applications, interviews, scorecards and files — including repeat applicants, hires, rejections at every stage, and candidates on multiple jobs. Repeat applicants are where the model mapping actually gets tested.
-
Run the load in dependency order with logging
Jobs, candidates, applications, interviews, then files, logging each request against its source ID. Track file uploads separately: they fail for different reasons and at different rates than record writes.
-
Verify journeys and funnel metrics
Confirm each candidate sits at the right stage on the right job with their history intact, and that per-stage funnel counts match Lever for the pilot jobs. Funnel mismatches point straight back to stage mapping.
Migration Validation Tool Diff the pilot batch against source before scaling up -
Open every pilot resume and check re-parsing
Actually open the files rather than trusting the upload count, and check whether re-parsing has overwritten any candidate fields. A resume that uploaded as a zero-byte file still counts as a success in most logs.
-
Put recruiters in front of the pilot data
Have recruiters work their own pilot requisitions end to end. They immediately spot missing feedback, wrong stages and unreadable history that reconciliation cannot see.
Don't move on until
- Candidate-application-job relationships intact for the pilot
- Funnel counts per stage match source for pilot jobs
- Resume files open correctly for every pilot candidate
05 Cutover Switch recruiting without dropping a live candidate.
Objective All in-scope recruiting data live in Ashby, careers site and boards repointed, recruiters working.
Keep these open
-
Pre-load historical candidates and closed jobs
Load closed requisitions, rejected candidates and archived applications while Lever stays live. Only active pipeline and the final delta need to move in the window.
-
Publish the runbook including the careers-site switch
A timed sequence with owners and abort criteria, treating the careers site and job boards as first-class steps. They are candidate-facing, so a failure there is publicly visible in a way a data defect is not.
-
Freeze Lever and take the final delta
Stop new applications and let recruiters finish in-flight actions, then export everything changed since the pre-load. Coordinate with anyone actively interviewing so feedback is not entered into the old system mid-freeze.
Interview feedback entered in the old ATS during the freeze is lost, and it is the data recruiters most immediately notice missing.
-
Load active pipeline and reconcile stages
Load active candidates and applications, then verify every active candidate is at the correct stage on the correct job before repointing anything. Active-stage accuracy is what recruiters check first on day one.
Migration Validation Tool Confirm the final delta landed before you reopen -
Repoint careers site, job boards and integrations
Switch the careers-site integration, repost or migrate live job ads, and repoint HRIS, background check, assessment and calendar integrations. Then submit a real test application through the careers site and every major board.
Job ads left posted against the old ATS keep collecting applications that never reach the new system.
-
Go/no-go and switch recruiters over
Call the decision against the exit criteria, then move recruiters with support on hand for the first day. Keep Lever read-only — candidate records have retention obligations that outlast the migration.
Don't move on until
- Historical load complete and reconciled before the freeze
- Careers site and job boards posting into Ashby and verified
- Active candidates confirmed at the correct stage
06 Validation Prove the funnel, the files and the compliance position.
Objective Reconciled recruiting data, funnel parity with baseline, and a defensible compliance record.
Keep these open
-
Reconcile every object including files
Compare counts for candidates, applications, jobs, interviews, scorecards and files, with field-level spot checks on a sample. Count files separately — they are the object most likely to be quietly short.
Migration Validation Tool Reconcile Lever and Ashby record-for-record -
Tie funnel and time-to-hire reporting to baseline
Rebuild funnel conversion, time-to-hire, source effectiveness and offer-acceptance reporting and compare to pre-migration figures. Variances trace back to stage mapping and to how application timestamps were handled.
Time-to-hire depends on stage-transition timestamps. If those were approximated, the metric will differ even with identical records.
-
Verify file integrity at scale
Sample-open resumes across the whole load and compare file sizes against source. Zero-byte and truncated files are common and never surface in an upload success count.
-
Confirm retention, consent and EEO configuration
Verify retention rules, consent state and EEO segregation are correctly configured in Ashby, and that excluded records genuinely did not migrate. File this as your compliance evidence.
PII & Compliance Scanner Produce the compliance evidence your auditor will ask for -
Test workflow, notifications and candidate-facing paths
Fire every stage automation, interview scheduling flow, rejection template and offer approval, and submit a live application through the careers site. Candidate-facing emails going out wrong is a brand problem, not just a bug.
-
Sign off and schedule decommission
Get written acceptance against the Discovery criteria, retain Lever read-only for the period your retention policy requires, take a final archive export, and diarise cancellation.
-
Verify permissions
Confirm recruiter permissions and confidential job access are correct in Ashby.
-
Monitor for 2 weeks
Watch for missing data, broken reports, or candidate experience issues. Have a point person checking daily.
Lever → Ashby specifics
- Recreate automations
- Lever's workflow rules (auto-archive, auto-advance, email triggers) don't transfer. Rebuild them using Ashby's automation builder.
- Reconnect integrations
- Job board feeds, HRIS syncs, Slack notifications, and calendar connections all need to be set up fresh in Ashby.
- Train your team
- Ashby's UI paradigm and candidate/application terminology differ from Lever. Schedule hands-on training sessions covering candidate search, application review, scheduling, and reporting.
- Pre-built response validation
- that catches Ashby's non-standard error pattern on every API call
- Post-migration validation
- with record-count reconciliation and field-level sampling
Don't move on until
- Reconciliation complete across candidates, applications and files
- Funnel and time-to-hire reporting tie to baseline
- Retention and EEO configuration verified, acceptance signed
Field mapping reference
The field-by-field mapping for each object. Use this as the starting point for your mapping spec.
Object Equivalent
| Lever field | Ashby field | Notes |
|---|---|---|
| Contact | Candidate | 1:1 mapping. Deduplicate by email before import. |
| Opportunity | Application | Each Lever Opportunity becomes an Ashby Application linked to a Candidate and Job. |
| Posting | Job | Map Posting IDs to Job IDs. Create Jobs in Ashby first. |
| Stage | Interview Stage | Lever stages are per-pipeline; Ashby stages are per-job interview plan. |
| Feedback / Scorecard | Application Feedback | Use applicationFeedback.submit in Ashby. Form structure must be pre-configured. |
| Notes | Candidate Notes | Use candidate.createNote. Supports HTML formatting. |
| Tags | Candidate Tags | Use candidate.addTag. |
| Sources | Candidate Source | Map Lever's origin and sources fields to Ashby's source tracking. |
| Resume / Files | Candidate Files | Lever allows file download via API; Ashby file upload requires candidate.uploadResume or applicationForm.submit. |
| Archived Reason | Application Archive Reason | Map Lever's archive reasons to Ashby's configured reasons. |
Lever Ashby
| Lever field | Ashby field | Notes |
|---|---|---|
| contact (ID) | candidate.id | Generate new; maintain lookup table |
| name | candidate.name | Direct map |
| emails [] | candidate.emailAddresses [] | Flatten to primary + additional |
| phones [] | candidate.phoneNumbers [] | Direct map |
| headline | candidate.title | Direct map |
| location | candidate.location | May require structured parsing |
| tags [] | Candidate Tags | Call candidate.addTag per tag |
| sources [] | candidate.sourceId | Map to pre-created Ashby sources |
| origin | candidate.creditedToUser | Map origin type to Ashby user |
| stage.text | application.currentInterviewStageId | Map by stage name to Ashby stage ID |
| archived.reason | application.archiveReasonId | Pre-create archive reasons in Ashby |
| createdAt | candidate.createdAt | Convert epoch ms → ISO 8601 |
Risk matrix
Per-object risk for this pair. Plan extra validation around anything marked high.
| Object | Risk | Notes |
|---|---|---|
| Interview Feedback | high | Requires pre-configured Ashby feedback forms; structure is lost without upfront template creation |
| Confidential Data | high | Lever requires special API key permission granted at creation time; missing data creates silent gaps |
| Multi-Opportunity Candidates | high | Must produce one Candidate with multiple Applications; incorrect handling creates duplicates |
| Custom Fields | medium | Lever allows flexible fields; Ashby requires strict schema definitions with pre-loaded picklist values |
| Pipeline Stages | medium | Lever stages are per-pipeline; Ashby stages are per-job interview plan — requires mapping by name |
| Resume Files | medium | Lever allows download via API but Ashby upload capabilities are more limited |
| Archive Reasons | low | Requires pre-creation in Ashby but mapping is straightforward |
| Tags | low | Direct mapping via candidate.addTag endpoint |
| Notes | low | HTML-formatted notes transfer well via candidate.createNote |
| Sources | low | Map Lever origin and sources fields to pre-created Ashby source categories |
The hard parts
What makes this specific migration difficult, beyond the mechanics.
Ashby 200 OK Error Trap
Ashby returns HTTP 200 even for failed requests. The success/failure is buried in the response body's success field — scripts checking only status codes silently skip failed writes.
Multi-Opportunity Deduplication
A single Lever Contact with many Opportunities must become one Ashby Candidate with multiple Applications. Creating a new Candidate per Opportunity produces phantom duplicates.
Timestamp Conversion
Lever stores timestamps as Unix epoch milliseconds while Ashby expects ISO 8601 strings. Every date field needs explicit conversion.
Feedback Form Pre-Configuration
Ashby's applicationFeedback.submit requires pre-configured feedback form IDs. You cannot dump Lever feedback directly — forms must be created or a generic form must be used.
API Architecture Mismatch
Lever uses REST (GET requests) while Ashby uses RPC-style (all POST requests). Two fundamentally different API patterns must be handled in a single pipeline.
Tools used in this playbook
All free, all run entirely in your browser — nothing is uploaded.
FAQ
How long does a Lever to Ashby migration take?
A CSV-based migration for under 500 candidates can be done in a day. A full API-based migration preserving interview history, feedback, and relationships typically takes 2-4 weeks for a custom ETL build, or days with a managed migration service.
What are the Lever and Ashby API rate limits?
Lever enforces 10 requests per second per API key (2 req/sec for application POSTs). Ashby allows 1,000 requests per minute per API key. Report endpoints in Ashby are further limited to 15 requests per minute.
Can I migrate interview feedback from Lever to Ashby?
Yes, but not via CSV. You need to extract feedback per Opportunity via Lever's API, then load it into Ashby via the applicationFeedback.submit endpoint. Ashby requires pre-configured feedback forms, so you must create matching forms before importing — or create a generic 'Migrated Feedback' form and map all Lever feedback into a text field.
Why can't I use a CSV export to migrate from Lever to Ashby?
CSV exports flatten relational data. You lose the links between candidates, applications, interview notes, and scorecards. Multi-opportunity candidates become duplicate rows. Ashby explicitly says its self-serve CSV import is not a comprehensive candidate-lifecycle migration.
How do I avoid duplicate candidates during the migration?
Ashby does not enforce deduplication on candidate.create. Build a local lookup table keyed by canonical email address. Before every candidate.create call, check whether that email already has an Ashby candidate ID. One Lever Contact with multiple Opportunities should produce one Candidate and multiple Applications.