How to Migrate to Bullhorn Without Importing a Mess

How to Migrate to Bullhorn Without Importing a Mess

TL;DR: Most Bullhorn migrations go wrong because of skipped data auditing and entity mapping, not import errors. Audit and clean your source data first, map every legacy entity to Bullhorn's Candidate/Contact/JobOrder/Placement model explicitly, and treat GDPR consent records as a migration dependency. Plan on four to six weeks for a clean small agency, ten to sixteen for a mid-size one, and keep the old system running for at least two weeks after go-live.

Decide what you are actually migrating before you touch anything

Most agencies assume a migration to Bullhorn means moving everything across. It does not. The cheapest way to cut migration cost, timeline and post-go-live mess is to decide, in writing, which entities have genuine operational value and which are dead weight. Migrating ten years of uncontacted candidates does not preserve value, it pollutes the new system and hands you a GDPR liability on day one.

The scoping framework I use splits everything into three tiers. First, entities with active revenue attached: candidates with placements in the last 24 months, live job orders, active client contacts. Second, entities with compliance value: right-to-work records, consent history, contractor timesheet history. Third, everything else, which by default does not migrate. On a recent 12-desk agency project, the source database held 68,000 candidate records, of which 9,000 had any placement or application history. The other 59,000 were event lists and a 2016 CV-dump scrape. That database would have cost roughly three times as much to migrate in full, and every one of those 59,000 records would have been a consent question with no answer.

Duplicate company records need a merge strategy decided in the source system before export. Legacy systems accumulate five variants of the same client: "ACME Ltd", "Acme Limited", "ACME", "Acme (London)", "acme". If you export the duplicates and try to merge them in Bullhorn afterwards, you are re-linking every associated job order and placement by hand. Do not do this. I have unpicked exactly this mess on a live instance and it took longer than the original import.

Orphaned records are the other pre-export find: notes attached to merged or deleted records, placements pointing at client contacts who left in 2019. These surface as import errors at best and silently broken relationships at worst. Bullhorn's onboarding team will not clean any of this up - they load what you give them. Agencies routinely discover this at week three, which is an expensive time to learn it.

What I would do is budget two to three weeks of admin time for the audit on a mid-size database. It is the highest-value work in the entire project, and on any honest project plan it should account for 60-70% of the elapsed time.

How Bullhorn's data model differs from common source systems

Bullhorn's data model forces mapping decisions that most legacy ATSs never required. The differences are structural, not cosmetic, and if you do not plan for them your CSV will import without errors and still be wrong. The four differences below account for most of the broken migrations I have been called into afterwards.

The entity mapping table

The first difference is the Candidate versus Contact split. Most source systems - JobAdder, Loxo, Recruit CRM - use a single person record. Bullhorn separates Candidates (workers) from Contacts (client-side people) as distinct entities. A person who was a placed contractor and later became a hiring manager at a client exists as two records with no native link between them. Every person record needs an explicit routing decision: candidate, contact, or both. A workable mapping looks like this:

  1. JobAdder "Candidate" maps to a Bullhorn Candidate.

  2. JobAdder "Contact" maps to a Bullhorn Client Contact.

  3. Loxo's single "Person" record needs a routing decision based on ownership and history: if the person has placements or applications, they become a Candidate; if they sit on a client account, a Contact; if both, two records with a note on each pointing at the other.

The second difference is that placement history is relational. A Bullhorn Placement links Candidate plus JobOrder plus Client Contact, and sits within a Tearsheet context. A flat CSV export from Vincere or Loxo has none of that structure, so you need to export and reassemble four related datasets in the correct dependency order - companies first, then candidates and contacts, then job orders, then placements. Get the order wrong and every placement imports as an orphan with nothing attached to it.

Field types that break silently

The third difference is field type constraints. The Notes body field is a textarea with a character limit that silently truncates long notes on import. No error, just a cut-off sentence. Custom text fields have their own limits. Verify both against a sample batch before the full run.

The fourth difference catches almost everyone: MultiValue fields require pipe-delimited formatting in bulk import files. A working value looks like VAT Registered|PAYE|Umbrella. Import a comma-separated version and Bullhorn stores it as a single malformed option that then breaks every filter and report built against that field. Worth flagging that this produces no error at import time either - the failure shows up weeks later when a consultant filters on PAYE and gets nothing.

