Skip to content

Close to GoHighLevel Migration: Data Mapping, API Limits & Methods

Migrating from Close CRM to GoHighLevel? Learn how to map Leads to Contacts, handle API rate limits, and choose the right migration method.

Raaj Raaj · · 16 min read
Close to GoHighLevel Migration: Data Mapping, API Limits & Methods
TALK TO AN EXPERT

Planning a migration?

Get a free 30-min consultation. Our engineers review your setup and map out a custom migration plan — no obligation.

Schedule Free Consultation
  • 1,200+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing

Migrating from Close CRM to GoHighLevel (GHL) means mapping a Lead-centric sales CRM onto a Contact-centric marketing-and-sales platform. The structural mismatch between these two systems is the single biggest source of data loss, broken pipelines, and failed imports.

Close nests everything — contacts, tasks, opportunities, and the full activity timeline — under a parent "Lead." GoHighLevel revolves around standalone Contact records, with Opportunities inside Pipelines and Companies as a separate grouping object. A flat CSV export tends to either duplicate company data across contacts or collapse several real people into one record.

That is why a serious Close-to-GHL migration starts with a target data model, not an export button. You need to decide where company data lives, how deal stages translate, which contact is primary for each opportunity, and whether historical activities should become notes, conversations, or an external archive reference. Those decisions are much harder to undo after import than before.

If you're a Sales Ops Manager, RevOps lead, or Agency Owner planning this move, this guide gives you the technical detail to avoid the most common pitfalls.

Data Model Mismatch: Close Leads vs. GoHighLevel Contacts

Close CRM is Lead-centric. Every piece of data — contacts, tasks, opportunities, and activity history — lives inside a parent Lead container. Leads are the most important object in Close. They represent a company or organization and can contain contacts, tasks, opportunities, and activities. In fact, these other objects must be children of a Lead.

By default, Close imports Companies as "Leads." The individuals at that company are seen as "Contacts," and if you are in the process of selling something to that Lead, we track that through "Opportunities." For B2B, your Leads will be Companies where each Lead (Company) will have one or more Contacts. For B2C, your Leads will be Customers with exactly one Contact each.

GoHighLevel is Contact-centric. The Contact record is the atomic unit. Opportunities exist inside Pipelines, and each Opportunity is linked to a Contact — not to a parent company container like Close's Lead. Companies exist as a separate object for grouping contacts together. For a deeper look at GHL's architecture, see our Keap vs GoHighLevel 2026 comparison.

This means you need to flatten Close's nested Lead → Contact → Opportunity hierarchy into GHL's flat Contact + Opportunity structure. Here is what that mapping looks like in practice:

Close CRM Object GoHighLevel Object Notes
Lead (company/account) Contact or Company Company name becomes a Contact field or GHL Company record
Contact (person) Contact Primary mapping target; email + phone are required identifiers
Lead Custom Fields Contact Custom Fields Must be pre-created in GHL before import
Opportunity Opportunity (in a Pipeline) Pipeline and Stage must exist in GHL first
Opportunity Status Pipeline Stage Map each Close status to a GHL stage
Opportunity Custom Fields Opportunity Custom Fields GHL stores these at the contact level — see edge case below
Activities (calls, emails, SMS) Notes or API-injected records CSV import cannot carry full activity history
Lead Status Tag or Contact Custom Field No direct equivalent in GHL
Tasks Manual recreation or workflow triggers No direct CSV import path
Warning

Critical edge case: Even when you edit a custom field from inside an opportunity, GoHighLevel saves that data to the contact, not to the individual opportunity. If the same contact appears in more than one pipeline or in multiple stages, the custom field value is shared across all of their opportunities. If you have multiple Close Opportunities per Lead with different custom field values, you will lose that per-deal granularity in GHL.

Two mapping decisions deserve special attention:

