Universal CSV Importer
The Universal CSV Importer lets workspace admins bulk-import their data into Toggl 2.0 from any CSV file.
The importer works with any CSV file - whether it's an export from another tool (Harvest, Clockify, ClickUp, Asana, Teamwork, or others) or a spreadsheet you built yourself. You map your CSV's columns to Toggl fields once, and the importer creates clients, projects, tasks, tags, members, and time entries for you.
Who can use it
- Plan: All Toggl plans.
- Role: Workspace admins only.
Where to find it
You'll find it under Settings → Data import → Universal CSV Importer → Open importer. If you don't see it, the feature may not be enabled for your workspace yet, or you may not have admin rights.
What you can import
The importer supports six data types:
- Clients
- Projects (can be linked to a client)
- Tasks (can be linked to a project, client, parent task, assignee, and tags)
- Tags (imported through a Task's Tags column - see Tasks)
- Members (workspace users, invited by email)
- Time entries (can be linked to a task, project, client, and user)
🧩 Custom fields are supported. If your workspace uses custom fields, you can import their values on projects and tasks — see Custom fields under the field reference below.
Before you start: preparing your file
Is there a template or required format?
There's no fixed template. You can use a CSV from almost any tool, and you map your columns to Toggl fields during the import. Your file does, however, need to meet a few basic requirements:
- File type:
.csvonly. - Header row: The first row must contain column names (headers). The importer uses these for mapping.
- Encoding: UTF-8 is recommended. Files saved as Windows-1252 (the Excel-on-Windows default) also work. UTF-16 is not supported — if your export is UTF-16, re-save it as UTF-8 first.
- Delimiter: Auto-detected. Commas, semicolons, tabs, and pipes (
|) are all recognized, so European-style semicolon CSVs work out of the box.
Limits
| Limit | Value |
|---|---|
| Maximum file size | 10 MB per file |
| Maximum files per import | 10 files (uploaded together) |
| Maximum rows per file | 500,000 data rows (excluding the header) |
| Saved mapping profiles | Up to 100 per workspace |
💡If your export is larger than 10 MB or 500,000 rows, split it into multiple files and upload them together (up to 10 at a time). Each file can have its own column mapping.
How to import, step by step
The importer is a simple 3-step wizard: Upload → Map data → Review.
Step 1 — Upload CSV file
- Open the importer (Settings → Data import → Universal CSV Importer → Open importer).
- Drag and drop your CSV files into the upload area, or click Choose files. You can add up to 10 files (10 MB each).
- Each uploaded file is listed with its column count. Remove any file with the trash icon.
- Click Next.
Step 2 — Map data
This is where you tell Toggl what each column means.
- Pick what you're importing. Choose a data type card: Members, Projects, Tasks, or Time entries. (Clients and tags don't have their own card — clients come from a separate client column in your file, shown in the example below, and tags are added on the Tasks card by mapping a column that lists each task's tags, split into multiple tags by a separator you choose (comma or semicolon)).
- Match columns to Toggl fields. For each Toggl field, choose the matching column from your CSV using the dropdown. The importer auto-detects common columns (e.g. "Project name", "Customer", "Duration", "Email") to get you started — review and adjust as needed. Sample values from your file are shown to help you confirm each match.
- Required vs. optional fields. Required fields are shown first; optional fields are tucked under More properties. You can't continue until every required field is mapped.
- Set formats for dates and durations where relevant (see Dates & durations below).
- Click Save & continue. A green check appears on each data type you've mapped.
|
Project
|
Client
|
Billable
|
|---|---|---|
|
Website Redesign
|
Acme Inc
|
true
|
|
Mobile App
|
Globex
|
false
|
Map Project → name, Client → Client, and Billable → billable — this creates two projects, each linked to its client.
Step 3 — Review your import
- Check against your workspace. Click Check against workspace to preview — the importer compares your file to existing data and shows, per data type, how many rows will be created vs. matched, with a sample of rows. This catches typos and duplicates (e.g. Parlsey Health vs Parsley Health) before anything is written. Nothing is imported at this stage; re-run it if you change the mapping or import mode:
- Pick an import mode:
- Create missing projects, tasks & clients — anything that doesn't exist yet is created and imported.
- Match existing only — rows are matched against existing clients, projects, tasks, and members; anything that can't be matched (and any time entries that depend on it) is skipped, and nothing new is created.
- Click Import. The import runs in the background and you'll see a progress screen, then a completion summary (Created / Skipped / Failed).
🔒 Only one import can run at a time per workspace. If an import is already in progress, resume or cancel it before starting a new one.
Field reference (what you can map)
Below are the fields available for each data type. Required fields must be mapped; everything else is optional.
Clients
| Field | Required? | Notes |
|---|---|---|
| name | Yes | Client name |
| external_id | No | Your own reference ID (will not be mapped, used for deduplication) |
Projects
| Field | Required? | Notes |
|---|---|---|
| name | Yes | Project name |
| client | No | Links the project to a client (created if missing, in Create mode) |
| billable | No | true / false |
| external_id | No | Your own reference ID (will not be mapped, used for deduplication) |
Tasks
| Field | Required? | Notes |
|---|---|---|
| name | Yes | Task name |
| project / client / parent_task | No | Links the task to its project, client, or a parent task |
| assignee | No | A member (matched by email or name) |
| description | No | |
| estimated_minutes | No | Whole number of minutes |
| start_date / end_date | No | Dates (see formats below) |
| archived | No | true / false |
| billable | No | true / false |
| tags | No |
One column listing a task's tags; split into multiple tags by a separator (comma or semicolon). Each tag is created if missing and matched by name.
|
Tags
Tags aren't mapped on their own — you import them through the Tasks card by mapping a column that lists each task's tags. Put several tags in one cell separated by a comma or semicolon (pick which in the Separator control); the importer creates each tag (matching by name) and links it to the task.
Members
| Field | Required? | Notes |
|---|---|---|
| Yes | Used to invite/match the member | |
| name | No |
Time entries
| Field | Required? | Notes |
|---|---|---|
| duration or start + end | Yes (one of these) | You must map either a duration column, or both a start and an end column so the duration can be calculated. |
| start / end | Conditional | Date-times (see formats below) |
| task / project / client | No | Links the entry to its task, project, client |
| user | No | The member the entry belongs to |
| description | No | |
| billable | No | true / false |
💡If a time entry has a date but no time of day, you can set a Default time in the mapping step — it's used to fill in the missing time (defaults to 09:00 if not set).
Custom fields
- Supported types: text, number, date, checkbox, single-select, multi-select, and user fields.
- Formatting: numbers must be numeric, dates use your chosen date format, and checkboxes accept true / false.
- Options & people: single- and multi-select values match the field's existing options by name; user fields match members by email.
- List values: multi-select and user fields accept several values in one cell, split by a separator (comma or semicolon) — same as tags.
- Any value that can't be parsed or matched (e.g. an unknown option) is skipped with a warning, and the rest of the row still imports.
Dates & durations
Supported date formats
Choose the format that matches your file (set per file or per column):
YYYY-MM-DDMM/DD/YYYYDD/MM/YYYYDD.MM.YYYYYYYY/MM/DD
For time entry start/end, date-time values are also accepted (e.g. 2026-06-30 14:30, 2026-06-30T14:30:00, ISO 8601).
Supported duration formats
- Decimal hours — e.g.
2.5= 2 hours 30 minutes (default) - HH:MM:SS — e.g.
1:30:00 - Minutes — e.g.
90
💡A decimal comma (e.g. 2,5) is accepted as well as a decimal point. Negative durations are not allowed.
How matching works (avoiding duplicates)
When you import, Toggl decides for each row whether to create something new or match an existing record:
- Records are matched by name (members are matched by email).
- Relationships are part of the match, not just the name. A record only counts as a duplicate when its parent relationships match too: a project matches an existing project only if it has the same client, and a task matches only if it has the same project and parent task. So two tasks named "Design" under different projects stay separate, and a "Website" project under Acme won't collide with a "Website" project under Globex. (Clients and tags are top-level, so they match on name alone.)
- When a same-named record with matching relationships already exists, the importer reuses it instead of creating a duplicate.
- You can mark a column with "Use this column to match existing records" to control which value is used for matching.
- Choosing Match existing only in the Review step guarantees nothing new is created — unmatched rows (and their time entries) are skipped instead.
ℹ️ Matching for clients and projects is exact (case- and spacing-sensitive); tasks match case- and spacing-insensitively. Re-importing the same file is safe — already-imported records are matched rather than duplicated.
Saving and reusing mappings (mapping profiles)
If you import from the same source regularly (e.g. a monthly Harvest export), you can save your column mapping as a profile and reuse it next time — no re-mapping needed.
- Save: In the Review step, click Save profile on a file. Give it a name (e.g. "Harvest time entries") and an optional Source product label (e.g. Harvest, Clockify, ClickUp).
- Reuse: On the mapping step, pick a saved profile from Apply mapping profile. It applies to files whose columns match the saved layout.
- Reset / delete: Use the reset icon to go back to the auto-detected mapping, or delete a profile you no longer need.
You can save up to 100 profiles per workspace.
FAQ
- Is there a template or format I have to follow? No fixed template. Any CSV works as long as it has a header row and uses a supported encoding/delimiter. You map your columns to Toggl fields during import.
- Is there a limit to the file size or number of rows? Yes — 10 MB per file, up to 10 files per import, and 500,000 rows per file. For larger data, split it into multiple files and upload them together.
- Can I import from Harvest, Clockify, ClickUp, Asana, or Teamwork? Yes. The importer works with CSV exports from any of these tools — and any other tool — because you map the columns yourself. There are no fixed, tool-specific templates; the named tools are just common examples.
- Can I import custom field values? Not yet. The importer currently supports clients, projects, tasks, tags, members, and time entries. Custom field import is planned for the future.
- Will it create duplicates if I import the same data twice? No. Records are matched by name (members by email), so re-imports reuse existing records instead of duplicating them. You can also use Match existing only mode to ensure nothing new is created.
- My file won't upload or shows garbled characters — what's wrong? Make sure the file is a
.csvunder 10 MB with a header row, and saved as UTF-8 (UTF-16 isn't supported). If special characters look wrong, re-save the file as UTF-8 from your spreadsheet tool and re-upload.