Close's Lead-centric model must be flattened to fit GoHighLevel's Contact-centric structure. Activity history requires JSON export plus API injection — CSV imports can't carry it.
There is no native migration path between Close CRM and GoHighLevel. Close uses a Lead-centric data model where contacts, opportunities, tasks, and activities are nested under a parent Lead object, while GoHighLevel is Contact-centric with standalone Contact records, separate Company objects, and Opportunities linked to Contacts within Pipelines. Migrating between them requires flattening Close's hierarchical structure, pre-creating custom fields and pipeline stages in GHL, and using a combination of CSV imports and API-based data injection—since activity history (calls, emails, SMS) can only be exported from Close as JSON and cannot be imported into GHL via CSV.
Read this first
Pair-specific gotchas that catch teams out. Each one has cost somebody a weekend.
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.
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.
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)
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.
OAuth requirement for V2 API
GHL's V2 API requires OAuth-based authentication through a registered Marketplace app — there is no simple API key option for V2. If you're building a DIY migration script, you'll need to register an app in the GHL Marketplace, implement the OAuth flow, and manage token refresh. This is a meaningful setup hurdle compared to Close's straightforward API key authentication.
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.
Which method should you choose? If you have fewer than 1,000 contacts and don't care
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.
The runbook
Work top to bottom. Tick steps as you go — your progress is saved in this browser.
01 Discovery Agree scope, pipeline design and success criteria before touching data.
Objective A scope covering every object in the revenue model, with sales leadership signed up to the pipeline design.
Keep these open
-
Inventory every object in Close
Count accounts, contacts, leads, deals or opportunities, activities, notes, emails, files, products and quotes. Activity and email history is usually the largest object by an order of magnitude and the one people forget to size.
Data Profiler Get real record counts instead of estimating from memory -
Map the current pipeline and agree the target model
Document every pipeline, stage, probability and required field, then agree the HighLevel model with sales leadership. Migrating a broken pipeline faithfully is a wasted opportunity; redesigning it mid-migration is a wasted migration.
Stage changes alter historical conversion rates. Agree how you will restate reporting before you change the model.
-
Catalogue integrations and automation
List every system touching Close: marketing automation, quoting, billing, ERP, data enrichment, dialler, BI. Each is a separate cutover task with its own owner, and each can silently write bad data into your new CRM.
-
Capture the reporting that must survive
Interview the people who actually live in the dashboards — forecast, pipeline coverage, rep activity, cohort conversion. Every one of these needs the underlying fields to migrate, which frequently expands the scope.
-
Build the business case and pick the go-live date
Model licence delta, implementation effort and productivity dip. Then choose the date deliberately: mid-quarter is disruptive, quarter-end is worse. Most teams land on the first week of a new quarter.
COI & ROI Calculator Build the 36-month business case you will need for sign-off
Don't move on until
- Object counts confirmed for accounts, contacts, deals and activities
- Target pipeline and stage model agreed with sales leadership
- Reporting requirements captured from the people who use the reports
02 Data Audit CRM data is usually dirtier than anyone expects. Find out how dirty.
Objective A profiled export with duplicates, ownership gaps and relationship integrity all quantified and triaged.
Keep these open
-
Export and profile every object
Profile null rates, distinct values and type consistency across all objects. Pay attention to fields sales reps were supposed to fill in: an 80% null rate on a field your forecast depends on is a business finding, not a data one.
Data Profiler Profile the Close export for nulls, outliers and type drift -
Quantify duplicates and agree the merge policy
Measure duplicate accounts (same company, different spellings and suffixes) and contacts (same email, or same person at a renamed company). Agree survivorship rules before merging: which record wins, which fields, and what happens to the activity history on the loser.
Merging before you have agreed survivorship rules destroys history irreversibly. Decide first, merge second.
Data Cleaner Strip empty rows, stray whitespace and dead columns -
Verify relationship integrity
Check every deal has a valid account, every contact a valid account, every activity a valid parent. Referential breaks are the defect that turns a clean-looking load into a CRM where the pipeline report does not tie to the account list.
-
Resolve ownership and the user map
Build the Close user → HighLevel user map, including leavers. Every record needs a valid owner: records assigned to deactivated users either fail to load or land unassigned, and unassigned pipeline is pipeline nobody works.
Records owned by deactivated users are a top cause of load failures. Decide the reassignment target before you start.
-
Scan for PII and regional compliance
CRMs hold marketing consent, lawful basis and unsubscribe state. Confirm these fields migrate intact and that consent provenance survives — losing consent records is a regulatory problem, not a data-quality one.
PII & Compliance Scanner Find regulated fields before they land in a new system -
Clean, normalise and archive the pre-state
Normalise country and state values, phone formats, currencies and casing, and standardise all timestamps to UTC. Keep an untouched copy of the raw export — it is your only reference if a mapping decision turns out wrong.
Don't move on until
- Duplicate rate quantified per object with a merge policy agreed
- Every record has a valid owner mapped to a target user
- Relationship integrity verified — no orphaned deals or contacts
03 Field Mapping Map objects, relationships and picklists — in that order.
Objective A signed mapping spec that covers objects, relationships, picklist values and currency handling.
Keep these open
-
Map objects and their relationships first
Establish how Close objects correspond to HighLevel objects before any field work. Leads-versus-contacts, accounts-versus-organisations and deal hierarchies differ structurally between CRMs, and a field map built on the wrong object model has to be redone.
Schema Mapper Opens pre-loaded with the Close → HighLevel field pair -
Generate and then hand-review the field map
Auto-match both schemas, then review every row. Look hardest at anything named "type", "source", "stage" or "status", where names match and meanings do not.
-
Map every picklist value, including retired ones
Enumerate all values on both sides — deal stages, lead sources, industries, statuses — and map each explicitly, including values no longer offered but still present on old records. Unmapped values either fail the row or land as blanks that quietly break segmentation.
Historical records often carry picklist values that were retired years ago and no longer appear in the UI.
-
Decide currency, amount and date handling
If you sell in multiple currencies, confirm how HighLevel stores amounts, exchange rates and dated conversion rates. Recalculating historical deal values at today's rate silently rewrites your revenue history.
Multi-currency deals re-converted at current rates will not tie to your historical reporting or your finance system.
-
Determine the load order
Sequence the load so parents exist before children: users, then accounts, then contacts, then deals, then activities and notes. Keep source IDs in custom fields so relationships can be rebuilt by lookup rather than guesswork.
-
Freeze the spec and sign off
Version-control the mapping, walk RevOps and sales leadership through the decisions that change reporting, and get written sign-off before the pilot.
Don't move on until
- Object and relationship model mapped and reviewed
- Every picklist value explicitly mapped, including dead values
- Load order determined so parents always exist before children
04 Test Migration Pilot with related records, not a flat sample.
Objective A pilot load whose relationships, ownership and roll-up reporting all verify against source.
Keep these open
-
Configure the HighLevel sandbox to match the agreed model
Build the pipelines, stages, custom fields, record types and user roles first. Load into a default configuration and you will only discover the configuration defects at full scale.
-
Select a connected pilot slice
Take complete account trees — 50-100 accounts with all their contacts, deals, activities and files — rather than a flat random sample. Relationship defects are the whole point of a CRM pilot and a flat sample cannot expose them.
-
Run the load in dependency order with full logging
Load users, accounts, contacts, deals, then activities, logging every request against its source ID. Note which failures are transient (rate limits, timeouts) and which are structural (validation, missing parent).
-
Verify relationships and roll-ups
Confirm every deal sits on the right account with the right owner and stage, and that pipeline totals per account and per rep match Close exactly. Roll-up mismatches almost always mean a relationship or currency defect upstream.
Migration Validation Tool Diff the pilot batch against source before scaling up -
Measure throughput and project the full load
Record actual records-per-hour under HighLevel's API limits and extrapolate, remembering activity history usually dominates volume. If the projection exceeds your window, split the load or trim activity scope now.
-
Let reps work the pilot data
Put two or three reps in the sandbox against their own accounts. They spot missing context, wrong owners and unusable notes far faster than any reconciliation script, and their buy-in is what makes adoption work.
Don't move on until
- Relationships intact across the whole pilot slice
- Pipeline roll-ups match source for the pilot accounts
- Reps have worked pilot records and confirmed they are usable
05 Cutover Switch the revenue system with the pipeline intact.
Objective All in-scope CRM data live in HighLevel, integrations repointed, and reps selling on day one.
Keep these open
-
Pre-load history ahead of the freeze
Load closed deals, historical activities and inactive accounts while Close stays live. Only open pipeline and the final delta need to move inside the window.
-
Publish the cutover runbook
A timed sequence with owners and abort criteria: freeze, final export, delta load, integration switch, smoke test, go/no-go, rep enablement. Pick a window that avoids quarter-end and month-end close.
-
Freeze Close and take the final delta
Set Close read-only and export everything changed since the pre-load. Reps updating deals during an unenforced freeze is the classic way to lose the most recent — and most valuable — pipeline changes.
A rep who updates a deal in the old CRM during the freeze will lose that update permanently.
-
Load the delta and reconcile the pipeline
Run the delta, then verify open pipeline value and count per rep against Close before anything else. If the pipeline number is wrong on day one, reps stop trusting the system and never fully come back.
Migration Validation Tool Confirm the final delta landed before you reopen -
Repoint every integration and verify with real records
Switch marketing automation, quoting, billing, enrichment, dialler and BI connections, then push a live record through each path. An unrepointed integration writing into the old CRM causes divergence that gets harder to reconcile every day.
Two-way integrations left pointing at the old CRM will keep writing there. Disable them before you switch, not after.
Cron Expression Builder Schedule the delta syncs that run through the freeze -
Go/no-go, then enable the reps
Call the decision explicitly against the exit criteria. Run enablement on real data with their own accounts on screen, and keep Close read-only rather than cancelled until validation closes.
Don't move on until
- Historical load complete and reconciled before the freeze
- All integrations repointed and verified end to end
- Reps logged in with pipeline visible and correct
06 Validation Prove the revenue numbers tie out, then close the project.
Objective Reconciled data, forecast parity with pre-migration reporting, and signed acceptance.
Keep these open
-
Reconcile every object
Compare counts and values across accounts, contacts, deals, activities and files, plus field-level spot checks on a random sample. Produce a single report suitable for audit and for finance.
Migration Validation Tool Reconcile Close and HighLevel record-for-record -
Tie the pipeline and forecast to baseline
Rebuild forecast, pipeline coverage and win-rate reporting and compare to pre-migration figures. Every variance needs an explanation — most trace back to stage or currency mapping decisions made in Field Mapping.
Stage-model changes will legitimately shift historical conversion rates. Restate the baseline rather than chasing the difference as a defect.
-
Verify ownership, visibility and permissions
Confirm every record has the right owner and that sharing rules, territories and role hierarchy give each rep exactly the visibility intended. Over-broad visibility in a CRM is a data-protection issue as much as a config one.
-
Re-profile for field completeness
Compare loaded null rates against the source profile per field. A field that arrived empty while counts matched is the failure counts alone cannot detect.
Data Profiler Prove field completeness held up through the load -
Test automation and integration write-back
Fire every workflow, assignment rule, sequence and notification, and confirm each integration writes correctly in both directions. Automation is rebuilt rather than migrated, so it is unproven until observed.
-
Sign off and schedule decommission
Get written acceptance against the Discovery criteria, keep Close read-only for 30-90 days with a final archive export taken, then diarise cancellation so the contract does not auto-renew.
Don't move on until
- Full reconciliation report complete across all objects
- Forecast and pipeline reports tie to pre-migration baselines
- Acceptance signed and Close decommission scheduled
Field mapping reference
The field-by-field mapping for each object. Use this as the starting point for your mapping spec.
CRM Object GoHighLevel Object
| Close field | HighLevel field | 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 |
| Tags | Tags | Close tags on Leads map to GHL tags on Contacts; straightforward but must be included in scope |
| User/Owner assignments | Assigned User | Close assigns users at the Lead, Contact, and Opportunity level; GHL assigns users on Contacts. Map team members before import and handle any structural differences (e.g., merged roles, departed reps) explicitly |
Risk matrix
Per-object risk for this pair. Plan extra validation around anything marked high.
| Object | Risk | Notes |
|---|---|---|
| Contacts | medium | Contacts map relatively well to GHL Contact records, but phone numbers must be normalized to E.164 format and email/phone deduplication logic must be carefully managed to prevent merge conflicts. |
| Companies (Leads) | medium | Close Leads representing companies must be mapped to either GHL Company objects or Contact fields, and GHL only allows one company association per contact, complicating multi-Lead relationships. |
| Opportunities | medium | Opportunities can be migrated to GHL Pipelines, but pipeline stages must be pre-created and each Close status must be explicitly mapped to a GHL stage before import. |
| Opportunity Custom Fields | high | GHL saves opportunity custom field data at the contact level, so per-deal granularity is lost when a single contact has multiple opportunities with differing custom field values. |
| Custom Fields | medium | All custom fields must be manually pre-created in GHL before import and data types must be matched, as there is no automatic schema migration between the two systems. |
| Activities (Calls, Emails, SMS) | high | Activity history can only be exported from Close as JSON and cannot be imported via GHL's CSV importer, requiring custom API-based injection or archival as external references. |
| Notes | high | GHL CSV import supports only one note per contact with a 5,000-character limit, meaning extensive Close activity notes, call summaries, and email logs will be silently truncated or lost. |
| Tasks | high | There is no direct CSV import path for tasks into GHL; they must be manually recreated or rebuilt using workflow triggers after migration. |
| Lead Status | medium | Close's Lead Status has no native GHL equivalent and must be mapped to tags or custom fields, which can break reporting if conflated with Pipeline Stages. |
| Tags | low | Tags can generally be mapped to GHL tags via CSV import columns, though naming conventions should be standardized before import to prevent duplicates. |
The hard parts
What makes this specific migration difficult, beyond the mechanics.
Lead-to-Contact Model Flattening
Close nests contacts, opportunities, tasks, and activities under a parent Lead object, which must be decomposed into GHL's flat Contact + Company + Opportunity structure without duplicating or collapsing records.
Activity History Export Complexity
Close only exports activity data (calls, emails, SMS, notes) in JSON format, which GHL's native CSV importer cannot accept, requiring custom parsing, transformation, and API injection.
Opportunity Custom Field Granularity Loss
GoHighLevel stores opportunity custom fields at the contact level rather than per-opportunity, so multiple Close Opportunities under one Lead with different custom field values will overwrite each other in GHL.
CSV Import Size and Note Limits
GHL CSV imports are limited to as low as 20 MB or 10,000 rows per file, only one note per contact (max 5,000 characters), making it impossible to carry detailed activity histories through the native importer.
Close API Pagination Constraints
Close's API limits responses to 100 records per request with a hard cap of 10,000 objects via the Advanced Filtering API, requiring date-range batching and multi-pass extraction for larger datasets.
Lead Status Has No Direct Equivalent
Close treats Lead Status and Opportunity Stage as separate concepts, but GHL has no native Lead Status field, requiring it to be mapped to tags or custom fields to avoid breaking post-migration reporting.
Tools used in this playbook
All free, all run entirely in your browser — nothing is uploaded.
FAQ
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.