Skip to main content

Import applicants from your previous ATS

Move candidates from an old applicant tracking system into Fountain with one CSV file: what comes across, how to format it, and how to check the result.

Use this when you already have candidates somewhere else — an old applicant tracking system, a spreadsheet, an agency list — and you want them inside Fountain.

You upload one CSV file. Fountain creates an applicant for each row and places them in the opening you choose.

Coming soon: connect your system directly instead.

If your applicant tracking system is one Fountain supports, the Connector Marketplace will bring applicants across on its own — nothing to export, nothing to upload, and it keeps working after the first load. When that arrives it becomes the recommended route. This CSV method then stays for the cases a connector does not cover: a system that is not supported, a one-off historical migration, or a file you have already cleaned by hand.

Before you start

What comes across, and what does not

It imports data: name, email, phone number, home address, language, time zone, messaging consent, and any custom question your account already has.

It does not import files. Resumes, certificates, signed documents and photos cannot be imported this way. If you need those, contact your Customer Success Manager — that is a separate migration project.

Everyone lands in the opening's first stage. A stage is a position in a Fountain workflow, not a field on the applicant, so a row cannot simply name a stage, and re-importing never moves anyone who has since progressed. If your candidates need to start at different points in the process, that is still possible: see Placing people in different stages at the end of this article.

Any column Fountain does not recognise is dropped, with no warning. source, recruiter_notes, lever_status and the like simply vanish while the import reports success.

The import itself sends nothing. No text message, no email, no automation, no webhook fires because of the import. This is deliberate: importing 5,000 old candidates must not send 5,000 messages. The suppression covers the import only — once people are in, they behave like any other applicant, so before you move a large batch to another stage, check what that stage does. Fountain shows you: the move dialog names the automated actions for the destination stage before you confirm.

Create your openings first

Every applicant in Fountain belongs to an opening. You cannot import applicants on their own, so create your openings first.

You can create openings two ways:

  • By hand, in Hire, one at a time.

  • By import, if you have many. Openings need a location and a position to exist first, so the order is: locations and jobs, then openings, then applicants.

Decide where people should land

If your candidates map cleanly to real openings, import each group into its own opening.

If they do not — for example you are moving 8,000 old candidates and you just want them searchable — the common approach is to create one opening used as a talent pool, import everyone into it, and make the first stage a rule stage or a job selector stage that routes people to the right opening later. This is what most migrations do.

Find the opening ID

Each row of your file must say which opening the applicant joins. That is the funnel_id column.

To find it: open the opening in Hire and look at the address bar. The ID is the long code straight after /jobs/.

https://app.fountain.com/your-account/.../jobs/b5d2f4ea-a5ed-43c5-ae5d-1ff75a911920/v2/stages

In that example the opening ID is b5d2f4ea-a5ed-43c5-ae5d-1ff75a911920 — 36 characters with dashes. The opening name will not work; it has to be this ID.

Tip for large files

If your export has opening names but no IDs, you do not have to look each one up by hand. A Data Pipeline can fill funnel_id for you from the opening name. See Filling the opening ID automatically at the end of this article.

Import your file

Step 1 — Open the import window

Go to Applicants in Hire and click Import applicants.

Step 2 — Download the template and fill it in

Leave Standard configuration - Applicants import selected, then click Download CSV template. The template already has the correct column names, so using it is the easiest way to avoid mistakes.

One row per applicant. Keep the first row (the column names) exactly as it is.

Required in every row

Column

What to put

funnel_id

The opening ID from the address bar

email

The applicant's email address

phone_number

The applicant's phone number

name

Full name — or fill first_name and last_name instead

Optional

Column

What to put

first_name, last_name

Use these instead of name if your export has separate columns

applicant_id

Rarely needed. Fountain already matches on opening plus email, so use this only if you kept Fountain's own applicant IDs from an earlier export

country_code

Two letters, like US, FR, GB. Important for non-US phone numbers

phone_platform

sms or whats_app. Must be switched on for your account, otherwise the row fails

time_zone

Like America/New_York

application_locale

Like en, fr, es

consent_sms_transactional, consent_sms_marketing, consent_calls_transactional, consent_calls_marketing

true or false only. Leave blank if you do not know

address1, address2, city, state, zip, country

Home address

You can leave any optional column blank, or delete the whole column.

Step 3 — Upload and preview

Drag your file into the window and click Preview. Fountain shows you how your columns will be read.

Check the preview, then click Import applicants.

Run a sample of 5 to 10 rows first

The preview catches empty required cells, but it does not catch everything. An opening ID that does not exist, or the same person listed twice, is only reported once the import runs. Import a short file, open those applicants in Hire, and only then run the full export. Undoing a bad import is manual, so ten minutes here saves hours later.

Step 4 — Check the result

A large file takes a few minutes. When it finishes, click Go to Data Pipeline Logs to see what happened.

Each run shows how many rows were created, how many were updated, and the exact reason for every row that failed.

Then open your opening in Hire. The new applicants sit in the first stage.

