Documentation Index
Fetch the complete documentation index at: https://docs.recotap.com/llms.txt
Use this file to discover all available pages before exploring further.
All errors use a consistent envelope. The exact shape differs slightly between validation errors and business logic errors.
Validation errors (400 from DTO checks, fired before any database call):
{
"statusCode": 400,
"timestamp": "2026-04-28T10:15:00.000Z",
"path": "/api/v1/crm/accounts",
"message": "Bad Request",
"data": [
{
"property": "domain",
"constraints": { "isNotEmpty": "domain should not be empty" }
}
]
}
data contains the raw class-validator error objects. There is no customMessage on validation errors.
Business logic errors (thrown by the service or controller):
{
"statusCode": 400,
"timestamp": "2026-04-28T10:15:00.000Z",
"path": "/api/v1/crm/accounts",
"message": "Bad Request",
"customMessage": "Segment 'abc' is not active or draft and cannot accept new members",
"data": null
}
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 | externalId — missing | externalId must be a string |
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/:externalId | domain field included in request body | Domain cannot be updated via this endpoint |
PUT /accounts/:externalId | 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/:externalId | No account matches externalId | Account with externalId '<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 | Duplicate externalId — use PUT to update |
POST /accounts | failed | Unknown custom field key in customFields |
POST /deals | failed | Deal upsert failure |
POST /sales-activities | failed | Duplicate externalActivityId |
POST /sales-activities | skipped | activityType is not call or email |