Bulk-Importing Employees from CSV for Phishing Campaigns
The fastest path from "we just bought a phishing simulation platform" to "we just ran our first campaign" is a clean CSV import of your employee roster. Done right, it takes ten minutes and unlocks every downstream feature - automated training assignment, manager-level reporting, departmental click-rate breakdowns and difficulty-tiered targeting. Done wrong, you'll be untangling duplicates and email-bounce noise for a week.
This post is the practical, copy-this-format guide to bulk-importing employees from CSV into Bait & Phish: required columns, recommended columns, deduping rules, what happens on re-import and how the import feeds the auto-assignment system that fires training the instant a user clicks a simulated phishing email.
Why bulk import beats one-by-one
Adding users one at a time through the UI is fine for a 5-person pilot. It stops being fine the moment you cross 25 - which is also the moment your free trial limit kicks in and the conversation with HR about a real roster begins. CSV import:
- Lets HR or IT export from your existing source-of-truth (HRIS, AD, Google Workspace, Okta) and hand it to the security team without granting platform access.
- Captures the org-chart relationships - manager email, department - that drive the most useful reports.
- Is repeatable. The same file format is what you'll use every month or quarter to keep the roster fresh.
The required CSV format
Bait & Phish accepts a standard comma-separated file with a header row. Required columns:
- first_name - used for greeting personalization in regular and hard difficulty templates.
- last_name - used for full-name personalization where templates support it.
- email - the recipient address; also the unique identifier for deduplication.
- department - used for cohort-level reporting and per-department campaigns.
Recommended optional columns:
- job_title - drives executive-targeting logic (used to flag executives for hard-difficulty campaigns).
- manager_email - enables direct-supervisor click reporting and escalation. This is one of the most quietly impactful fields; managers seeing their team's results changes culture faster than any all-hands email.
- location - useful for region-specific campaigns and timezone-aware sending.
- employee_id - pass-through identifier for SIEM and HRIS reconciliation.
A minimal valid CSV looks like this:
first_name,last_name,email,department,job_title,manager_email
Sarah,Patel,sarah.patel@example.com,Finance,Controller,cfo@example.com
Marcus,Lee,marcus.lee@example.com,Engineering,Software Engineer II,em-lead@example.com
Priya,Singh,priya.singh@example.com,Sales,Account Executive,vp-sales@example.com
Deduping and update behavior
The unique key is email, normalized to lowercase. Practical implications:
- If the same email address appears twice in a single CSV, the second row wins. Newer department, title and manager values overwrite older ones from the same import.
- If an email already exists in the platform from a prior import, the new row updates the existing record in place. There is never a duplicate user.
- Whitespace and case are normalized -
Sarah.Patel@Example.commatchessarah.patel@example.com. - Rows missing from a re-import are not deleted by default. Deletion is an explicit step. This protects you from accidentally wiping a campaign's audience because someone exported only the Engineering department by mistake.
Pre-flight: cleaning your CSV
Most CSV import problems are CSV problems, not platform problems. A 60-second pre-flight check saves an hour of cleanup later:
- UTF-8 encoding. Save as UTF-8, not Windows-1252. Most spreadsheet apps default to Windows-1252 and quietly mangle accented names.
- No empty rows in the middle of the file. Some HRIS exports leave a blank row between departments - strip them.
- Email column actually contains email addresses. A surprising number of HRIS exports put the company-wide distribution list in the email column for executives. Spot-check the top 10 rows.
- Manager email matches an actual employee email in the file. If a manager_email isn't in the roster, manager reporting will silently no-op for that user. Either include the manager in the roster or leave the field blank.
- Excluded users are excluded. Pull out shared mailboxes, role accounts (info@, sales@, billing@) and any address you don't want to test. These are the leading cause of bounce noise.
Running the import
Once the CSV is clean, the platform import takes three clicks: upload, map columns, confirm. The mapping screen shows a preview of the first ten rows so you can verify columns are interpreted correctly before any data is written. The import is transactional - if any row fails validation, the whole import surfaces the row numbers so you can fix and re-upload, rather than leaving a half-imported list.
Imports up to 50,000 rows complete in under a minute on a standard plan. Larger imports - common for MSPs or enterprise consolidations - should be split into multiple files or run through the API.
How auto-assignment uses the imported list
The reason the import matters so much is what happens after a campaign runs. The instant a user clicks a simulated phishing link, Bait & Phish:
- Records the click event with template, difficulty and timestamp.
- Auto-assigns a remediation training module matched to the lure category they fell for (credential, authority, financial, IT, delivery).
- Notifies the user with a non-punitive learning prompt.
- Logs a notification to the user's
manager_emailif one was provided in the import - closing the feedback loop without making it punitive.
That entire chain depends on the import data being clean. Department drives cohort reporting; manager_email drives the supervisor loop; job_title flags executives for hard-tier targeting. Skip those columns at import time and you'll do the work twice when you decide you want them later.
Re-import cadence and roster hygiene
For most organizations, monthly re-imports are the right cadence. New hires arrive, departures leave, departments restructure. Common patterns:
- Monthly: Pull from HRIS or AD on the first of the month, re-import. Picks up new hires before they're targeted.
- Quarterly clean: Run an explicit deletion pass against the active roster - users not in the latest export but still in the platform. This is opt-in for safety.
- Real-time via API: For larger organizations, the API hook into Okta or Azure AD lifecycle events keeps the roster current without a CSV step.
Privacy, security and legal hygiene
An employee roster CSV is HR data. Treat it accordingly:
- Transmit over HTTPS only - never email the CSV around. The platform import is over TLS.
- Use the minimum data set required. Job title and department are valuable; salary, SSN or DOB do not belong in a phishing roster CSV.
- Document the data flow in your security awareness program record. Both NIST SP 800-50 and the Anti-Phishing Working Group (APWG) guidance call out program documentation as a standard requirement.
- If you're under GDPR or a similar regime, the lawful basis for processing this data is legitimate interest in security training; document that, too.
Common CSV import errors and what they mean
The errors that come back during import are short and specific. The five most common, with the fix:
- "Invalid email format on row N." Usually trailing whitespace, a missing
@, or a copy-pasted address with smart quotes. Open the row, retype the address, save as plain CSV. - "Duplicate email at row N." Two rows share an email. The platform treats the second as an update of the first, but flags it so you know. Generally safe to ignore unless the duplicate is unintentional (a merge artifact).
- "Manager email not found in roster." The
manager_emailcolumn references an address that's neither in the import nor already in the platform. Manager reporting will no-op for that user. Add the manager to the roster or leave the field blank. - "Row exceeds free trial limit." You're over 25 users on the free tier. Either trim the import or upgrade. The cap is enforced at import time precisely to avoid silent truncation.
- "Unsupported character encoding." The file isn't UTF-8. Re-save from your spreadsheet app with explicit UTF-8 encoding selected and retry.
API import for ongoing sync
For organizations larger than a few hundred employees, a quarterly CSV import becomes its own administrative burden. The Bait & Phish API supports the same import schema programmatically, which lets a security-engineering team wire the platform directly to the HRIS or identity provider. Common patterns: nightly diff against Okta or Azure AD, lifecycle events from Workday firing on hire and termination and SCIM provisioning for organizations standardized on it. The CSV format remains the source of truth for the data shape - the API is just a different transport for the same fields.
Where to start
If you've never run a campaign, the cleanest path is: import a CSV of up to 25 users into the free trial, run a single easy-difficulty campaign this week and use the results to scope your full rollout. If you're already past 25, pricing covers organizations of every size, and the same import format scales without modification. For walkthroughs of the larger campaign flow, see simulated phishing attacks, and for the training side that runs against your imported list, the security awareness training page covers auto-assignment in depth. Stuck on a stubborn HRIS export format? Contact us - we've seen most of them.
For broader context on phishing-program operations and reporting, the Verizon DBIR, FBI IC3 annual report, CISA, NIST, and Krebs on Security are the canonical sources we reference in our internal playbooks.
Related program operations and how-to guides
- Auto-assigned training for click events
- How to write effective phishing email templates
- Launch your first phishing simulation in 30 minutes
- Phishing simulation maturity model (5-tier framework)
- Phishing test difficulty levels and progression
- Multilingual phishing simulation programs