Skip to content

Request an integration

Tell us which system you want to connect. We review every request weekly and publish a step-by-step guide or build the connection.

Importing from Toggl, Clockify, TimeChimp and Harvest

Import time entries from Toggl Track, Clockify, TimeChimp and Harvest CSV exports: recognised columns, date and duration formats, matching to people and placements, dry run, person mapping and POST /import/time-entries.

Last updated: · Markdown version

Switching tools should not cost you your history. Export the detailed time report from your current tracker as CSV and import it. Every entry becomes a claim with source import (see sources and conflicts); entries are summed per placement per day, like every other source.

Ways to run it:

  • Dashboard: "Importeren" → tab "Uren uit Toggl, Clockify, TimeChimp of Harvest". Upload (.csv or .xlsx), check the review, link unknown people, then "Importeer".
  • API: POST /import/time-entries {csv, provider?, dryRun, personMap?} (write key). See the API reference.

Recognised exports

The provider is detected from the header row; pass provider to force it. Headers are compared case-insensitively, ignoring spaces and punctuation (Duration (h) = durationh).

Provider Export Columns used
Toggl Track (toggl) Reports → Detailed → Export CSV User/Member, Email, Client, Project, Task, Description, Start date, Start time, End time/Stop time, Duration (hh:mm:ss)
Clockify (clockify) Reports → Detailed → Export CSV User, Email, Client, Project, Task, Description, Start Date, Start Time, End Time, Duration (h) (hh:mm:ss) or Duration (decimal)
Harvest (harvest) Reports → Detailed time → Export CSV Date, Client, Project, Task, Notes, Hours (decimal), First Name, Last Name; Started At/Ended At when timestamp timers are on
TimeChimp (timechimp) Uren → Exporteren Dutch or English: Datum/Date, Medewerker/Employee/User, E-mailadres/Email, Klant/Customer, Project, Taak/Task, Opmerking/Notes, Starttijd/Start, Eindtijd/End, Uren/Hours (decimal) or Duur

TimeChimp export templates vary per account, so its columns are matched by alias. If your file is not recognised, rename the headers to one of the names above. The mapping lives in @tt/core (IMPORT_PROVIDERS) as data, with fixture files and tests per provider.

Unused columns (billable, rates, tags) are listed in unmappedHeaders. Amounts are never imported.

Values

  • Dates: YYYY-MM-DD, DD-MM-YYYY, DD.MM.YYYY and slashed dates. For slashed dates the file decides: a first part above 12 means day/month, a second part above 12 means month/day. Otherwise Clockify defaults to month/day (its US default) and the others to day/month.
  • Times: 08:00, 08:00:00, 12-hour 08:00:00 PM, or ISO timestamps (the local clock time is kept).
  • Durations: hh:mm(:ss) (seconds round to the nearest minute; hours may exceed 24 in totals) or decimal hours (7.5, 7,50). Without a duration, minutes come from start and end (overnight when end ≤ start). Entries of 0 minutes or over 24 hours are rejected.

Matching

  1. Person: the explicit mapping from the review (personMap), else the e-mail address, else the full name (accents, case and punctuation ignored; ambiguous names do not match).
  2. Placement: the person's active placement on that date. With several, the one whose client name (or placement reference) equals the entry's client or project. A single placement is used even if the client name differs; the review then notes opdrachtgever "X" ≠ Y.
  3. Day: entries are summed per placement per date. Clock times are kept when all entries of the day have them: earliest start, latest end, and the gaps become the break.

Rows that do not match are listed in unmatched with a reason (Medewerker niet gevonden, Geen actieve plaatsing op deze datum, Meerdere plaatsingen; opdrachtgever niet herkend) and are skipped. Unknown people are also listed in unknownPeople; pass personMap: { "<key>": "<personId>" } and run the dry run again.

Dry run, commit and re-imports

  • dryRun defaults to true and changes nothing. Each day gets a status: new, duplicate (already imported), locked (the day is exported or locked: book a correction in an open period) or error.
  • With dryRun: false, new days are stored through the normal claim path (permission check, matching, conflicts, claim.created webhook) and become imported.
  • Claim ids are derived from the content (org, provider, placement, date, minutes, times), so importing the same export twice creates no duplicates. A changed entry is a new claim; the newest claim per source wins.
  • Imported hours start as draft. When the worker also logged the day in the app, a difference becomes a normal conflict.
  • Up to 20,000 entries (5 MB) per request.