Getting your file right

These are the mistakes we see most often.

Clean the data before, not after. Fountain accepts a lot of imperfect input silently — short phone numbers, odd email addresses. Whatever you send is what you get.

Save your file as a comma CSV

This is the number one cause of a failed import.

In Europe, Excel often saves CSV files using semicolons instead of commas. Fountain reads that file as one single column, so every row fails with a confusing message saying funnel_id, email and phone_number are all missing — even though you can see them in your spreadsheet.

If you get that error on every row, open the file in a text editor. If you see semicolons between values, re-save it. In Excel: File, Save As, CSV UTF-8 (Comma delimited).

Do not put spaces in the column names

A column named funnel_id with a space at the end is not the same column as funnel_id. Fountain will not recognise it and will tell you the field is missing. The values can have spaces — Fountain trims those — but the header row cannot.

Delete empty rows

A blank row in the middle or at the end of your file counts as a row. It fails and shows up as an error, which makes a good import look broken.

Extra columns are ignored, silently

If your export has a column Fountain does not know — recruiter_notes, source, lever_status — the import succeeds and that column is simply dropped. There is no warning.

If you need to keep that information, the custom question must already exist in your Fountain account, and a Data Pipeline must map your column onto it. New custom questions cannot be created during an applicant import.

Files saved from Excel are fine

Windows line endings and the invisible marker Excel adds to UTF-8 files both work. You do not need to do anything about them.

Import one file at a time

Running several imports at the same moment can make one of them time out with Applicant import poll timed out. Nothing is lost — just run it again, one at a time.

The home address may not be visible

It is imported and stored, but it only shows on the applicant profile if the opening actually asks for a home address. If your opening does not collect one, you will not see it even though it is there.

Phone numbers

Phone numbers are converted to international format automatically. You do not need to format them yourself. Each of these is accepted and stored in full international format:

What you type

What Fountain stores

(415) 555-0101

+14155550101

415-555-0102

+14155550102

415.555.0103

+14155550103

+1 415 555 0104

+14155550104

4155550105

+14155550105

Non-US numbers need a country code. A French number written 06 12 34 56 79 is only read correctly if the row also has country_code = FR. With it, you get +33612345679. Without it, Fountain assumes your account's country and the number will be wrong. Numbers already written in full international form are always safe.

Remove extensions before importing. 415-555-0108 x22 is stored as +14155550108 x22, extension included. Text messages to that number will not work. Put extensions in a separate column, or delete them.

Fountain does not check that a number is real. 555-0109 is accepted and stored as +15550109. Clean your data before importing — nothing will warn you.

Email addresses

Email is how Fountain recognises someone, so it matters more than the other fields.

  • Capitals and spaces do not matter. [email protected] and [email protected] are treated as the same person.

  • An address with no @ is rejected, with the message Email is invalid.

  • Checking is light. john@@example.com is accepted. Fountain will not catch every typo, so clean your list first — a wrong address means the applicant never hears from you.

  • Email is required. Rows without one are rejected.

Consent columns

The four consent columns accept true or false and nothing else — yes, Y or 1 fail the row.

A blank consent cell records nothing at all. For a new applicant that means no consent on file, so you cannot message them about future opportunities. For someone already in Fountain it means their existing consent is left untouched — a blank cell never removes a consent they already gave.

Only put true if your old system holds a real opt-in for that channel. Whether an opt-in given to a previous vendor still applies in Fountain is a legal question, not a data question — check with whoever owns privacy at your company before filling these in.

Creating, updating and duplicates

Fountain matches on the opening plus the email address.

  • Email not yet in that opening: a new applicant is created.

  • Email already in that opening: the existing applicant is updated, not duplicated.

  • The same person in two different openings: two applicants, one per opening. This is intended, because in Fountain someone applies to a specific opening.

Re-importing the same file is safe. Run the same file twice and nothing is duplicated. The second run updates instead of creating.

An update never moves anyone. If a candidate has already progressed — say they are sitting at Interview — re-importing their row changes their details and leaves them exactly where they are. Applicants land in the first stage only on the run that creates them.

To update people, send the same file with the values changed. Two rules:

  1. Required fields must be there every time. Even to change only a name, the row still needs funnel_id, email and phone_number. A row missing the phone number is rejected, even for an update.

  2. Blank cells never erase anything. Leaving a cell empty keeps whatever is already in Fountain. You cannot clear a field by importing an empty value — do that in Hire.

The same person twice in one file. If two rows in the same file have the same opening and the same email, the first is imported and the second is rejected as a duplicate. Remove duplicates before importing.

When something fails

Message

What it means

What to do

"funnel_id" required on every row

Your file is probably semicolon-separated, or a header has a space

Re-save as comma CSV, check the header row

"funnel_id" invalid uuid

You put an opening name instead of the ID

Copy the ID from the opening's address bar

Funnel not found for funnel_id

The ID is well formed but no opening matches

Check you copied the right opening, in the right account

"email" required or "phone_number" required

