Skip to content

An In-Depth Guide to Migrating from Zendesk Sell to Pipedrive

Migrating from Zendesk Sell to Pipedrive involves careful planning, data mapping, and API integration. This guide walks you through migrating users, pipelines, custom fields, deals, activities, and attachments, ensuring a smooth transition with zero downtime

Tejas Mondeeri Tejas Mondeeri · · 10 min read
An In-Depth Guide to Migrating from Zendesk Sell to Pipedrive
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Moving from Zendesk Sell to Pipedrive is more than a simple export and import. Zendesk Sell organizes its data with key nuances you'll want to preserve, such as its use of a single Contact object to represent both individuals and organizations, distinguished by a boolean flag. You will also need to handle distinct entities for Calls, Tasks, and a specific Order and Line Item structure for attaching products to a deal.

Pipedrive models data around a set of distinct core entities, with separate objects for Persons and Organizations. Its RESTful API provides first-class endpoints for these entities, as well as for Activities (which encompass calls and tasks) and Notes, which makes it a strong destination for a clean, API-driven migration.

This guide walks through how to map each concept one-to-one, handle attachments and ownership, and execute the migration with proper sequencing and validation.

Phase 1: Pre-Migration Planning, Mapping & Setup

Before writing a single line of code, it's crucial to understand the data models of both CRMs and set up your API access.

While both Zendesk Sell and Pipedrive are sales CRMs, they organize data differently. Pipedrive's API is built around a set of core entities, including Leads, Deals, Persons, Organizations, Activities, Products, and Users. Understanding how Zendesk Sell's concepts map to these entities is the first step.

Here is a high-level mapping of the primary objects:

Zendesk Sell Pipedrive Mapping notes
Contact (is_organization: true) Organization Zendesk uses a single Contact object for both people and companies. You'll need to filter these based on the is_organization flag.
Contact (is_organization: false) Person A Zendesk Contact can be linked to an organization via contact_id, which maps to a Pipedrive Person's org_id.
Lead Lead Pipedrive keeps leads in a separate "Leads Inbox" before they are converted into deals. Zendesk Leads map directly to this concept
Deal Deal This is a straightforward mapping. Both platforms track ongoing transactions through pipelines and stages
Pipelines & Stages Pipelines & Stages The concepts are parallel. You will need to recreate the pipeline and stage structure in Pipedrive first.
Task Activity (type task) Zendesk Tasks map to Pipedrive Activities. Pipedrive uses different ActivityTypes (e.g., call, meeting, task)
Call Activity (type call) & CallLog Zendesk Calls should be migrated as call type Activities in Pipedrive. They can also be added as CallLogs (specific type of activity that stores call details) in Pipedrive
Notes Notes Notes can be attached to leads, contacts, and deals in Zendesk and to leads, deals, persons, and organizations in Pipedrive
Document File Documents attached to Zendesk resources can be migrated to Pipedrive as files attached to the corresponding items
Product Product Both platforms have a product catalog. Pipedrive allows products to be attached directly to deals
Order & Line Item Product on a Deal Zendesk uses an Order object with Line Items to link products to a deal. In Pipedrive, you'll add products directly to a deal, specifying quantity and price
User User Represents the accounts for your team members
Info

A note on Pipedrive API versions: Pipedrive is in the process of rolling out a v2 API alongside its existing v1. Throughout this guide, we reference v2 endpoints where they are available (e.g., POST /api/v2/deals, POST /api/v2/organizations) and fall back to v1 for endpoints that have not yet been migrated (e.g., POST /v1/leads, POST /v1/notes, POST /v1/files). Check the Pipedrive API changelog for the latest availability.

Setting Up API Access:

Your migration script will need to authenticate with both services.

  1. Zendesk Sell Authentication:
  • To access the Zendesk Sell Core API, you need a Personal Access Token.
  • Sign in to your Sell account and navigate to Settings > Integrations > OAuth.
  • In the Access Tokens tab, generate a new token. Store this token securely, as it will not be shown again.
  • All API requests to Zendesk must include this token in the Authorization header: Authorization: Bearer $ACCESS_TOKEN.
  1. Pipedrive Authentication:
  • Pipedrive's RESTful API uses an api_token for authentication, which is ideal for a migration script.
  • Find your personal API token in your Pipedrive account by going to Settings > Personal preferences > API.
  • All calls to the Pipedrive API must include this token as a query parameter (e.g., ?api_token=YOUR_API_TOKEN).

Phase 2: The Migration Process

The key to a successful migration is to transfer data in a logical order to preserve relationships. You should migrate foundational data (like users and pipelines) before migrating the data that depends on it (like deals).

Note: Throughout this process, it's essential to create and maintain a mapping of Zendesk Sell entity IDs to the new Pipedrive entity IDs you create.

Step 1: Migrate Users

  1. Fetch from Zendesk Sell: GET /v2/users endpoint Retrieve all users from your account.
  2. Create in Pipedrive: For each Zendesk user, make a post request: POST /v1/users To create a corresponding user in Pipedrive. You must provide their email.
  3. Map IDs: Store the original Zendesk id and the new Pipedrive id for each user. This map is crucial for assigning ownership correctly later.