Finally, custom field capacity differs by Bullhorn subscription tier, so count your legacy custom fields before committing. If the audit turns up 30, merge the redundant ones during the audit rather than migrating all of them into a tier that will not hold them.

What are the three ways to migrate to Bullhorn from another ATS, and which fits your data?

There are three realistic routes: Bullhorn's own onboarding and data migration service, a third-party partner working through the Bullhorn REST API, or a DIY bulk import. The right choice depends on data complexity and volume rather than budget - a clean 4,000-record database can go through bulk import, while anything relational, compliance-heavy, or over roughly 5,000 records needs API work.

Option 1: Bullhorn's onboarding service

Bullhorn's own service typically covers candidates and companies in standard fields. It does not usually cover custom field mapping, compliance records, or the Privacy Consent entity. The realistic timeline from their side is days to weeks once your file is ready - the queue is your file readiness, not their capacity. The drawback is that everything the service does not cover lands back on your desk, usually without anyone saying so at the start.

Option 2: a third-party partner via the REST API

This is how it works at a high level: OAuth authentication, entity-by-entity POST requests in dependency order, and rate limits of roughly 10 calls per second on standard allocations, which turn a 50,000-record migration into a multi-day scripted run rather than an afternoon. The drawback is cost and dependency on the partner, which is why the questions matter more than the quote. Ask any partner four things: how do you handle the Privacy Consent entity, what is your rollback plan, what happens to placements with missing linked entities, and can you show me a validation report. A partner who cannot answer all four is a partner who has not done this before.

Option 3: DIY bulk import

Bulk import is viable for small, flat datasets - a few hundred companies, a simple candidate list with no custom fields. It breaks down on anything relational, anything using MultiValue or custom fields at scale, and any volume over about 5,000 records where error handling becomes a job in itself. The drawback is that the failure modes are silent: truncated notes, malformed MultiValues, orphaned placements, no consent records.

Pick based on what the Section 1 audit tells you about data complexity, not on which option looks cheapest in week one. A DIY route that silently truncates notes across 20,000 records costs more to fix than the partner quote ever did.

What happens to your GDPR consent records in a Bullhorn migration?

Migrating candidates without their associated consent status leaves you with a live database you may have no lawful basis to communicate with. Bullhorn handles GDPR consent natively through the Privacy Consent entity and consent fields on the Candidate record, but the bulk import tool does not create Privacy Consent records - that requires API work or a manual post-migration process.

Where consent lives in legacy systems varies, and each storage pattern needs a different extraction approach. Usually it is a checkbox custom field ("GDPR consent - Y/N"), sometimes a dated note, and sometimes nothing structured at all - just an absence of complaints. A 2018-era checkbox field with no timestamp is legally weaker than a dated note and should be flagged for re-permissioning, not silently migrated as valid consent.

On the Bullhorn side, the Privacy Consent entity holds consent type, date, source and expiry where applicable, alongside candidate-level GDPR fields. Set your Privacy Consent types up before migration day, not after. The specific gap to plan around: because bulk import does not create Privacy Consent records, a DIY or onboarding-route migration can land 40,000 candidates with a "consent" text field populated and zero actual Privacy Consent records. The system looks compliant and is not. That is the single most likely source of post-migration ICO exposure I see.

Right-to-work and other compliance documents need the same treatment: establish where they sit in the source system, whether the attachments themselves survive export, and how expiry dates map to Bullhorn fields. Attachments are the part that most often does not survive.

My recommendation is to treat consent mapping as a migration dependency with its own line in the plan, not a post-migration tidy-up. If consent data cannot be mapped for a candidate, that candidate goes into a quarantined state or into a re-permissioning campaign before anyone emails them. If neither is possible, they do not migrate.

Email, calendar, and job board integrations during the switchover

Integrations are configured against your live system, so cutting over to Bullhorn mid-month can break active sourcing workflows if nothing has been reconfigured beforehand. The job boards stop pulling applications, email stops logging, and nobody notices for a week because everyone assumes the quiet pipeline is a quiet market.

Build a parallel running checklist before go-live. It should cover every active integration - Bullhorn for Gmail/Outlook, calendar sync, CV-Library, Reed, Indeed, LinkedIn RPS - plus the credentials or API keys needed for each, the Bullhorn-side reconfiguration steps, and a named person responsible. Include Bullhorn Marketplace partners too: TextKernel for CV parsing, SourceBreaker, Idibu. Each has its own activation process, and some have an activation lag of days before they are live. Discovering that lag on go-live day is entirely avoidable.

