Errors
Errors are JSON with an error field:
{ "error": "validation_failed", "details": [{ "field": "email", "code": "invalid_email" }] }Newer endpoints use stable lowercase codes, safe to branch on. Older endpoints (website analytics, inbound webhooks) send a short English message instead; branch on the HTTP status there.
Status codes
Section titled “Status codes”| Status | Meaning | Retry? |
|---|---|---|
200 / 201 |
Done / created | — |
400 |
The request is malformed (bad JSON, missing required parameter) | No, fix it |
401 |
No key, wrong key, revoked or rotated key, or a key that may not call this endpoint | No, fix the key |
403 |
The key is valid but not for this: another workspace’s webinar, or an access level this endpoint does not accept | No |
404 |
Not found in this workspace | No |
405 |
Wrong HTTP method | No |
413 |
Body too large | No, send less |
422 |
Valid JSON, wrong fields; details lists each one |
No, fix the fields |
429 |
Rate limit; wait Retry-After seconds |
Yes, after the wait |
5xx |
Our side | Yes, with exponential backoff |
By endpoint
Section titled “By endpoint”POST /v1/contacts
Section titled “POST /v1/contacts”| Status | error |
|---|---|
400 |
invalid_json |
401 |
unauthorized |
403 |
forbidden |
405 |
method_not_allowed |
413 |
payload_too_large |
422 |
validation_failed, with details[].code from the list on the Contacts page |
429 |
rate_limited |
500 |
internal |
POST /v1/webinar-registrants
Section titled “POST /v1/webinar-registrants”| Status | error |
|---|---|
400 |
invalid_json, no_registrants, batch_too_large, webinar_required |
401 |
unauthorized |
403 |
forbidden |
404 |
webinar_not_found |
405 |
method_not_allowed |
429 |
rate_limited |
500 |
internal |
Per registrant, inside a 200: consent_required, invalid_registrant, email_or_phone_required,
valid email required, validation_failed, webinar_full, internal.
GET /v1/api-v1 (website analytics)
Section titled “GET /v1/api-v1 (website analytics)”400 Missing site_id · 400 Unknown action · 401 Unauthorized · 404 Site not found · 429 rate_limited
Inbound webhooks (hook.nexacloser.com)
Section titled “Inbound webhooks (hook.nexacloser.com)”400 Missing webhook slug · 401 Unauthorized — x-webhook-token header required ·
401 Unauthorized · 404 Webhook not found · 413 payload_too_large · 429 rate_limited
MCP (/mcp)
Section titled “MCP (/mcp)”401 with JSON-RPC error -32001 Unauthorized. Tool failures are 200 with result.isError: true
and the reason as text. See MCP.
Retrying safely
Section titled “Retrying safely”POST /v1/contactsmatches on phone and email, so repeating it updates the same contact.POST /v1/webinar-registrantsreturns the existing registration for a repeat (duplicate: true).- Inbound webhooks drop an identical body sent within 2 minutes (
deduped: true).
So retrying after a timeout or a 5xx does not create doubles. The one exception is a workspace
that allows duplicate contacts.