Lead Status is not Opportunity Stage. Close treats these as separate concepts, and GHL has no direct equivalent for Lead Status. In most migrations, Lead Status belongs in a tag or custom field — not in the Pipeline Stage. Conflating them is a common source of broken reporting after cutover.

One company per contact. GHL allows each contact only one company association. If the same person appears under multiple Close Leads, you need a deliberate rule: pick a canonical company, duplicate the contact intentionally, or store the secondary relationship in custom data. (help.gohighlevel.com)

Exporting Data from Close CRM: API Limits & JSON Challenges

Getting data out of Close is the first hurdle, and it's harder than it looks — especially if you need activity history.

CSV vs. JSON Exports

JSON is a less compact file format and it shows hierarchical and other relational data. JSON is the best file format for doing large-scale exports from Close and it's the only format you can use to export all Activities (Emails, Calls, SMS messages, Notes, Custom Activities) from Close.

CSV format is the most commonly used export format and is best used for exports when you don't need to export activity data from Close. CSV files can be opened in Excel or Google Sheets for data manipulation.

In plain terms: if you need call logs, email threads, or SMS history, you must export as JSON. CSV exports from Close will not include activity data. This creates an immediate problem — GHL's native importer only accepts CSV. Any activity data exported as JSON needs to be parsed, transformed, and injected via the GHL API.

Pagination and the Export API

The Close CRM API only allows 100 records per request (pagination limit). For small datasets, you can paginate through results using _skip and _limit parameters:

let skip = 0;
const limit = 100;
let hasMore = true;
 
while (hasMore) {
  const response = await fetch(
    `https://api.close.com/api/v1/lead/?_skip=${skip}&_limit=${limit}`,
    { headers: { 'Authorization': `Basic ${btoa(API_KEY + ':')}` } }
  );
  const data = await response.json();
  processLeads(data.data);
 
  if (data.has_more) {
    skip += limit;
  } else {
    hasMore = false;
  }
}

For larger organizations, brute-force offset loops become impractical. There is a hard limit of 10,000 objects when paginating via the Advanced Filtering API. If you need to paginate for more than 10,000 results, update your query to return smaller batches of objects — a popular method is to use the date_created field as a range.

For production-scale extractions, the Close Export API is the better path. It supports both CSV and JSON formats, but include_activities only works with type=leads and format=json. Exports run asynchronously and are delivered as gzip-compressed files. (developer.close.com)

{
  "format": "json",
  "type": "leads",
  "include_activities": true,
  "send_done_email": false
}

If you export CSV first and hope to recover full call, email, or SMS history later, you are already making the migration harder than it needs to be.

Activities Must Be Fetched Separately via API

If you're querying the Close API directly instead of using the Export API, note that when a lead is returned, its basic info as well as related tasks, opportunities, and custom fields are included. Activities are excluded and have to be fetched separately via the activities endpoint.

This means a full API-based extraction requires at minimum two passes: one for leads, contacts, and opportunities, and a second to iterate through each lead's activities. For an org with 5,000 leads and 50,000+ activities, this quickly becomes a multi-hour extraction job.

Close API Rate Limits

Rate limits are enforced per endpoint group. Endpoint groups are used to provide more granular control by grouping endpoint URL paths and methods together. For instance, GETs to /api/v1/lead/ and POSTs/PUTs to /api/v1/activity/ may be counted as two different API groups.

The per Organization limit is currently 3 times higher than individual API key rate limits, meaning that if the API key rate limit maximum RPS is 20 RPS, the organization-wide limit would be 60 RPS for that same endpoint group.

Depending on the endpoint, you're looking at roughly 10–40 requests per second per API key, with an org-wide cap of 3× that. Not prohibitive for extraction, but enough to slow down a script that doesn't implement exponential backoff.

Tip

Keep the raw Close JSON export as an immutable archive even after the migration is complete. It's your audit trail, your rollback source, and your safety net if a mapping rule changes later.

Importing into GoHighLevel: CSV Constraints & API Rate Limits

Getting data into GoHighLevel has its own set of hard constraints.

