Leads — Pitfalls
Trying to change the lead identifier
Symptom. POST /lead/{leadId} returns 403 INVALID_LEAD with "Cannot modify lead identifier field".
Cause. The workspace's lead identifier (default: phone) is immutable after creation.
Fix. Remove the identifier from the update body. If you genuinely need to change it (e.g. correct a typo), do it manually in the dashboard.
Treating a 200/201 as full success
Symptom. Some custom fields or initial actions are missing on the created lead despite the API returning a successful status.
Cause. POST /lead and POST /lead/{leadId}/action support partial success. Fields and actions that fail validation are dropped silently and reported in the remarks array; the rest succeed.
Fix. Always inspect remarks and the per-action status array. Anything with status: IGNORED did not persist.
Sending search criteria as query parameters
Symptom. 404 or 405 from GET /lead/search?phone=....
Cause. Search is POST with a JSON body — not a GET. Only skip and limit are query parameters.
Fix. Issue a POST to /lead/search with the filters in the request body. See Search leads.
Creating a duplicate lead
Symptom. POST /lead returns 409 LEAD_ALREADY_EXISTS.
Cause. A lead with the same identifier value already exists in the workspace.
Fix. Either fall through to POST /lead/{leadId} to update the existing lead, or use the Async API which performs create-or-update automatically based on the identifier.
Pagination beyond the page cap
Symptom. 400 BAD_REQUEST with "Limit should be between 1 and 100".
Cause. limit on lead search and lead-actions inclusion is capped at 100.
Fix. Cap your page size at 100 and paginate via skip for larger result sets. The response includes total_count to compute how many pages remain.
Searching for unknown statuses
Symptom. fields.status filter returns no results even though leads with that status exist in the dashboard.
Cause. Status values are matched case-sensitively against the workspace's lead stage pipeline. Display labels can differ subtly from what the dashboard shows (extra whitespace, trailing characters).
Fix. Fetch the canonical labels via GET /lead-stage-pipeline and use those exact strings.
Using ISO 8601 dates
Symptom. Date filters (fields.created_on, actions.performed_at) return zero results or wrong matches.
Cause. Date inputs accept Unix milliseconds or the workspace-configured date format string. ISO 8601 (e.g. "2026-01-01T10:30:00Z") is not parsed.
Fix. Use one of the supported formats. See Field Types → date.