---
title: "Teamleader to Nutshell Migration: A Technical Guide"
slug: teamleader-to-nutshell-migration-a-technical-guide
date: 2026-08-18
author: Abdul
categories: [Migration Guide, CRM]
excerpt: "Technical guide to migrating from Teamleader Focus to Nutshell. Covers API constraints, data mapping, activity history, custom fields, and edge cases."
tldr: "Teamleader to Nutshell is a data-model reduction: CRM data maps directly, but invoices, projects, and tickets have no Nutshell target. Activity history requires API-to-API migration."
canonical: https://clonepartner.com/blog/teamleader-to-nutshell-migration-a-technical-guide/
---

# Teamleader to Nutshell Migration: A Technical Guide


# Teamleader to Nutshell Migration: A Technical Guide

Migrating from Teamleader Focus to Nutshell is a data-model reduction problem. Teamleader is an **all-in-one European business platform** — CRM, invoicing, project management, quotations, tickets, and time tracking in a single product. Nutshell is a **B2B sales-focused CRM** built around Companies, People, and Leads with pipeline management, email automation, and reporting. Nutshell has no native invoicing, no project module, and no ticketing system.

That mismatch means you cannot migrate everything. Teamleader Deals translate to Nutshell Leads, and Companies/Contacts map directly, but Projects, Invoices, Quotations, Subscriptions, and Tickets have no target in Nutshell. A naive CSV export will also silently drop activity history — Teamleader's backup feature explicitly excludes activity tracking data, and Nutshell's CSV import cannot create Activities. If timeline history matters, you need API-level extraction on the Teamleader side and API-level loading on the Nutshell side.

