400 from DTO checks, fired before any database call):
data contains the raw class-validator error objects. There is no customMessage on validation errors.
Business logic errors (thrown by the service or controller):
customMessage is present only when the service explicitly sets it. Use it for logging and user-facing messages.
401 Unauthorized
Applies to every endpoint.| Condition | customMessage |
|---|---|
X-Api-Key header missing | X-Api-Key header is required |
| Key not found or invalid | Invalid API key |
400 Bad Request — validation
Fires before any database call.data contains the raw class-validator error objects.
| Endpoint | Field / rule | Example customMessage |
|---|---|---|
POST /accounts | accounts — empty or missing | accounts must be an array |
POST /accounts | accounts — more than 100 items | accounts must contain no more than 100 elements |
POST /accounts | domain — missing | domain should not be empty |
POST /accounts | name — missing | name should not be empty |
POST /deals | deals — more than 100 items | deals must contain no more than 100 elements |
POST /deals | externalDealId — missing | externalDealId should not be empty |
POST /deals | startDate / closedDate — not ISO 8601 | startDate must be a valid ISO 8601 date string |
POST /deals | ownerEmail — not a valid email | ownerEmail must be an email |
POST /sales-activities | activities — more than 50 items | activities must contain no more than 50 elements |
POST /sales-activities | occurredAt — missing or not ISO 8601 | occurredAt must be a valid ISO 8601 date string |
POST /sales-activities | domain — missing | domain should not be empty |
POST /sales-activities | ownerEmail — missing or invalid | ownerEmail must be an email |
POST /sales-activities | contacts — missing or empty | contacts must contain at least 1 elements |
POST /sales-activities | direction — not inbound or outbound | direction must be one of the following values: inbound, outbound |
POST /accounts/custom-field | label — missing | label should not be empty |
POST /accounts/custom-field | labelType — invalid value | labelType must be one of the following values: singleLineText, ... |
POST /accounts/custom-field | options — missing when required | options must contain at least 1 elements |
GET /accounts | lastSync — invalid format | lastSync must be a valid ISO 8601 date string |
PATCH /accounts/external-ids | mappings — more than 100 items | mappings must contain no more than 100 elements |
400 Bad Request — business logic
| Endpoint | Condition | customMessage |
|---|---|---|
POST /accounts | segmentId not found | Segment '<id>' not found |
POST /accounts | segmentId is a dynamic segment | Segment '<id>' is not a static segment |
POST /accounts | segmentId status is not active or draft | Segment '<id>' is not active and cannot accept new members |
PUT /accounts/:rtp_aid | rtp_aid is not a valid format | Invalid rtp_aid format |
PUT /accounts/:rtp_aid | customFields keys not defined | Custom field key(s) not found: KEY_C. Unable to update this account. |
404 Not Found
| Endpoint | Condition | customMessage |
|---|---|---|
PUT /accounts/:rtp_aid | No account matches rtp_aid | Account with rtp_aid '<id>' not found |
500 Internal Server Error
message is always Internal server error. Do not parse customMessage — use it for logging only. Safe to retry with exponential back-off.
Per-item errors in batch endpoints
POST /accounts, POST /deals, and POST /sales-activities always return HTTP 200. Check each item’s status field in results.
| Endpoint | Item status | Cause |
|---|---|---|
POST /accounts | failed | Domain already exists — use PUT /accounts/:rtp_aid to update |
POST /accounts | failed | Unknown custom field key in customFields |
POST /deals | failed | Pipeline already exists e.g. Pipeline(s) already exist: smb-pipeline |
POST /sales-activities | failed | Duplicate externalActivityId |
POST /sales-activities | skipped | activityType is not call or email |