CSV Import Limits

Warning

GHL's own documentation is inconsistent on file limits. A contact CSV guide updated March 2026 says files should be under 30 MB. A getting-started article from the same month says CSV files up to 50 MB. The troubleshooting article still says 20 MB or 10,000 rows. In production, treat the smaller bound as the safe one and split files aggressively. (help.gohighlevel.com)

Other CSV import requirements:

  • Your CSV file must contain only one sheet/tab.
  • Every row should have at least one required field (Name, Email, or Phone).
  • Remove spaces, dashes, or letters from phone numbers. Phone numbers must follow E.164 format.
  • Imports cannot be undone. Always validate your data before importing.
  • Country values are validated. GHL's formatting guide requires country values to match its accepted list exactly — United States is accepted, while USA or U.S. can fail. (help.gohighlevel.com)

When updating existing contacts via CSV, GHL checks for matches in this order: Contact ID → Email → Phone. If email and phone match two different existing contacts, GHL updates the record matched by whichever field comes first in the configured sequence. This is why phone normalization, email hygiene, and a source-to-target ID crosswalk matter before first load. (help.gohighlevel.com)

The Notes Truncation Problem

This is one of the most misunderstood limitations in GHL:

When importing contact notes, you may only have one note per contact record with a limit of 5,000 characters.

As per the current export behavior, GHL supports a max of 255 characters for the last note.

So while you can import a note of up to 5,000 characters, you're limited to one note per contact via CSV. If a Close Lead has 50 activity notes, call logs, and email summaries, a CSV import can carry a single note. The rest is lost.

Danger

Data Loss Warning: If your sales reps leave detailed call summaries in Close, a CSV import into GoHighLevel will silently reduce all activity history to a single note. To preserve full history, you must use the GHL API.

To understand why flat files consistently fail for complex CRM data, read our breakdown on using CSVs for SaaS data migrations.

Company Import Paths

GHL now offers two paths for company data. A Business Name field on the contact CSV auto-creates and associates company records during import. A separate Company CSV import supports company-level metadata directly. Use the direct import path when company-level custom fields matter; use Business Name automation when simple association is all you need. (help.gohighlevel.com)

GoHighLevel API V2 Rate Limits

GHL has implemented rate limits on its public V2 APIs using OAuth. Burst limit: a maximum of 100 API requests per 10 seconds for each Marketplace app per resource (Location or Company). Daily limit: 200,000 API requests per day for each Marketplace app per resource.

At 100 requests per 10 seconds, that's an effective throughput of 10 records per second if each record requires one API call. For a migration of 20,000 contacts with associated opportunities and notes, expect 30–60 minutes of API write time at best — and longer in practice due to retry logic, multi-object writes, and error handling.

V1 APIs reached end-of-support as of December 31, 2025. Existing connections will continue to work, however no support or updates will be provided for V1 APIs.

Info

Plan requirement: Basic API access is included with Starter and Unlimited plans, while Advanced API access is available on the Agency Pro plan. The Agency Pro tier unlocks the use of Agency API Keys, where lower plan levels only access Location API Keys.

Comparing Migration Methods: DIY CSV vs. iPaaS vs. Custom Scripts

There are three realistic approaches to this migration. Each has clear trade-offs.

Method 1: Native CSV Export/Import (DIY)

How it works: Export leads, contacts, and opportunities from Close as CSV. Clean and reformat in a spreadsheet. Import into GHL via the built-in CSV importer.

Pros:

  • Free
  • No code required
  • Works for small datasets (under 2,000 contacts) with no activity history needs

Cons:

  • Activity history (calls, emails, SMS) is completely lost — Close CSV exports don't include activities
  • One note per contact, capped at 5,000 characters on import
  • Manual field mapping is tedious and error-prone
  • No rollback if something goes wrong
  • Must manually split files that exceed the row or size limits
  • Lead-to-Contact flattening must be done manually in the spreadsheet