This guide covers the structural mismatch between the two platforms, API and CSV constraints on both sides, every viable migration method with honest trade-offs, field-level data mapping, and the edge cases that silently corrupt data. For a broader pre-migration framework, see our [CRM data migration checklist](https://clonepartner.com/blog/blog/the-ultimate-crm-data-migration-checklist-a-10-point-plan-for-a-zero-loss-transition/).

> **Last verified:** API v2 endpoints and import limits confirmed against Teamleader Focus and Nutshell documentation. Verify rate limits and field caps against live headers during your dry run, as these can change without notice.

## Why Teams Move from Teamleader to Nutshell

The migration drivers typically fall into three categories:

- **Outgrowing the European-only ecosystem.** Teamleader Focus is a Belgian platform (owned by Visma since 2022) built primarily for European SMBs. Teams expanding into US or global markets often find Nutshell's North American integrations, English-first support, and US-based infrastructure a better fit.
- **CRM depth vs. breadth trade-off.** Teamleader bundles CRM, invoicing, project management, and ticketing — but the CRM portion has limited pipeline automation and customization. Nutshell offers deeper sales automation, custom pipelines, and more flexible reporting within a pure-CRM scope.
- **Contact limits.** Teamleader's default limit is 10,000 contacts and companies combined, with a hard ceiling of 200,000. Nutshell includes unlimited CRM contacts on every plan. ([support.focus.teamleader.eu](https://support.focus.teamleader.eu/hc/en-150/articles/25691237031697-What-are-the-limits-for-files-custom-fields-quotations-invoices-and-timesheets-in-Teamleader-Focus))

## Teamleader vs. Nutshell: Data Model Comparison

Understanding the structural mismatch is the foundation of any migration plan. Here is how the core objects map:

| Teamleader Focus | Nutshell | Migration Notes |
|---|---|---|
| **Companies** | **Companies** | Direct map. Addresses, tags, custom fields transfer. |
| **Contacts** | **People** | Direct map. Linked to Companies in both systems. |
| **Deals** | **Leads** | Conceptual match, but field structures differ significantly. |
| **Deal Phases** | **Pipeline Stages** | Must pre-create pipelines and stages in Nutshell before import. |
| **Projects** | ❌ No equivalent | Archive or export to a project tool. |
| **Invoices** | ❌ No equivalent | Export to accounting software separately. |
| **Quotations** | ❌ No equivalent | Archive as PDFs or structured data. |
| **Tickets** | ❌ No equivalent | Migrate to a helpdesk tool, not Nutshell. |
| **Events/Calls** | **Activities** | Must use API. Cannot CSV-import activities into Nutshell. |
| **Tasks (Todos)** | **Tasks** | API-only on the Nutshell side for creation. |
| **Custom Fields** | **Custom Fields** | Max 50 per object in Teamleader. Type mapping required. |
| **Tags** | **Tags** | Direct map. Create in Nutshell before import. |
| **Products** | **Products** | Can import via Nutshell's product importer. |

> [!WARNING]
> Teamleader's backup feature does **not** export activity/tracking data, article lines on quotations/invoices, uploaded files, or generated PDFs. If you rely on the built-in backup for extraction, you will lose interaction history silently.

## Migration Method Decision Matrix

Before diving into technical details, use this matrix to select the right method for your situation:

| Method | Record Volume | History Fidelity | Technical Effort | Data Loss Risk | Approx. Time |
|---|---|---|---|---|---|
| **CSV Only** | <2,000 | Low (0/3) — no activity history | Low (1/5) | High — activities, relationships, 11+ custom fields silently lost | 2–5 days |
| **API-to-API** | Any | High (3/3) — full history possible | High (5/5) | Low — most edge cases addressable in code | 1–3 weeks |
| **Hybrid (CSV + API)** | 2,000–15,000 | Medium (2/3) — bulk records via CSV, history via API | Medium (3/5) | Medium — join key discipline required | 1–2 weeks |
| **iPaaS (Zapier/Make)** | <500 ongoing | Low (1/3) — no historical trigger | Very Low (1/5) | High — no historical export trigger available | Hours setup, linear cost |

**How thresholds were determined:** The 2,000-record threshold for CSV-only is driven by the practical deduplication burden — above this, manual review of duplicate emails and name mismatches becomes the primary time sink, not the import itself. The 15,000-record ceiling for hybrid is driven by Nutshell's 32MB CSV cap and the overhead of maintaining a reliable join key between two separate load phases when records exceed several hundred pages of API pagination.

## API Constraints

Both platforms have specific constraints that shape your migration architecture. Understanding these up front prevents you from building an extraction pipeline that stalls halfway through.

### Teamleader Focus API v2

Teamleader's API v2 uses an HTTP RPC-style pattern — all requests are `POST` to `https://api.focus.teamleader.eu/resource.action` with JSON payloads. Teamleader API v1 has been deprecated; all new integrations must use v2. ([developer.focus.teamleader.eu](https://developer.focus.teamleader.eu/docs/authentication?utm_source=openai))

**Authentication:** OAuth2 only. Your migration app must be registered on the Teamleader Marketplace (it can remain private). You receive an access token and refresh token flow. Access tokens expire, and refresh tokens are single-use — your script must handle token refresh cycles mid-extraction, especially for large datasets that take hours to pull.

**Rate limits:** The V2 API enforces a **sliding window** rate limit of approximately **200 requests per minute** per integration per Teamleader account. The API returns `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers on every response. When you hit `429 Too Many Requests`, your script must wait until the oldest request in the current window expires. Verify the live headers during your dry run, as tenant-level limits may differ.

**Pagination:** List endpoints like `contacts.list` and `deals.list` use `page [size]` (maximum 100) and `page [number]` parameters. You must loop through pages sequentially.

**Data hydration:** The `.list` endpoints return shallow objects. To get custom fields or linked entities, you often need to call the `.info` endpoint for individual records, which rapidly consumes your rate limit. Teamleader's docs recommend using `.list` endpoints with entity ID filters instead of individual `.info` calls wherever possible.

**Key extraction endpoints:**

```
POST /contacts.list               → paginated contact list
POST /contacts.info               → single contact with full detail
POST /companies.list              → paginated company list
POST /companies.info              → single company with full detail
POST /deals.list                  → paginated deal list
POST /deals.info                  → single deal with phases, custom fields
POST /events.list                 → calendar events (activities)
POST /tasks.list                  → todos/tasks
POST /customFieldDefinitions.list → custom field schema
POST /tags.list                   → all tags
POST /users.list                  → team members (for assignee mapping)
```

**Webhook event types:** Teamleader fires webhooks on `contact.created`, `contact.updated`, `contact.deleted`, `company.created`, `company.updated`, `deal.created`, `deal.updated`, and `deal.deleted`. These are the events relevant to delta sync. Webhook payloads include the entity type, entity ID, and timestamp — not the full record, so you must re-fetch the record from the API on receipt. Webhooks are reliable for low-volume delta catches but should not be your sole sync mechanism for high-velocity migration windows.

**Practical extraction throughput:** At 200 requests/minute, extracting 10,000 contacts via `contacts.list` with page size 100 requires 100 list requests — approximately 30 seconds of raw list time. But fetching full detail via `contacts.info` for each record adds 10,000 individual calls, consuming roughly 50 minutes at the rate limit ceiling. A 10,000-contact account with full relationship data typically requires 500–1,500 API calls on the Teamleader side — 3–8 minutes of raw extraction time before transformation. Plan accordingly when scoping extraction windows.

> [!CAUTION]
> **Destructive collection updates:** When updating records via the Teamleader API, collections (tags, custom fields, addresses) are **replaced entirely**. If you read a contact, modify one tag, and write back without including all existing tags, you wipe the others. This matters during retries, dry runs, and any write-back or delta sync against Teamleader during migration. Treat every update script as destructive until you prove otherwise in a sandbox. ([github.com](https://github.com/teamleadercrm/api/blob/master/apiary.apib))

### Nutshell API

Nutshell offers two APIs: a **REST API** and a **JSON-RPC API** (legacy, maintained indefinitely according to Nutshell's documentation). Both are available on all Nutshell plans. For more context on handling Nutshell's API constraints and relational data model, see our [Nutshell to GoHighLevel migration guide](https://clonepartner.com/blog/blog/nutshell-to-gohighlevel-migration-guide-2026/).

**Authentication:** HTTP Basic Auth using your Nutshell email as the username and an API key as the password. API keys are generated from your Nutshell account settings — simpler than Teamleader's OAuth flow.

**JSON-RPC endpoint structure:** All JSON-RPC requests are POSTed to a single endpoint (e.g., `https://app.nutshell.com/api/v1/json`) with the method specified in the JSON body. You can batch multiple operations into a single HTTP request by sending an array of JSON-RPC objects — Nutshell processes each operation in the batch independently. If one operation in a batch fails, the others still execute; you must check each response object individually for errors. Recommended batch size is 10–25 operations per request to balance throughput against partial-failure complexity.

**Rate limits:** Nutshell does not publish a fixed requests-per-minute number. Rate limits are applied most aggressively to large `find*` requests with non-stub responses. Individual `get*` and write operations are throttled less aggressively. Implement exponential backoff with jitter — start at 1 second, double on each `429`, cap at 60 seconds.

**Timestamp handling:** By default, creating a note or activity via the API sets the creation date to *now*. To preserve historical timelines from Teamleader, you must explicitly pass the original timestamps in your payload. If you skip this, every interaction from the last five years will appear as if it happened on migration day — a problem that is invisible in record counts and only discovered by users reviewing timelines.

**Key write endpoints (JSON-RPC):**

```
newAccount    → create a company
editAccount   → update a company
newContact    → create a person
editContact   → update a person
newLead       → create a lead (requires linked account/contact)
editLead      → update a lead
newNote       → add a note to a lead, contact, or account
newActivity   → create an activity (calendar event)
newTask       → create a task
```

**Rollback and recovery:** Nutshell does not expose a bulk-delete API endpoint. If a load run creates corrupt or duplicate records, you must either delete them individually via the API (`deleteAccount`, `deleteContact`, `deleteLead`) or use Nutshell's in-app bulk-select delete. For large-scale bad loads (>1,000 records), contact Nutshell support — they can restore from a database snapshot within a limited window after account creation. **Test in a Nutshell trial account before writing to production.** There is no undo for a production bulk load.

### CSV Import Constraints

If you are considering a CSV-based migration, know the limits on both sides:

- **Teamleader export limits:** Excel exports cap at **50,000 records**. The in-app export allows a maximum of **50 fields per export template**. Import files are limited to 5 MB, 35,000 lines, and 200 columns. ([support.focus.teamleader.eu](https://support.focus.teamleader.eu/hc/en-150/articles/25691237031697-What-are-the-limits-for-files-custom-fields-quotations-invoices-and-timesheets-in-Teamleader-Focus))
- **Nutshell CSV import:** Files must be **UTF-8 encoded** and under **32 MB**. You can import Companies, People, and Leads. Activities **cannot** be imported via CSV — they can only be created manually or through the API. Custom field names must exactly match pre-configured fields in Nutshell. Duplicate detection supports matching by email, full name, Legacy ID, or Nutshell ID. ([support.nutshell.com](https://support.nutshell.com/en/articles/8429035-import-data-you-can-import-into-nutshell))

> [!WARNING]
> Nutshell's documentation shows inconsistent date format recommendations — one import article recommends **MM-DD-YYYY**, while the best-practices page recommends **YYYY-MM-DD**. Test with a small sample before the full run and normalize every date column to one format. ([support.nutshell.com](https://support.nutshell.com/en/articles/8429035-import-data-you-can-import-into-nutshell))

## Migration Methods: Trade-offs

### Method 1: CSV Export → CSV Import

Export Companies, Contacts, and Deals from Teamleader as CSV/Excel files. Clean and transform them. Import into Nutshell using their CSV import wizard.

**What you get:** Company and Contact records with standard fields, Deal data mapped to Leads, tags and basic custom fields.

**What you lose:** All activity and interaction history (Teamleader's export excludes it). Relationship links are flattened into separate files — you must reconstruct them during import. Custom fields beyond the first 10 per module in Teamleader's backup (sorted alphabetically; field 11 onward is silently dropped). Files and attachments. Structured deal phase history.

**Failure modes specific to this method:** Duplicate emails in the source data (common — roughly 8–12% of Teamleader contact exports contain at least one duplicate email address) will import as separate records unless you deduplicate before loading. Company-contact link failures are silent — if a contact's company reference does not exactly match an existing company name, Nutshell creates the person unlinked, with no error.

**Best for:** Small accounts (<2,000 records) where interaction history is not business-critical.

**Effort estimate:** 2–5 days for data cleaning, field mapping, and staged import.

### Method 2: API-to-API (Custom ETL Pipeline)

Build a custom extraction-transform-load script that reads from Teamleader's API, transforms the data model, and writes to Nutshell's API.

**What you get:** Full Company, Contact, and Deal data with all custom fields. Activity and event history via `events.list`. Notes, tasks, and tags. Preserved Company→Contact→Lead relationships. Assignee/owner mapping with user ID translation.

**What you still lose:** Invoices, projects, quotations, and tickets have no Nutshell target. File attachments require separate download-and-reupload handling.

**Error handling:** Implement per-record error logging with the Teamleader source UUID, the attempted operation, and the API response. On a 5xx from Nutshell, retry with exponential backoff (1s → 2s → 4s → 8s → cap at 60s). On a 4xx, log and skip — do not retry, as the error is in your payload, not Nutshell's server. After load completion, reconcile your error log against expected record counts to identify gaps requiring manual resolution.

**Best for:** Any migration where activity history, relationship integrity, or custom field completeness matters. This is the recommended path for most production migrations.

**Effort estimate:** 1–3 weeks for development, testing, and staged rollout.

### Method 3: Hybrid (CSV Bulk + API for History)

Export Companies and Contacts via CSV for the initial bulk load. Then use a targeted API script to backfill activity history, notes, tasks, and deal data.

**The key requirement:** You need a reliable matching key to link API-loaded data to CSV-imported records. Include the Teamleader UUID as a **Legacy ID** column in your CSV so the API script can look up records by that identifier in Nutshell. Without this join key, backfill scripts have no reliable way to associate historical events with the correct Nutshell record — name and email matching introduce ambiguity that compounds across thousands of records.

**Best for:** Mid-size accounts (2,000–15,000 records) where contact/company data is relatively clean but activity history is important.

### Method 4: iPaaS (Zapier, Make, n8n)

Integration platforms work record-by-record and are designed for ongoing sync, not bulk migration. Zapier's Teamleader triggers are limited to new/updated records — you cannot trigger a full historical export. Execution costs scale linearly with record count (at Zapier's task pricing, a 10,000-record migration can cost $50–200 in task consumption alone, depending on your plan).

**Best for:** Small ongoing syncs or post-migration delta catches, not the primary migration method.

## Field-Level Data Mapping

### Companies

| Teamleader Field | Nutshell Field | Notes |
|---|---|---|
| `name` | Company Name | Direct |
| `emails [].email` | Email | Nutshell supports multiple |
| `telephones [].number` | Phone | Map by type (work, mobile) |
| `addresses []` | Address | Break into street, city, state, zip, country |
| `website` | URL | Direct |
| `tags []` | Tags | Pre-create in Nutshell |
| `custom_fields []` | Custom Fields | Type-match: text→text, number→number, date→date |
| `responsible_user.id` | Account Owner | Map Teamleader user IDs to Nutshell user names |
| `vat_number` | Custom Field | No native VAT field in Nutshell |
| `business_type` | Industry | Map to Nutshell industries or custom field |

Store the Teamleader company UUID in Nutshell's **Legacy ID** field or a dedicated custom field so you can rerun imports without creating duplicates. Teamleader does not let you export company details and linked contact details together in one file — plan a join step or extract them separately. ([support.nutshell.com](https://support.nutshell.com/en/articles/8429035-import-data-you-can-import-into-nutshell))

### Contacts → People

| Teamleader Field | Nutshell Field | Notes |
|---|---|---|
| `first_name` | First Name | Direct |
| `last_name` | Last Name | Direct |
| `emails [].email` | Email | Primary + additional |
| `telephones [].number` | Phone | Map by type |
| `function` | Job Title | Direct |
| `company.id` | Company link | Must resolve to Nutshell Company ID |
| `tags []` | Tags | Pre-create in Nutshell |
| `custom_fields []` | Custom Fields | Same type-matching rules |

Teamleader's contact-company link can carry a `position` and `decision_maker` flag. Nutshell can import Job Title, but only when the person is already associated with a company during import. The decision-maker flag has no native Nutshell equivalent — create it as a custom field if your sales team filters on it. ([developer.focus.teamleader.eu](https://developer.focus.teamleader.eu/docs/api/contacts-update-company-link?utm_source=openai))

### Deals → Leads

| Teamleader Field | Nutshell Field | Notes |
|---|---|---|
| `title` | Lead Name | Direct |
| `estimated_value.amount` | Value | Map currency if multi-currency |
| `estimated_closing_date` | Expected Close Date | Direct |
| `current_phase.name` | Pipeline Stage | Must pre-create pipeline and stages |
| `responsible_user.id` | Assignee | Map to Nutshell user names |
| `company.id` | Related Company | Must resolve to Nutshell Company ID |
| `contact.id` | Related Person | Must resolve to Nutshell Person ID |
| `source.name` | Lead Source | Map or create in Nutshell |
| `custom_fields []` | Custom Fields | Type-match required |
| `lost_reason` | Lead Outcome | Map to won/lost/cancelled status |

**Status mapping:** Teamleader deals are `open`, `won`, or `lost`. Nutshell lead statuses include `Pending`, `Open`, `Won`, `Lost`, and `Cancelled`. Map explicitly so you do not accidentally reopen years of closed deals.

**Product gotcha:** If you import a lead value into Nutshell without a product name, Nutshell will create a product called "Imported product." Migrate your product catalog first, then link products to Leads by ID.

> [!TIP]
> Teamleader deals can have multiple deal phases with timestamps (phase history). Nutshell leads track stage progression natively, but you can only set the **current** stage during import. If phase history matters, append it as a structured note on the Lead with the format: `[Phase History] Phase: {name} | Entered: {date} | Exited: {date}`.

## Custom Field Migration

Custom fields are where most migrations silently lose data.

**Teamleader custom field types:** text, textarea, number, money, date, single-select, multi-select, boolean. Hard limit of **50 custom fields per object**.

**Nutshell importable types:** text, long text, number, decision (boolean), date, and currency.

**Mapping gotchas:**

- **Multi-select fields** in Teamleader have no direct Nutshell CSV import equivalent. Convert to comma-separated text, or use the API to write individual values.
- **Money fields** in Teamleader include a currency code. Nutshell's currency fields may need normalization.
- Teamleader's backup only exports the **first 10 custom fields per module, sorted alphabetically**. Field 11 onward is silently dropped with no error message. If you have 30 custom fields on Companies, you lose 20 unless you create a custom export template.
- The in-app export supports up to **50 fields per template**. If you have objects with more than 50 fields (standard + custom), you need multiple export passes and a join step.
- Custom field **IDs** in Teamleader are UUIDs. Call `customFieldDefinitions.list` to get the mapping between IDs and human-readable names before extraction.
- Single- and multi-select picklists can have many options in Teamleader, but only **250 options** can be imported into a single Nutshell field.
- Nutshell custom field names are case-sensitive during CSV import. A field named "Deal Region" in Nutshell settings will not match "deal region" in your import file — the value will be silently ignored.

## Handling Activity History

This is the single most common data loss point in Teamleader-to-Nutshell migrations.

**The problem:** Teamleader's built-in backup and CSV export do not include activity/tracking data. On the Nutshell side, activities cannot be imported via CSV — they can only be created manually or through the API. If you rely on CSV alone, your entire interaction history disappears. This is invisible in record counts: you can have a 100% record match on Companies, People, and Leads while silently losing every call log, meeting note, and email record in the system.

**The API solution:**

1. **Extract** via Teamleader API: Use `events.list` with date range filters to pull all calendar events, calls, and meetings. Each event includes participants, type, date/time, and linked entities.
2. **Transform:** Map Teamleader event types to Nutshell activity types. Resolve participant IDs to Nutshell People/Company IDs using your ID mapping table.
3. **Load** via Nutshell API: Use `newActivity` (JSON-RPC) to create activities linked to the correct contacts and leads. Pass original timestamps explicitly in the payload — if omitted, all activities will be dated to migration day.

**Fallback — notes instead of activities:** If the API approach is too complex for your timeline, import activities as notes attached to the relevant Company, Person, or Lead. You lose calendar and scheduling metadata, but the interaction record appears in the Nutshell timeline. Format each note with the activity type, date, participants, and description:

```python
# Convert Teamleader event to Nutshell note
note_body = f"""[Migrated Activity]
Type: {event['type']}
Date: {event['started_at']}
Participants: {', '.join(p['name'] for p in event['participants'])}
Description: {event.get('description', 'N/A')}
"""
```

Make this decision early. Do not wait until cutover week to determine how much timeline history your team actually needs.

## Deduplication Strategy

Duplicates are the second most common migration failure mode. In practice, roughly 8–12% of Teamleader contact exports contain at least one duplicate email address — Teamleader does not enforce email uniqueness at the database level. Nutshell's API will blindly create duplicates if you send identical payloads. Nutshell's CSV import offers duplicate matching by email, full name, Legacy ID, or Nutshell ID, but if your Teamleader data already contains duplicates, Nutshell will import them as separate records.

**Pre-migration dedup process:**

1. Export all contacts and companies from Teamleader
2. Check for duplicate emails, phone numbers, and company names
3. Merge or flag duplicates **before** loading into Nutshell
4. Use the Teamleader UUID as a **Legacy ID** in Nutshell so every record has a unique, traceable identifier
5. During Nutshell CSV import, set duplicate matching to email address for People and name matching for Companies
6. For API-based loading, use email as the primary key for People and domain name for Companies — if a conflict is found, update the existing record (`editContact` or `editAccount`) rather than creating a new one

Keep three identifiers on every record throughout the project: the Teamleader source UUID, the transformed import key, and the final Nutshell ID. That three-key chain is what makes reruns, deduplication analysis, and rollback targeting possible. Without it, a partial load failure requires manual triage across thousands of records.

## Migration Execution Plan

### Step 1: Audit and Scope

Inventory your Teamleader data: count of companies, contacts, deals, activities, custom fields, products, tags, and users. Identify what has a Nutshell target and what does not (projects, invoices, tickets). Decide the archival strategy for non-migratable data. Scope drift — discovered mid-migration — is the fastest way to turn a two-day import into a multi-week cleanup.

### Step 2: Pre-configure Nutshell

Before importing a single record:

- Create all **custom fields** with exact name matches (case-sensitive)
- Create **pipelines and stages** matching your Teamleader deal phases
- Create **tags** matching your Teamleader tags
- Set up **user accounts** for every team member (assignee mapping depends on this)
- Create **products** if you are migrating product data
- Configure **territories**, **industries**, and **lead sources**
- Enable **currencies** that appear in your Teamleader deal data

Stages and territories must exist before import. Owner names in CSV imports must match Nutshell user names exactly — "Jan De Vries" in Teamleader vs. "Jan de Vries" in Nutshell will cause the assignment to silently fail with no error in the import log. ([support.nutshell.com](https://support.nutshell.com/en/articles/8429036-import-best-practices-for-importing-data?utm_source=openai))

### Step 3: Sandbox Validation

Extract a 5% sample of your Teamleader data (stratified across record types, owners, and date ranges — not just the first 5% alphabetically) and push it into a Nutshell trial account. Have your sales leaders validate the mapping. Check pipelines, ensure notes are attached to the right people, and verify that historical dates are accurate. This step catches mapping errors that are invisible in data files but obvious the moment a user opens a record.

### Step 4: Extract from Teamleader

Use the API for completeness. Extract in this order:

1. Custom field definitions (to build your mapping table)
2. Users (for assignee mapping)
3. Tags
4. Companies (with all custom fields)
5. Contacts (with company links)
6. Deals (with phases, custom fields, linked companies/contacts)
7. Events/activities
8. Notes
9. Tasks

Store extracted data as JSON files with Teamleader UUIDs preserved. Confirm the exporting user has Teamleader's **Export** permission enabled before you begin. ([support.focus.teamleader.eu](https://support.focus.teamleader.eu/hc/en-150/articles/25691186210961-Create-an-Excel-export-in-Teamleader-Focus))

### Step 5: Transform

Build the ID mapping table (Teamleader UUID → Nutshell ID). Transform Teamleader's data model into Nutshell's schema. Handle type conversions, flatten multi-select fields, normalize phone numbers and addresses, strip HTML from background information fields, and resolve all entity cross-references. Log every transformation decision — you will need this when validating edge cases.

### Step 6: Load into Nutshell

Load in dependency order:

1. **Companies** first (no dependencies)
2. **People** second (link to Companies)
3. **Leads** third (link to Companies and People)
4. **Notes** (link to Companies, People, or Leads)
5. **Activities** (link to People, Companies, or Leads)
6. **Tasks** (link to Leads or People)

CSV import works for bulk Companies, People, and Leads if activity history is handled separately via API. Use the Nutshell API for activities, tasks, and any records that need relationship precision. Log every write operation with source UUID and Nutshell response ID.

### Step 7: Validate

Run record counts by object, owner, stage, and status. Spot-check 5–10% of records manually. Verify:

- Company→Person links are intact
- Lead values and stages are correct
- Custom field values transferred without truncation
- Activity timeline shows expected history with original dates
- Assignee/owner mapping is correct
- No "Imported product" ghost products exist

A record count can look perfect while relationship data is wrong. Open 10–20 random high-value accounts and confirm the right people, leads, notes, and owners are attached. Ask two or three sales reps to review their own records — they will spot anomalies that validation scripts miss.

### Step 8: Delta Sync and Cutover

If your team continues using Teamleader during migration, run delta syncs to catch records created or modified after the initial extraction. Use Teamleader's `updated_since` filter on `.list` endpoints. For cleaner delta sync windows, configure Teamleader webhooks on `contact.updated`, `company.updated`, and `deal.updated` events to queue changes for re-extraction rather than polling on a schedule. ([support.focus.teamleader.eu](https://support.focus.teamleader.eu/hc/en-150/articles/25691065794577-Getting-started-What-are-webhooks-in-Teamleader-Focus))

Continue delta syncs for 1–2 weeks after cutover. Then revoke user access to Teamleader, run one final delta sync, and route all new integrations (website forms, email routing) directly into Nutshell.

## Edge Cases That Break Migrations

- **Multi-currency mismatches:** Teamleader handles multi-currency deal values natively. Nutshell supports multiple currencies, but you must configure your base currency and enable market currencies in Nutshell settings before import. If your script pushes a deal with a currency code (e.g., `GBP`) that is not active in Nutshell, the API call will fail silently or with a generic error.
- **Backup custom field truncation:** Teamleader's backup only exports 10 custom fields per module, sorted alphabetically. Field 11 onward is silently dropped — this is not flagged as an error anywhere in the export interface.
- **Nutshell's 32MB CSV limit:** Large accounts need their CSV split into multiple files. Each file must include the header row, and all files must use the same column order.
- **Assignee name matching:** Nutshell matches lead assignees by exact user name string. If names differ by so much as a capital letter, the assignment silently fails.
- **Background info as HTML:** Teamleader background information is hidden from default exports and emitted as HTML when explicitly exported. Strip HTML tags before loading into Nutshell descriptions or notes. ([support.focus.teamleader.eu](https://support.focus.teamleader.eu/hc/en-150/articles/25693492944529-Export-the-background-information-of-contacts-companies))
- **File attachments:** Neither Teamleader's backup nor CSV exports include attached files. API extraction is possible but requires per-file download and re-upload, which is slow and should be handled in an asynchronous queue separate from your primary data load.
- **"Imported product" creation:** If you import a lead value into Nutshell without a product name, Nutshell creates a product called "Imported product." Migrate your product catalog first and verify product associations before loading leads.
- **People imported before companies:** If contacts are imported before their company links exist in Nutshell, the Job Title field never lands on the record. Always load Companies first. This dependency is not documented in Nutshell's import UI.
- **Nutshell JSON-RPC batch partial failures:** When batching multiple operations into one HTTP request, a failure in one operation does not roll back the others. Each batch response is an array — check every element for an `error` key, not just the HTTP status code.
- **Teamleader OAuth refresh token expiry:** Refresh tokens are single-use and expire after use. If your extraction script crashes mid-run and you restart it without generating a new refresh token, every API call will return 401. Build token refresh handling into your retry logic before the first extraction attempt.

## What You Lose No Matter What

Be explicit with stakeholders about data that cannot migrate to Nutshell under any method:

- **Invoices and payment history** — Nutshell has no invoicing module. Map high-level aggregates (lifetime value, last invoice date) to custom fields on the Company record, or export to your accounting platform.
- **Project plans, time tracking, and budgets** — No equivalent in Nutshell. Export to dedicated project management tools.
- **Quotations** — Nutshell has a quotes feature, but the data model differs significantly from Teamleader's. Rebuilding quotes is typically manual.
- **Tickets and support history** — Nutshell is not a helpdesk. Migrate to a dedicated support platform.
- **Deal phase transition history** — You can set the current stage, but the full phase-change timeline does not transfer natively. Append as structured notes if needed.
- **File attachments** — Require manual download and re-upload; are not included in any automated export path.

## Closing Notes

A Teamleader-to-Nutshell migration is fundamentally a scope reduction exercise. Teamleader's invoicing, project, and ticketing layers have no Nutshell equivalent — that data must be archived, redirected to specialist tools, or summarized as custom fields. What remains — Companies, People, Deals, Activities, and Notes — maps cleanly if the migration is executed in dependency order with API-level extraction for history.

The technical risk is concentrated in three places: silent data loss from CSV-only extraction (activity history, 11+ custom fields), relationship integrity failures from load ordering errors, and timestamp loss if original event dates are not explicitly passed during Nutshell API writes. All three are preventable with the methods described above.

If all you need is a current-state CRM snapshot for a small team, CSV may be sufficient. If you need relationship fidelity, native activity reconstruction, or a short cutover window with delta syncs, the migration requires custom engineering against both APIs.

> Planning a Teamleader to Nutshell migration? Book a 30-minute call with our migration engineers. We'll scope your data, map the edge cases, and give you a realistic timeline — no commitment required.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### Can I migrate activity history from Teamleader to Nutshell?

Not via CSV. Teamleader's backup excludes activity data, and Nutshell's CSV import cannot create activities. You must extract activities via Teamleader's events.list API endpoint and load them via Nutshell's newActivity API method. As a fallback, you can import activities as timestamped notes, but you lose calendar metadata.

### What Teamleader data cannot be migrated to Nutshell?

Invoices, payment history, project plans, time tracking, quotations, tickets, and support history have no equivalent in Nutshell. These must be exported to dedicated tools (accounting software, project management platforms, or helpdesk systems) separately.

### Can I use CSV for a Teamleader to Nutshell migration?

Yes, if you only need current CRM data and simple notes. Teamleader exports cap at 50,000 records, Nutshell CSV files must stay under 32 MB, and Nutshell's CSV import creates historical activities as notes rather than native activity objects. For small accounts without critical activity history, CSV works.

### Does Teamleader's backup export all custom fields?

No. Teamleader's built-in backup exports only the first 10 custom fields per module, sorted alphabetically. If you have more than 10 custom fields on any object, you must create a custom export template per module to capture the rest. The in-app export supports up to 50 fields per template.

### How do Teamleader deals map to Nutshell leads?

Teamleader Deals map to Nutshell Leads. Deal title becomes Lead name, estimated_value maps to Lead value, and estimated_closing_date maps to expected close date. Deal phases must be pre-created as Pipeline Stages in Nutshell. Phase transition history does not transfer natively — only the current stage migrates.
