Actions — Pitfalls
Writing a non-writable action type
Symptom. POST /lead/{leadId}/action returns 201 but the entry comes back as action_id: null, status: IGNORED, with the remark Custom action with code 'OUTGOING_CALL' not found.
Cause. The public API can only write custom actions and PAYMENT actions. Built-in types like OUTGOING_CALL, INCOMING_WHATSAPP_MSG, and LEAD_ASSIGNMENT are recorded automatically by telecrm in response to real events; they cannot be synthesized through the API.
There is no request-level rejection for this — a batch of nothing but built-in types still returns a success status with every entry ignored. Only get and update reject a non-writable type with a 400.
Fix. If you need to mark a call or message manually, create a custom action representing it and write that instead.
Using the ACTION_ prefix
Symptom. The custom action comes back IGNORED with Custom action with code 'ACTION_1001' not found.
Cause. The Sync API uses the bare numeric code for custom actions ("1001", "1002") on writes. The ACTION_ prefix ("ACTION_1001") is exclusive to the Async API. Reads are the other way round: get and search return type in the full ACTION_ form, and GET /custom-actions/{code} is looked up by it.
Fix. Drop the prefix. The format-comparison table is in Actions → The ACTION_ prefix.
diff
- { "type": "ACTION_1001", "fields": { "note": "..." } }
+ { "type": "1001", "fields": { "note": "..." } }Trying to change amount or currency on a payment
Symptom. POST /lead/{leadId}/action/{actionId} returns 400 with "Cannot update amount, currency, paymentid or employeeid fields for existing payment action".
Cause. Payment actions are immutable except for status. The amount, currency, external payment ID and recorded team member are locked in at creation.
Fix. Send only type and status in the update body. If the original payment data was wrong, void it (e.g. set status: CANCELLED) and create a new payment action with the correct values.
Per-action partial success on batch create
Symptom. Some actions in a batch are missing on the lead even though the request returned 201. Or an action was created, but one of its fields is empty.
Cause. POST /lead/{leadId}/action processes each action independently, and the two writable kinds fail differently:
- A
PAYMENTentry is all-or-nothing. Any invalid or missing value drops the whole entry —action_id: null,status: IGNORED. - A custom action is still created when a non-mandatory field fails validation. The entry reports
CREATEDwith a realaction_id, and only the bad field is dropped, reported inremarks. A missing mandatory field, by contrast, drops the whole entry.
Fix. Inspect the per-entry actions[].status and the remarks array — status: CREATED alone does not mean every field landed. Remarks are addressed as actions[<index>].fields.<apiName>, so you can map each one back to the entry it came from.
Using search to fetch a built-in action's full body
Symptom. Search returns matching INCOMING_CALL entries but GET /action/{actionId} on each one returns 400 BAD_REQUEST.
Cause. The single-action GET endpoint can only return custom, payment, and attachment actions. Built-in types appear in search results (so you can confirm activity occurred) but their full bodies are not exposed through the API.
Fix. Use search to count or detect, but expect that only type is meaningful for built-in entries. Open the lead in the dashboard for full call/message details.
Forgetting required payment fields on create
Symptom. Payment action returns IGNORED in remarks with a missing-field error.
Cause. A payment action requires type, status, currency, and amount together. Omitting any of them causes the entry to be dropped.
Fix. Always include all four. See Actions → PAYMENT for the full schema.