Best for: Small orgs with under 1,000 contacts where activity history isn't needed.

Method 2: iPaaS Tools (Zapier / Make)

How it works: Use Zapier or Make scenarios to read from the Close API and write to the GHL API, record by record.

Pros:

  • Can handle some activity data if configured correctly
  • No server infrastructure needed
  • Good for ongoing sync after the initial migration

Cons:

  • Close's API returns 100 records per request, requiring loop-based pagination — incrementing the offset parameter to retrieve subsequent batches. Most iPaaS users struggle to implement this correctly.
  • GHL's 100-request/10-second burst limit means scenarios need built-in throttling
  • Cost scales linearly with record count — a 20,000-contact migration with activities can burn through thousands of Zapier tasks
  • Error handling is primitive — a single failed record can break an entire scenario
  • Custom Activity types from Close have no native Zapier mapping to GHL

Best for: Teams with under 5,000 contacts and an in-house automation builder who understands API pagination and rate limiting. Also useful as a bridge for ongoing low-volume sync after the initial data move.

Method 3: Custom API Scripts

How it works: Write purpose-built scripts (Python, Node.js, etc.) that extract from Close's API, transform the data model, and inject into GHL's API — handling pagination, rate limiting, retries, and data validation programmatically.

Pros:

  • Full control over data transformation
  • Can preserve complete activity history by writing directly to GHL's API
  • Handles Lead→Contact structural flattening with precision
  • Maps Close Opportunity Statuses to GHL Pipeline Stages programmatically
  • Supports idempotent writes and rollback logic

Cons:

  • Requires engineering time (typically 40–80+ hours for a complete migration)
  • Must implement rate limiting for both Close (10–40 RPS) and GHL (100 req/10s)
  • Needs thorough testing with a subset before running the full migration
  • Error handling, logging, and validation must be built from scratch

Best for: Any migration where activity history matters, or where the dataset exceeds 5,000 contacts.

Tip

Which method should you choose? If you have fewer than 1,000 contacts and don't care about call/email history, CSV is fine. If you need activity history, or have complex multi-contact Leads with multiple Opportunities, custom scripts — either built in-house or outsourced — are the only reliable path.

Edge Cases and Limitations to Watch For

After handling hundreds of CRM migrations, these are the gotchas specific to Close→GHL:

  1. Multi-contact Leads. A Close Lead with 3 contacts and 2 Opportunities creates a many-to-many problem. GHL Opportunities link to a single primary Contact (with up to 10 additional contacts in an opportunity). You need a clear strategy for which contact becomes primary.

  2. Opportunity confidence values. Close tracks Total Value and Expected Value (deal value × confidence level) for forecasting. GHL Opportunities have a monetary value field but no native confidence percentage. You'll need a custom field or accept losing this data.

  3. Email thread context. Close stores full email threads with in-reply-to chains. GHL has conversations, but they're tied to its built-in messaging. Imported email history typically lands as notes, not threaded conversations.

  4. Smart Views and saved filters. These don't migrate. You'll need to rebuild them as GHL Smart Lists after cutover.

  5. Sequences and workflows. Close Sequences do not map to GHL Workflows. These must be rebuilt manually in GHL's workflow builder.

  6. Phone number formatting. Close is relatively flexible with phone formatting. GHL requires E.164 format — clean your phone numbers before import or rows will fail silently.

  7. Close Custom Objects. Custom Objects are always tied to a specific lead, and GHL has its own Custom Objects system that works differently. These require special handling during the transformation phase.

  8. Activity richness beyond text. Close notes support rich text, call activities can include recordings and transcripts, and SMS activities can include attachments. Decide early whether GHL needs first-class conversation history or whether a readable archive note is sufficient for your operators. (developer.close.com)

Pre-Migration Checklist: Close CRM to GoHighLevel

Before you start — whether DIY or with a partner — run through this checklist.