Step 2: Migrate Pipelines and Stages

  1. Fetch Pipelines from Zendesk:
    GET /v2/pipelines Get a list of your sales pipelines.
  2. Create Pipelines in Pipedrive: For each Zendesk pipeline, create a new one in Pipedrive: POST /api/v2/pipelines Map the old and new IDs.
  3. Fetch Stages from Zendesk: GET /v2/stages Retrieve all stages, which include a pipeline_id.
  4. Create Stages in Pipedrive: For each Zendesk stage, create a new one in Pipedrive: POST /api/v2/stages Make sure to associate it with the correct new Pipedrive pipeline ID. Map the stage IDs.

Step 3: Recreate Custom Fields

You cannot migrate custom fields directly; you must recreate their structure in Pipedrive first.

  1. Fetch Definitions from Zendesk:
    GET /v2/:resource_type/custom_fields Use this endpoint for resources like contact, lead, and deal to get their custom field structures.
  2. Create in Pipedrive: Create corresponding custom fields in Pipedrive using the appropriate endpoints: POST /v1/organizationFields POST /v1/personFields POST /v1/dealFields
  3. Pipedrive leads inherit the custom fields structure from deals, so you only need to create them once.
  4. Map Field Keys: Map the Zendesk custom field names to the new Pipedrive custom field keys (which look like long hashes).
Warning

Watch for custom field type incompatibilities. Not all Zendesk Sell custom field types have a direct equivalent in Pipedrive. For example, if Zendesk has a field type that Pipedrive doesn't support, you'll need to choose the closest available type and potentially transform the data. Review the field types on both sides before creating them in Pipedrive, and document any lossy conversions.

Step 4: Migrate Organizations and Persons (Zendesk Contacts)

Zendesk uses a single Contact object, while Pipedrive separates them into Organizations and Persons

  1. Fetch Organizations from Zendesk:
    GET /v2/contacts Filter for items where is_organization is true.
  2. Create Organizations in Pipedrive: Iterate through the results and create them in Pipedrive: POST /api/v2/organizations Populate standard and custom fields using your mapped keys. Store the ID mappings.
  3. Fetch Persons from Zendesk:
    GET /v2/contacts Filter for items where is_organization is false.
  4. Create Persons in Pipedrive: Create each person: POST /api/v2/persons If the Zendesk contact has a contact_id (linking it to an organization), use your ID map to find the new Pipedrive org_id and include it in the request. Store the Person ID mappings.

Here's pseudocode for the Contact-splitting logic:

zendesk_contacts = fetch_all_paginated("/v2/contacts")
 
for contact in zendesk_contacts:
    if contact["is_organization"]:
        pd_org = pipedrive_post("/api/v2/organizations", {
            "name": contact["name"],
            # map custom fields using field_key_map
        })
        id_map["orgs"][contact["id"]] = pd_org["id"]
    else:
        org_id = id_map["orgs"].get(contact.get("contact_id"))
        pd_person = pipedrive_post("/api/v2/persons", {
            "name": contact["name"],
            "email": contact.get("email"),
            "phone": contact.get("phone"),
            "org_id": org_id,
            # map custom fields using field_key_map
        })
        id_map["persons"][contact["id"]] = pd_person["id"]

Step 5: Migrate Leads

  1. Fetch from Zendesk: Retrieve all leads: GET /v2/leads
  2. Create in Pipedrive: For each Zendesk lead, create a Pipedrive lead: POST /v1/leads Use your ID maps to link the lead to the correct person_id or organization_id. Note that leads created via the API have a set source of "API".

Step 6: Migrate Deals

  1. Fetch from Zendesk: Get all deals: GET /v2/deals
  2. Create in Pipedrive: For each Zendesk deal, create a new deal in Pipedrive: POST /api/v2/deals Use your ID maps to correctly populate:
  • owner_id (from the Users map).
  • person_id and/or org_id (from the Persons/Organizations maps).
  • pipeline_id and stage_id (from the Pipelines/Stages maps).
  • Populate custom fields using the mapped keys.
  • If a deal's status is "lost" in Zendesk, you can migrate the loss_reason_id by first fetching the reason text: GET /v2/loss_reasons/:id And then setting it in Pipedrive's lost_reason text field.

Step 7: Migrate Associated Data (Notes, Activities, Files, etc.)

Once the core objects exist in Pipedrive, you can link their associated data.

  • Notes: Fetch notes from Zendesk: GET /v2/notes This provides resource_type and resource_id. Create them in Pipedrive: POST /v1/notes Link them to the new IDs for the corresponding deal, person, or organization.
  • Tasks & Calls (Activities):
    • Fetch Zendesk Tasks GET /v2/tasks And create them as Pipedrive Activities with type: 'task' using: POST /api/v2/activities.
    • Fetch Zendesk Calls GET /v2/calls And create Pipedrive Activities with type: 'call'. You can additionally create a detailed CallLog using POST /v1/callLogs — this is a separate, more structured record that stores call-specific metadata (duration, outcome, recording URL). Link it to the Activity with the activity_id field.
  • Documents (Files):
    • Fetch document metadata from Zendesk for a given resource GET /v2/documents
    • For each document, use the download_url provided in the response to fetch the file content.
    • Upload the file to Pipedrive using POST /v1/files Associate it with the correct new Pipedrive deal_id, person_id, org_id, or activity_id.
  • Products on Deals:
    • First, migrate your product catalog by fetching from Zendesk GET /v2/products Create them in Pipedrive POST /api/v2/products Map the product IDs.
    • For each Zendesk deal, fetch its associated Orders GET /v2/orders filtered by deal_id And then their Line Items GET /v2/orders/:order_id/line_items
    • For each line item, add the corresponding product to the new Pipedrive deal POST /api/v2/deals/{id}/products

