Back to Admin console

How do I bulk-import data from a CSV?

Admin → Import data bulk-imports employees, leave balances, holidays, assets, salary structures and the org chart from a CSV, with a dry-run preview before anything is written.

~4 min read · For admin · Updated 18 Sept 2026

Quick answer

Open Admin → Import data, pick what you are importing, download its CSV template, fill it in and upload it. A dry run shows exactly which rows are ready and which have a problem before anything is written — only pressing Commit actually creates or updates records.

What can I import?

  1. Employees

    email, full name, department, designation, manager's email, and whether to send a sign-in invite. Matched by email.
  2. Leave balances

    email, leave type, year, total allocated and carried-forward days. Matched by email + leave type + year.
  3. Holidays

    date, name, type (public/optional/restricted) and a description. Matched by date + name.
  4. Assets

    asset tag, name, category, who it is assigned to, purchase date, condition and status. Matched by asset tag.
  5. Salary structures

    email, effective date, pay mode, annual CTC, monthly stipend and a revision note. Matched by email + effective date.
  6. Org chart

    email and manager's email — the fastest way to wire up reporting lines in bulk. Matched by email.

Payroll history and anything not listed above has no importer yet — that is a gap, not a hidden option, and is not something a support request can turn on early.

How do I run an import?

  1. Open Admin → Import data

    Only admins can see this page.
  2. Pick what you're importing and download the template

    The template's header row and one worked example row are generated from what that import actually checks, so it never drifts out of date.
  3. Fill in the template and upload it

    Keep the header row exactly as downloaded — column order does not matter, but the names do.
  4. Read the dry run

    Every row is validated, and duplicate rows within the file are caught, before anything is written. Rows are listed with their row number, the column at fault, the message, and whether it is a blocking error or a warning.
  5. Fix any errors and re-upload

    A row with an error is dropped entirely — it will not be imported until you fix it in your file. Commit stays disabled while any error is outstanding.
  6. Commit

    If the dry run only has warnings, you are asked to confirm before committing — the flagged rows still import, just double-check them. The summary afterwards shows how many rows were created, updated and skipped.

What counts as an error vs a warning?

  • Error — the row was dropped and will not be imported: a required column was blank, a value did not parse (not a valid email, not a number, not YYYY-MM-DD), or its natural key repeats another row in the same file. Fix these in your file; the row does not import until you do.
  • Warning — the row still imports, but something about it needs a look: most commonly a manager_email or assigned_to_email that does not match anyone in your workspace yet. Set the correct link afterwards from that record's own page.

Is it safe to re-run a file?

Yes. Every import matches rows by a natural key — an employee's email, a holiday's date and name, an asset's tag, and so on (see the table in content/import-templates/README.md for the exact key per kind). Re-uploading the same file updates the same records again instead of duplicating them, so a corrected re-upload after fixing errors is the normal way to finish an import, not something to be careful about.

Why did some employee rows get skipped?

Bulk-inviting employees runs through the same seat-limit check a hand-typed invite does. If your file's invites would put your workspace over its plan's seat count, the rows after that point come back skipped with that reason rather than failing the whole file — the rows before the limit are still created. Add seats on Admin → Plan & Billing, then re-upload the same file to pick up where it left off.

Frequently asked questions

Which data can I bulk-import?
Employees, leave balances, holidays, assets, salary structures and the org chart — each from its own CSV template on Admin → Import data. Payroll history and anything else not listed there has no importer yet.
Will importing overwrite my existing data?
No, not silently. Every import matches rows by a natural key (an employee's email, an asset's tag, a holiday's date and name, and so on) — a row that already exists is updated, not duplicated, and a row the file does not mention is left untouched.
What happens if my file has errors?
The dry run lists every problem row before anything is written. A row that fails validation (a bad email, a missing required column) is dropped and never imported — fix it and re-upload. A row that only trips a warning (for example, a manager_email that does not match anyone yet) still imports, flagged so you can check it afterwards.
Can I import the same file twice by accident?
Yes, safely. Every importer commits by natural key, so re-running the exact same file updates the same rows again rather than creating duplicates.
Does send_invite on the employee template email everyone in the file?
Yes, for every row where it is true (or left blank, which defaults to true) — the same invite email a hand-typed employee would get, including the seat-limit check. Set it to false for people you want on record without a login.