Step 1: Audit Your Close Data

  • Count total Leads, Contacts, and Opportunities
  • Identify how many Leads have multiple Contacts (these need special handling)
  • Export a sample JSON file to understand your activity volume per Lead
  • Document all Lead, Contact, and Opportunity custom fields and their data types
  • Note any Custom Objects — they're always tied to a specific lead and need separate handling
  • List every object truly in scope: leads, contacts, opportunities, tasks, notes, calls, emails, SMS, meetings, custom fields, owners, and files

Step 2: Prepare Your GoHighLevel Sub-Account

  • Create all Pipeline Stages that map to your Close Opportunity Statuses
  • Create all Contact Custom Fields that correspond to Close's Lead and Contact custom fields
  • Create Opportunity Custom Fields as needed — but remember the contact-level storage limitation
  • Set up Tags to represent Close Lead Statuses
  • Configure duplicate-contact settings (GHL deduplicates on email or phone)
  • Confirm your GHL plan supports the API access level you need — Agency Pro for Agency API Keys

Step 3: Build Your Mapping Document and ID Crosswalk

  • Map every Close field to its GHL destination (see the mapping table above)
  • Define how multi-contact Leads will be handled: primary contact plus additional contacts, or separate records
  • Document all data transformations (phone number formatting to E.164, country name normalization, date formats)
  • Decide which activities to migrate and which to archive
  • Create a durable source-to-target ID crosswalk so retries don't create duplicates or drift

Step 4: Run a Test Migration

  • Migrate 50–100 records — and don't pick your cleanest data. Use a sample that includes multi-contact Leads, old Opportunities, malformed phone numbers, and long notes.
  • Validate: Are contacts created correctly? Are Opportunities in the correct Pipeline and Stage? Are notes populated with full content?
  • Check for duplicates
  • Confirm that your sales team can find what they need in the target system

Step 5: Execute the Full Migration in Phases

  • Load companies and contacts first, then opportunities, then notes and activity history
  • If writing through the API, pace requests against GHL's published burst limits and batch intelligently
  • Keep source-to-target ID maps updated as each batch completes
  • Log every write so failed batches can be replayed idempotently instead of guessing what partially landed

Step 6: Run a Delta Pass and Cut Over

  • Let your sales team keep working in Close during the backfill
  • Right before go-live, replay any changes made since the initial extraction
  • Spot-check 5–10% of migrated records manually
  • Verify Pipeline totals match source data
  • Have your sales team validate key accounts before going live
  • Disable or remap old automations in Close
  • Keep the raw Close export and ID crosswalk available for rollback or audit

How ClonePartner Handles Close-to-GoHighLevel Migrations

This is exactly the kind of migration we built ClonePartner to handle. The Close→GHL move touches every hard problem we specialize in: structural data model transformation, API rate limit management, and historical activity preservation.

Here's what our engineering-led approach looks like:

  • Lead-to-Contact flattening with relationship preservation. We map Close's nested Lead→Contact→Opportunity structure into GHL's flat model without losing the association between contacts and their deals. Company names, Lead-level custom fields, and Lead Statuses are preserved as GHL tags or custom fields.

  • Full activity history via API injection. Instead of relying on GHL's CSV importer (which limits you to one note per contact and drops activities), we write call logs, email threads, SMS messages, and notes directly via GHL's V2 API. This bypasses the CSV limitations entirely.

  • Rate-limit-aware orchestration. Our scripts manage both Close's per-endpoint-group rate limits and GHL's 100-request/10-second burst limit with built-in backoff, retry queues, and throughput monitoring. No timeouts, no data corruption.

  • Phased load with ID crosswalks. We load schema prep first, then companies and contacts, then opportunities, then history injection, then QA, then a delta catch-up pass before cutover. Source-to-target ID maps let us rerun failed batches idempotently instead of guessing what partially landed.

  • Zero downtime cutover. Your sales team keeps working in Close right up until the cutover moment. We run a final delta sync to capture last-minute changes, then switch. No "freeze your CRM for 48 hours" requirement.

