Skip to main contentGBOSSTABTime and Billing

Importing clients from a spreadsheet

Clients and projectsThe three-step CSV/TSV wizard.

Importing clients from a spreadsheet

If you're coming from QuickBooks, Xero, an older practice tool, or just a maintained spreadsheet, you don't have to re-key your client list. The importer reads your file, suggests a column mapping, and brings everyone in. Re-running the same file the next month is safe, the dedupe step catches anything you've already imported.

Supported formats

  • .csv, comma-separated.
  • .tsv, tab-separated.
  • .txt, treated the same as CSV/TSV (delimiter auto-detected).

.xlsx (Excel) is not supported yet. The wizard explicitly rejects Excel files: "Only CSV/TSV/text files are supported in Pass 1. Excel support is coming." Export to CSV from Excel first.

Files larger than 10 MB are rejected with a friendly error. Split a giant file or contact support.

Step 1, Upload

  1. Open Clients from the top nav.
  2. Click Import at the top right (it's enabled even when New client is disabled).
  3. Drag your file onto the drop zone, or click to browse.
  4. The wizard parses the file and shows a preview underneath: the headers it found, the first few sample rows, and the total row count.
  5. Click Next to advance to mapping. (If there's nothing to upload yet, a Download template CSV link is available, start from that for a fresh import.)

Step 2, Map columns

Each header in your file gets a row in a mapping table, with a sample value from your data and a dropdown that picks where the column should go in TAB. The wizard pre-fills the dropdowns based on header names ("Customer Name" → Name, "QB ID" → External ID, and so on).

Available target fields:

  • Name (required), at least one column must map to Name.
  • External ID
  • Email (billing_email)
  • Phone (primary_phone)
  • Address (billing_address)
  • Default rate (USD or cents)
  • Notes
  • , Merge into Notes, concatenates the column's value onto whatever's already in Notes, useful for "second address line" or "comments" fields.
  • , Skip column, ignore this column.

Underneath the mapping table is a Deduplication section with two choices:

  • By External ID, best when your file has a stable ID column. The importer looks up each row by ID; found = update, not found = create.
  • By Name + Email, fallback when you don't have IDs. A row matches an existing client only when both name and email line up.

A preview table below shows the first sample rows with the active mapping applied, columns mapped to Skip are dimmed.

You can run a Dry run before committing, same import logic but no DB writes. The result banner shows the counts you'd get ("Would create N, update N, skip N, errors N") so you can sanity-check before pulling the trigger.

The Import N clients button stays disabled until at least one column is mapped to Name.

Step 3, Review

After a real (non-dry) commit, the wizard advances to step 3 with four big counters:

  • Created, new client rows added.
  • Updated, existing clients matched and refreshed with the new data.
  • Skipped, rows the importer chose not to touch (most often because Name was empty).
  • Errors, rows that hit a problem.

A collapsible N issues section underneath lists each one by row number with a one-line reason. The first 50 issues are shown; if there are more, the rest are summarised as "… and N more".

From here you can Import another file or jump to the Clients list to see the results.

Safe to re-run

The importer is idempotent: pointing it at the same file twice doesn't create duplicates. If your old system gives you a fresh export every month, import the whole file every time, you'll get updates for changed clients and new rows for new clients.

Related