Docs / Core concepts
Errors
Status codes, the error object, and how to handle and retry failures safely.
Beta. The Trimline API is available to private beta customers. Endpoints may change before general availability in June 2027, and every breaking change is announced in the changelog. Request access.
Trimline uses conventional HTTP status codes. Codes in the 2xx range mean the request succeeded, 4xx codes mean something about the request needs fixing, and 5xx codes mean something went wrong on our side.
Error object
Every error response has the same shape, so you can handle errors in one place.
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "notice_deadline[lte] must be a date in YYYY-MM-DD format.",
"param": "notice_deadline[lte]",
"request_id": "req_Q2m8xVb41Kd",
"doc_url": "https://trimline.tech/docs/errors/#parameter_invalid"
}
}
typeenum | The broad category of the error. See the table below. |
codestring | A stable, machine-readable code. Branch on this, not on message. |
messagestring | A human-readable explanation. The wording may change, so don’t parse it. |
paramstring, nullable | The request parameter the error relates to, if there is one. |
request_idstring | Include this whenever you contact support. It’s also returned in the Request-Id header. |
HTTP status codes
| Status | Meaning |
|---|---|
200 OK | The request succeeded. |
201 Created | A new object was created. |
400 Bad Request | The request was malformed or a parameter was invalid. |
401 Unauthorized | No API key was sent, or the key is invalid or revoked. |
403 Forbidden | The key is valid but lacks the required scope. |
404 Not Found | The object doesn’t exist, or belongs to the other environment. |
409 Conflict | The object’s state doesn’t allow this action, such as approving a draft that was already sent. |
422 Unprocessable | The request was well-formed but couldn’t be carried out, for example because a mailbox connection has expired. |
429 Too Many Requests | You’ve hit a rate limit. Retry after the time given in the Retry-After header. |
500, 502, 503 | Something went wrong on our side. These are rare, and safe to retry with backoff. |
Error types
| Type | When it happens |
|---|---|
authentication_error | The key is missing, malformed, expired or revoked. |
permission_error | The key doesn’t have the scope this endpoint requires. |
invalid_request_error | A parameter is missing or invalid, or the object wasn’t found. |
state_error | The object isn’t in a state that allows this action. |
connection_error | A connected mailbox or finance account needs to be reauthorized. |
rate_limit_error | Too many requests in a short period. |
api_error | An unexpected problem on our side. |
Common codes
| Code | What to do |
|---|---|
parameter_missing | Add the parameter named in param. |
parameter_invalid | Check the type and format against the endpoint reference. |
resource_missing | Check the ID, and check you’re using a key for the right environment. |
insufficient_scope | Create a key with the scope listed in message. |
draft_not_pending | The draft was already approved, sent, held or discarded. Fetch it to see its current status. |
notice_deadline_passed | The contract can no longer be cancelled for this term. Negotiation is still possible, but you have less leverage. |
connection_expired | Ask the account owner to reconnect the mailbox from the dashboard. |
idempotency_key_reused | The same key was sent with a different request body. Generate a new key. |
Retrying safely
Retry 429 and 5xx responses with exponential backoff and jitter, starting at about 500 ms. Don’t retry other 4xx errors without changing the request. For POST requests, always send an idempotency key so that a retry can’t approve the same draft twice.
Something unclear or missing? Email developers@trimline.tech.