Phase 3: Pagination, Rate Limits & Error Handling

Pagination

Both APIs paginate their list responses. Your migration script must handle this to avoid missing records.

  • Zendesk Sell uses cursor-based pagination. Each response includes a links.next_page URL. Keep fetching until next_page is null.
  • Pipedrive also uses cursor-based pagination. Look for additional_data.next_cursor (v2) or additional_data.pagination.next_start (v1) in responses.

Here's a generic pagination pattern:

def fetch_all_paginated(base_url, params=None):
    results = []
    url = base_url
    while url:
        response = api_get(url, params=params)
        results.extend(response["items"])
        url = response.get("links", {}).get("next_page")  # adjust per API
        params = None  # params already encoded in next_page URL
    return results

Rate Limits

Both APIs enforce rate limits. Hitting them during a large migration is inevitable, so your script needs to handle throttling gracefully.

  • Pipedrive enforces rate limits per company per 2-second window. The exact limit depends on your plan tier. Pipedrive returns X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on every response — use these to throttle proactively rather than waiting for a 429.
  • Zendesk Sell also enforces rate limits and returns 429 responses when exceeded.

Implement exponential backoff with jitter for 429 responses:

import time, random
 
def api_request_with_retry(method, url, **kwargs):
    max_retries = 5
    for attempt in range(max_retries):
        response = method(url, **kwargs)
        if response.status_code == 429:
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
            continue
        response.raise_for_status()
        return response.json()
    raise Exception(f"Rate limited after {max_retries} retries: {url}")

Error Handling and Idempotency

Large migrations will encounter intermittent failures — network timeouts, partial writes, and unexpected API errors. Your script needs to be resilient.

  • Persist your ID mapping table to disk (or a database) after every successful write. If your script crashes after creating 5,000 of 8,000 Persons, you need to resume from record 5,001, not re-create duplicates.
  • Before creating a record, check if its Zendesk ID already exists in your mapping table. This makes your script idempotent — safe to re-run without creating duplicates.
  • Log every failed write with the Zendesk source ID and the error response. This gives you a clear remediation list after the migration completes.
def migrate_record(zendesk_id, entity_type, create_fn):
    if zendesk_id in id_map[entity_type]:
        return id_map[entity_type][zendesk_id]  # already migrated
    try:
        pd_record = create_fn()
        id_map[entity_type][zendesk_id] = pd_record["id"]
        save_id_map_to_disk(id_map)
        return pd_record["id"]
    except Exception as e:
        log_error(zendesk_id, entity_type, e)
        return None

Phase 4: Validation & Common Pitfalls

Data Validation

After the migration, perform sanity checks. Compare record counts for each entity between Zendesk and Pipedrive. Spot-check several complex records (e.g., a deal with multiple notes, activities, and products) to ensure all relationships were preserved correctly.

Common Pitfalls

  • Duplicate contacts. If your Zendesk data has contacts with the same email address, Pipedrive may reject or merge them depending on your duplicate detection settings. Audit for duplicates before you start.
  • Orphaned notes and activities. If a parent record (deal, person, org) fails to migrate, any notes or activities linked to it will have nowhere to land. Always validate that parent records exist before migrating child data.
  • Currency and deal values. If your Zendesk Sell instance uses multiple currencies, confirm that Pipedrive has the same currencies enabled. Deal values will import as numbers — the currency association must be set explicitly.
  • Timezone shifts on activity dates. Zendesk Sell and Pipedrive may store and display datetimes in different timezones. Verify that due_date and completed_at values on activities land on the correct dates after migration.
  • The is_organization split. The most common migration bug: forgetting to filter on is_organization and creating all Zendesk Contacts as Persons. Always migrate Organizations first, then Persons, so the org_id links resolve correctly.

Run a Sample Migration First

Run a sample migration on a subset of your data and confirm that everything looks good. This helps in identifying issues early and making necessary adjustments before the full migration.

Use SDKs: To simplify development, consider using one of Pipedrive's official client libraries for Node.js or PHP, which can handle API requests and authentication for you.

Further Resources:

More from our Blog

Pylon to Missive Migration: The Technical Guide
Migration Guide/Pylon/Missive

Pylon to Missive Migration: The Technical Guide

A technical guide to migrating from Pylon to Missive covering data model mapping, API rate limits, migration approaches, edge cases, and step-by-step implementation.

Nachi Nachi · · 25 min read