Troubleshooting
CRM — Troubleshooting
The most common failures, and the one-line fix. See also the platform-wide Errors reference.
400 "Field 'X' is required"
You keyed the data body by the field's display name/label instead of its
slug. The required check looks for the field's slug key (e.g. name-8fk2),
doesn't find it, and reports the field missing. Fix: key data by field slug —
fetch slugs from GET /object/:objectSlug/fields. This is the single most common
CRM mistake.
400 on create/update — bad value
- A
select/multi_select/status/priority/tagvalue that isn't one of the field's allowed options → validation fails after the required check. Send an exact option value. - Wrong type for the field (text into a
number, bademail/dateformat) → the per-type validator rejects it. Check themessagearray. - Missing
dataobject entirely →datamust be an object (IsObject).
401 Unauthorized
Missing, malformed, or expired credential. Re-authenticate and send either
Authorization: Bearer <jwt> or X-Api-Key: crtk_live_…. An unknown or
revoked API key also returns 401.
403 Forbidden
You're authenticated but lack the permission/scope for this object:
- API key — the key's
scopesdon't include the route name, e.g.create.contacts. Add the scope (or aread.*/create.*wildcard). - JWT — your role's access level on the object is too low. Creating needs the
object's
addright; reading/updating/deleting needview/edit/delete≠D. See Authorization. - Trying export/import, views, relations, comments, or analytics with an API key — those endpoints are admin-JWT only and reject API keys.
404 on a record you "know" exists
Not always missing — a record outside your visibility is masked as 404
(so you can't probe for rows you can't see). If it should be visible, your access
level is too low (M/G but it's someone else's) — raise the level or reassign
the record. Otherwise re-check the object/record slug (slugs, never numeric
ids).
The select dropdown is empty / options rejected
Fetch the field's options with GET /object/data/:objectSlug/field-options/:fieldSlug
(select-family) or GET /object/data/select-options/:objectSlug/:fieldSlug
(relation fields), and send an exact value.
Import / export "hasn't finished"
Large import/export runs as an async Bull job. The POST returns a jobSlug;
poll GET /object/data/:objectSlug/{import|export}/status/:jobSlug until
status = COMPLETED, then download. A job is owned by its creator — another
admin polling it gets 403.
My webhook doesn't fire
- Confirm the subscription's
events[]includes the event (record.created/record.updated/record.deleted) andtarget_urlis HTTPS. - A write made by your own API key is intentionally not delivered back to that key's subscription (loop prevention) — test with a different actor.
- Deliveries retry on non-2xx; return 200 fast. See Webhooks.