Sooner or later every agency needs to compare custom fields between sub-accounts. A workflow works in one client's account and fails silently in another. A snapshot was loaded months ago and both sides have drifted. A client wants their intake form copied to a second location. In each case the question is the same: what's in sub-account A that isn't in B, and does what matches actually match?
This guide covers the native ways to answer that, what to check beyond "missing fields," and where a dedicated compare tool helps.
What you are really looking for
A useful comparison catches more than missing fields. When we audit sub-accounts, these are the four problems that cause real breakage:
| Problem | Example | What breaks |
|---|---|---|
| Missing field | "Bank Statement 3" exists in A, not B | Forms and workflows that write to it |
| Different key, same name | "Monthly Revenue" is monthly_revenue in A and monthly_revenue_2 in B |
Merge tags and webhooks copied from A |
| Same key, different type | industry is a dropdown in A, single line text in B |
Smart list filters, conditions, integrations expecting set options |
| Different dropdown options | "Lenders" has 12 options in A, 8 in B | Checkbox and dropdown values that don't exist on the other side |
Keep that table in mind for whichever method you use.
How to compare custom fields between sub-accounts natively
Method 1: Side by side in two browser tabs
- Open sub-account A, go to Settings, then Custom Fields, and pick the object.
- Open sub-account B in a second tab and go to the same page.
- Work through folder by folder, checking name, type and key.
This is fine for a dozen fields. It falls apart past 50, and it's easy to miss a key that differs by a suffix.
Method 2: Export both lists through the API
The more reliable native-ish route is to pull both field lists and diff them in a spreadsheet.
- Get a token for each sub-account with the
locations/customFields.readonlyscope. Our Private Integration token guide walks through it. - Call
GET /locations/{locationId}/customFields?model=contactfor each, with theVersion: 2021-07-28header. Repeat withmodel=opportunity. - Convert each JSON response to a sheet with columns for
name,fieldKeyanddataType. - Use a lookup on
fieldKeyto flag keys present in one sheet and not the other. - Add a second lookup comparing
dataTypefor keys that match.
Dropdown options come back in the response too, but comparing them in a spreadsheet takes extra work since they're arrays.
Method 3: Re-push a snapshot
If both sub-accounts came from the same snapshot, you can update the snapshot from your source account and push it to the target. That adds fields the target is missing. It doesn't tell you what was different first, and it won't fix a field whose type changed, so it pairs well with Method 2 rather than replacing it.
Don't forget custom values and opportunity fields
A field comparison that only covers contact fields misses a lot. Opportunity fields have their own list, and custom values often hold the booking links and company details that messages depend on. Run the same comparison with model=opportunity, and pull custom values with GET /locations/{locationId}/customValues (scope locations/customValues.readonly). For custom values, compare names and keys, but expect the values themselves to differ between clients. That's the point of them.
When to run a comparison
- Before copying a workflow, form or webhook from one client to another.
- After loading or re-pushing a snapshot.
- When a merge tag works in one sub-account and comes back blank in another.
- As a quarterly check on any sub-accounts that are meant to stay identical.
Fixing what you find
- Missing fields: create them in the target, ideally with the same names so the generated keys match. If you have a lot, see how to bulk create custom fields in GoHighLevel.
- Key mismatch: decide which key is canonical and update your merge tags, webhooks and form mappings to match. Renaming a field doesn't reliably rename its key.
- Type mismatch: HighLevel doesn't let you change a field's type after creation. Create a new field with the correct type, move data over with a workflow or import, then retire the old one.
- Option drift: add the missing options to the dropdown, checkbox or radio field in the target.
Where the native way gets slow
The API method works, but it's a lot of setup for something you'll do every time you onboard or troubleshoot a client. You need a token per sub-account, a script or converter for the JSON, and a spreadsheet you rebuild each time. Custom object fields and custom values are separate calls on top of that.
Manual comparison is quicker to start but is exactly where "same name, different key" slips through.
How Field Finder handles it
Field Finder's sub-account compare does the diff for you. Pick sub-account A and sub-account B, and it shows every field that exists in one but not the other, plus any key whose type changed. We built it for keeping our own snapshot-based sub-accounts in sync.
Because one connection covers your whole agency, there's no token juggling per comparison. You can export the results to CSV and use that as the checklist for the fixes above. Field Finder is read-only, so the compare never changes either sub-account; you make the fixes yourself or with Sub-Account Manager.
For a one-off check between two small accounts, the two-tab method is enough. For an agency running the same build across many clients, an automatic diff catches the problems that eyes miss.
Questions
Can GoHighLevel compare custom fields between two sub-accounts?
As of October 2026 there is no native side-by-side comparison. You can compare the Custom Fields pages manually, export both field lists through the API into a spreadsheet, or use a third-party tool.
Why do workflows break when I copy them to another sub-account?
Usually because a field the workflow references doesn't exist in the target sub-account, or exists with a different key or type. Compare the field lists before you copy.
Can I change a custom field's type after creating it?
No. HighLevel doesn't allow changing a field's type after creation. If two sub-accounts have the same key with different types, you have to recreate the field with the right type and move the data.