Errors
One error shape for every endpoint, and the codes worth branching on.
Every error — validation, auth, not found, rate limit, or ours — comes back with the same body:
{
"error": {
"code": "CATALOG_PRODUCT_NOT_FOUND",
"message": "The catalog product does not exist."
}
}Branch on code, never on message. The code is part of the contract and won't change under you. The message is a sentence for a human reading a log, and we reword it whenever a clearer one turns up.
Status codes
| Status | What it means |
|---|---|
400 | The request isn't valid — a bad parameter, a malformed body, a duplicate contact |
401 | The key is missing, malformed, revoked or expired |
404 | That resource doesn't exist in this organization. It may exist in another one; you get the same 404 either way |
409 | Conflict with the current state of the resource |
429 | Over the request limit — see Rate limits |
5xx | Ours. Retry with backoff; if it persists, write to support@trama.so |
The codes
| Code | Status | When |
|---|---|---|
VALIDATION_FAILED | 400 | A parameter or field didn't pass validation. The message names the field: contacts.0.phone: Required |
CRM_CUSTOMER_DUPLICATE_IDENTIFIER | 400 | Another customer already uses one of those contacts, or the same contact is repeated inside your payload |
CRM_CUSTOMER_INVALID_PHONE | 400 | The contact's phone number isn't usable |
API_KEY_MISSING | 401 | No Authorization and no x-api-key header |
API_KEY_INVALID | 401 | The key doesn't validate |
API_KEY_NOT_FOUND | 401 | The key was revoked, or never existed |
CUSTOMER_NOT_FOUND | 404 | |
OPPORTUNITY_NOT_FOUND | 404 | |
CONVERSATION_NOT_FOUND | 404 | |
QUOTE_NOT_FOUND | 404 | |
CATALOG_PRODUCT_NOT_FOUND | 404 | |
NOT_FOUND | 404 | The endpoint itself doesn't exist. Check the method and the path |
API_KEY_RATE_LIMITED | 429 | See Rate limits |
A code you don't recognize is still safe to handle. New codes get added as the API grows, so treat the list above as the ones worth branching on and everything else as "an error of this status". What won't happen is an existing code changing meaning.
Reading a validation error
VALIDATION_FAILED puts the offending field at the front of the message, as a dotted path into what you sent:
{ "error": { "code": "VALIDATION_FAILED", "message": "limit: Number must be less than or equal to 100" } }That path is the useful part. The sentence after it comes from the schema and may be reworded.
What you won't get
- No stack traces and no internal details. A
5xxsays the request couldn't be completed and nothing else — on purpose. - No error text in Spanish. The dashboard is in Spanish and the domain code underneath it is too; the API translates at the boundary, so a caller never gets a message in a language they didn't ask for. If one ever slips through, that's a bug worth reporting.