Skip to content

Enterprise Metadata — Pitfalls

detail=true and detail=false return different shapes

Symptom. Code that parses detail=true responses crashes when called with detail=false (or vice versa) — missing keys, wrong types.

Cause. GET /custom-fields and GET /custom-actions return materially different shapes per detail mode. Summary mode returns a few labels; detailed mode returns IDs, schemas, descriptions, timestamps, and (for fields) typed options[] instead of plain strings.

Fix. Pick one mode for your client and stick with it. If you don't need the extra metadata, default to detail=false for smaller payloads. If you read both modes, branch on the presence of an id key on each item.

Sending API names with wrong casing

Symptom. GET /custom-fields/{apiName} returns 404 NOT_FOUND for a field that exists in the dashboard.

Cause. API names are case-sensitive. Contact_Source, contact_source, and CONTACT_SOURCE are three different lookups.

Fix. Get the canonical casing from GET /custom-fields, or copy the value from Settings → Lead Fields → click the field → Properties → API name in the dashboard.

Treating archivedStatuses and archivedLeadLostReasons as valid values

Symptom. Lead create or update with status: "Old Status" succeeds but the field is missing on the resulting lead.

Cause. Archived statuses and lost reasons are returned by GET /lead-stage-pipeline so historical leads remain readable, but they cannot be used as values on new or updated leads. Only activeStatuses[].label and activeLeadLostReasons[].reasonLabel are accepted.

Fix. Filter out the archived* arrays when building the set of valid values to expose to your users.

Looking up a custom action with the wrong code format

Symptom. GET /custom-actions/{code} returns 404 even though the action exists.

Cause. The path parameter takes the full code (ACTION_1001), but the Sync action payload uses the bare numeric ("1001"). It's easy to mix them up.

Fix. When calling the lookup endpoint, use the full ACTION_<numeric> form. When sending an action via create, strip the prefix.

diff
# Lookup endpoint
- /custom-actions/1001
+ /custom-actions/ACTION_1001

# Action create payload
- { "type": "ACTION_1001" }
+ { "type": "1001" }

Caching metadata forever

Symptom. A custom field renamed in the dashboard breaks payloads, or a newly-added option silently mismatches.

Cause. Custom fields, custom actions, and the lead stage pipeline are mutable in the dashboard. Stale caches drift from reality.

Fix. Refresh metadata at integration startup and on a slow cadence (e.g. every 15 minutes). The endpoints are cheap and idempotent — there's no rate concern about polling them periodically.

Confusing leadIdentifierFieldId with the API name

Symptom. Lead payloads use leadIdentifierFieldId (e.g. phone) as the key — works for default workspaces but fails for workspaces using a custom identifier with a different ID and API name.

Cause. leadIdentifierFieldId from GET /metadata is a field ID, not a guaranteed API name. For default phone identifiers the two happen to match, but for custom text identifiers they can differ.

Fix. Always join with GET /custom-fields?detail=true: match customFields[].id against leadIdentifierFieldId, then read apiName from the matching entry. The Examples page shows the full pattern.