The cell is empty

Fill it, or remove the row

"name" required

No name, and first_name and last_name are not both filled

Fill one or the other

Email is invalid

The address has no @

Fix the address

Country code is unknown

country_code is not a real country

Use two letters, like US

Phone platform not in sms

You asked for a channel your account does not have

Use sms, or ask your Customer Success Manager to enable WhatsApp

Cannot convert 'yes' to boolean

A consent column holds something other than true or false

Use true, false, or leave it blank

Duplicate email appears more than once in this import

Two rows, same opening, same email

Remove the duplicate

Applicant import poll timed out

The import took too long, often because several ran at once

Run it again on its own

Limits

  • 10 MB per file. Split larger exports.

  • No limit on the number of rows. With the standard columns, a 10 MB file holds tens of thousands of applicants. Fountain processes them in the background, 100 at a time.

  • CSV only for this screen.

Undoing an import

There is no single undo button. Each applicant's menu inside the opening has Delete Applicant, and you can tick several rows at once, but unwinding a wrong file of several thousand is slow and painful. That is the real reason to run the sample first.

Placing people in different stages

By default an import puts everyone in the opening's first stage. If your candidates need to start at different points in the process — some at Interview, some at Offer, the rest at the beginning — Fountain can place them from a column in your file.

The mechanism is a rule stage: a stage nobody stays in. It reads each applicant as they land, applies your rules, and pushes them to the stage you named.

Set it up

  1. Create a custom question on your account to carry the old status, for example previous_status. It has to exist before the import, because an import can only fill fields that already exist.

  2. In the opening's workflow, add a rule stage and move it to first position.

  3. In that rule stage, add one rule per destination.

  4. Add the column to your file and fill it in per row.

The rules read like this:

IF   previous_status = interview   →   move to stage "Interview"
IF previous_status = offer → move to stage "Offer"
ELSE → continue to the next stage

And the file carries each person's destination:

funnel_id                              name     email           previous_status
b5d2f4ea-a5ed-43c5-ae5d-1ff75a911920 Maria [email protected] interview
b5d2f4ea-a5ed-43c5-ae5d-1ff75a911920 Daniel [email protected] offer
b5d2f4ea-a5ed-43c5-ae5d-1ff75a911920 Priya [email protected]

Maria arrives at Interview, Daniel at Offer, and Priya, whose cell is empty, carries on to the opening's normal first stage. One file, one opening, three different destinations.

What to expect

Nothing is sent. The rule moves people silently, exactly like the import itself: no message, no email, no automation, no webhook.

An empty cell is not an error. Anyone matching no rule simply continues to the next stage, so leave the column blank for candidates who should start at the beginning. Nobody is left sitting in the rule stage.

Do not branch a rule on the consent columns. Consent is recorded after the applicant has been placed, so a rule reading it would always see the default value. Branch on a custom question, or on name, email or phone number.

Test the routing on a few rows first

Import three or four rows covering each destination and check where they land before you run the full file. A rule that names the wrong stage moves everyone silently, and there is no undo.

Filling the opening ID automatically

This section is for large files where looking up every opening ID by hand is not realistic. It has to be set up once by someone with access to Settings, Data Pipelines.

The idea: your file keeps the opening name it already has, and Fountain converts that name into the ID during the import.

Set it up

  1. Go to Settings, Data Pipelines and click Add a data pipeline.

  2. Name it, choose Inbound, and set Data type to Applicants.

  3. Under Enrich import data using, select Openings. This is the step people miss — without it the conversion cannot run.

  4. Click Next, and on the Mapping step map your opening-name column to funnel_id.

  5. Click the code icon on that row and paste the script below.

({ row, openings }) => {
  const COLUMN = 'opening_name';
  const name = String(row[COLUMN] || '').trim().toLowerCase();
  const opening = openings.byTitle[name];
  if (!opening || !opening.externalOpening) {
    throw new Error('Opening not resolved: ' + row[COLUMN]);
  }
  return opening.externalOpening.externalIdentifier;
}

Change one thing only: 'opening_name' on the second line, to the exact name of your own column. It appears once on purpose, so there is nothing else to edit. Column names with spaces are fine — const COLUMN = 'Requisition Title'; works as written. Save, then choose this pipeline instead of the standard one when you import.

What to expect

Capitals and spaces do not matter. Central Dispatch - Delivery Driver and central dispatch - delivery driver both work. Everything else must match the opening name exactly, punctuation and hyphens included.

Two openings with the same name are skipped on purpose. The script cannot tell which one you meant, so both are treated as not found. Give such openings distinct names, or use the ID for those rows.

Rows it cannot resolve fail individually with Opening not resolved, and the rest of the file still imports. Nothing is created for the failed rows.

Test your opening names before you commit the full file

Build a small file with one row per distinct opening name in your export, and import that first. Any name that comes back Opening not resolved is written differently in Fountain than in your export — correct the spelling, or use the ID for those rows. It takes a minute, and it beats finding out on row 2,400.

Did this answer your question?