You can read more about how we run migrations at ClonePartner — the same methodology applies here.

What This Migration Really Comes Down To

The Close→GoHighLevel migration isn't impossible to DIY, but it's deceptively complex. The data model mismatch between Lead-centric and Contact-centric architectures means every record needs structural transformation, not just field-to-field mapping. Add in the JSON-only activity export from Close, GHL's CSV import limits, and the API rate constraints on both sides, and you're looking at a project that requires genuine engineering work to get right.

If your Close data is basically one person per account and you only need present-state records, GHL's CSV importer is enough. If you care about relationship fidelity, full historical activity, or deterministic replay when something fails, treat this as an engineering project. The decision point is not volume alone — it's whether you can afford to lose structure or history on the way over.

We've completed 1,200+ migrations across CRMs, helpdesks, and data platforms. If you're planning a Close-to-GHL move and want to keep your activity history, pipeline data, and custom fields intact, we'll scope it, map it, and execute it — typically in days, not weeks.

Frequently Asked Questions

Can I migrate activity history (calls, emails, SMS) from Close CRM to GoHighLevel?
Not via CSV. Close only exports activity data in JSON format, and GoHighLevel's CSV importer supports just one note per contact. To preserve full activity history, you need to parse the JSON export and inject records via GHL's V2 API.
What are GoHighLevel's CSV import limits?
GHL's own documentation is inconsistent — different guides cite 20 MB, 30 MB, and 50 MB limits with a 10,000-row cap. Treat the smallest bound as the safe one, use a single sheet per file, and ensure every row has at least one identifier (Name, Email, or Phone). Imports cannot be undone.
How do Close CRM Leads map to GoHighLevel Contacts?
Close Leads are parent containers holding contacts, opportunities, and activities. In GoHighLevel, the Contact is the primary record. You need to flatten the Lead into one or more Contacts, map Lead-level fields to Contact custom fields or tags, and link Opportunities to the correct Contact inside a GHL Pipeline.
What is GoHighLevel's API rate limit for migrations?
GoHighLevel's V2 API enforces a burst limit of 100 requests per 10 seconds and a daily limit of 200,000 requests per location per app. That's an effective throughput of about 10 records per second when each record requires one API call.
Can Zapier or Make handle a full Close to GoHighLevel migration?
They can help with low-volume sync or delta catch-up, but full historical backfills are difficult. Close's 100-record pagination, GHL's burst limit, linear cost scaling, and limited error handling make iPaaS tools best suited for small datasets under 5,000 contacts.

More from our Blog

Keap vs GoHighLevel 2026: The Definitive Comparison for Scaling Businesses
GoHighLevel/Keap

Keap vs GoHighLevel 2026: The Definitive Comparison for Scaling Businesses

Discover the definitive 2026 comparison between Keap and GoHighLevel to find the right CRM for your business. Explore how Keap’s AI agents and native e-commerce tools benefit small, relationship-based businesses, while GoHighLevel’s white-label SaaS capabilities and advanced multichannel workflows empower marketing agencies and local services. Read our breakdown of features, automation logic, and hidden pricing structures to see which platform fits your growth strategy.

Raaj Raaj · · 6 min read
Salesforce to GoHighLevel Migration: The Technical Guide
GoHighLevel/Salesforce/Migration Guide/Salesforce Service Cloud

Salesforce to GoHighLevel Migration: The Technical Guide

A technical guide to migrating from Salesforce to GoHighLevel: object mapping, API rate limits, custom object constraints, and step-by-step ETL architecture.

Raaj Raaj · · 21 min read
Nutshell to GoHighLevel Migration Guide (2026)
GoHighLevel/Migration Guide

Nutshell to GoHighLevel Migration Guide (2026)

Technical guide to migrating from Nutshell to GoHighLevel — covering data model mapping, API constraints, migration methods, and edge cases that break DIY attempts.

Raaj Raaj · · 24 min read