Three specifics worth building into the checklist:

  • Job board API keys are issued per platform account, so reconfigure and test posting a live role to each board before you actually need the applications to flow.

  • Email sync needs testing on newly migrated records, not just new ones. Historically migrated contacts sometimes fail to match on email address, and replies silently vanish instead of logging to the record.

  • If the agency syncs Bullhorn to HubSpot or Salesforce, that mapping needs rebuilding against the new record IDs. Legacy Bullhorn IDs become invalid at migration, so anything downstream keyed on them breaks, usually without an error.

On sequencing: reconfigure integrations in the first days of parallel running, not on go-live day. That gives you a fortnight to spot the silent failures while the old system is still there as a reference.

What should you test during the parallel running period?

A sensible parallel running period is two to four weeks, and it should test data integrity rather than new-system opinion. Spot-check five to ten contractor placement histories end to end, verify note counts on a sample of candidate records, confirm active job orders have their correct linked contacts, and check that email sync and compliance fields behave as expected.

The placement history spot-check matters most. Pick five to ten long-standing contractors and walk the full chain in Bullhorn: candidate, placement, job order, client contact, tearsheet. Broken placements are the most common silent failure because the import reports success while the relationships are missing. Then work through the rest:

  • Note counts: compare the number of notes on a sample of 20 candidate records against the source system. Truncation and dropped associations show up here first.

  • Active job orders: confirm each has the correct client, contact and owner. A job order with no linked contact is invisible to the consultant working it.

  • Email sync logging on new records created during parallel running, not just migrated ones.

  • Compliance fields populated where expected, including Privacy Consent records actually existing - not just a field saying yes.

The core discipline underneath all of this: go live and switch off the old system are two separate events, separated by at least two weeks. The extra month of legacy licence fees is trivial against the cost of discovering a data gap after cancellation, when your export access may already be gone.

Realistic timelines by agency size

Timelines depend almost entirely on the state of the source data, but honest ranges exist. A boutique agency on clean data can go live in four to six weeks. A mid-size agency should plan for ten to sixteen. An enterprise group should not promise anything under six months.

Boutique agencies - under 5 staff, under 10,000 records, simple structure - can hit four to six weeks from scoping to go-live if the audit finds clean data. Bulk import or Bullhorn onboarding is often sufficient at that scale.

Mid-size agencies - 10 to 30 staff, 50,000+ records, an active contractor base, custom fields in daily use - should plan for ten to sixteen weeks, assuming a third-party migration partner and one dedicated internal project owner. The internal owner matters more than the partner. Migrations stall on decisions only the agency can make, and a partner cannot force them.

Enterprise groups with multiple divisions, custom integrations and heavy compliance complexity should expect six months, and phased division-by-division migration is usually the right shape.

The single biggest variable in all three cases is source data condition. Migrating from a well-structured Vincere instance is a different project from extracting eight years of hand-keyed records from a legacy system where twelve people entered data twelve different ways. The audit from Section 1 is what tells you which project you have.

Worth flagging that the timeline nobody budgets for is the data audit and mapping sign-off. It is typically 30-40% of total project elapsed time, and every overrunning migration I have seen under-planned it.

The timelines above all assume someone has already run that audit and built the entity map. If that is the bit you need, book a migration audit and I will scope what your source data actually supports before you commit to a route.

Jack Roberts
Written by
Jack Roberts

Jack builds automation for UK recruitment agencies - Bullhorn, JobScience, Vincere, HubSpot and Monday.com. Seven years in-house in recruitment marketing before going full-time on the technical side, so the builds start from how a desk actually runs, not what the tool demo shows.

See where your team's time is going.

It starts with a short audit of your stack. I'll show you where consultant and back-office hours are leaking, and what it would take to get them back.

Systems That Scale.

© 2026 Stack Logic. All rights reserved.
Here's our privacy policy.

See where your team's time is going.

It starts with a short audit of your stack. I'll show you where consultant and back-office hours are leaking, and what it would take to get them back.

Systems That Scale.

© 2026 Stack Logic. All rights reserved.
Here's our privacy policy.