> ## Documentation Index
> Fetch the complete documentation index at: https://developers.teambuilder.ge/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> One error shape for every failure, stable machine-readable codes, and a request ID for support.

TeamBuilder uses conventional HTTP status codes: `2xx` for success, `4xx` for a problem with the request, `5xx` for a problem on our side. Every error response has the same body:

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "Employee not found",
    "request_id": "req_7hT3mQ9xLc2VbN8rKw4pZa"
  }
}
```

| Field | Use it for |
| - | - |
| `code` | Branching in your code. Codes are stable within `/v1`. |
| `message` | Logs and debugging. Written for developers; wording can change, so never match on it. |
| `request_id` | Support. The same value is in the `X-Request-Id` header of every response, successful or not. |

## Error codes

| HTTP | `code` | Meaning | Retry? |
| - | - | - | - |
| `400` | `validation_failed` | A parameter, body field or cursor is invalid, or the body is not JSON. The message names the field and rule. | No, fix the request |
| `401` | `unauthorized` | Missing, malformed, unknown, revoked or expired key. | No |
| `403` | `forbidden` | The key lacks the endpoint's [scope](/authentication#scopes). | No |
| `404` | `not_found` | The resource does not exist in your company, the employee is deactivated, or the path or method is not supported. | No |
| `409` | `conflict` | Another roster sync of your company is running (sent with `Retry-After`), or a write clashed with existing data. | Yes, after `Retry-After` when present |
| `411` | `length_required` | A sync body was sent without a `Content-Length` header. | No, fix the client |
| `413` | `payload_too_large` | The body exceeds the size limit (16 MB for a sync, 100 KB elsewhere). | No, send fewer rows |
| `4xx` | `bad_request` | Any other client error. | No |
| `429` | `rate_limit_exceeded` | A [rate limit](/reference/rate-limits) was hit. Sent with `Retry-After`. | Yes, after `Retry-After` |
| `500` | `internal_error` | Something failed on our side. | Yes, with backoff |

Several validation problems in one request are reported together in `message`, separated by `; `.

<Note>
  New codes may be added within `/v1`. Treat an unknown `code` by its HTTP status: an unknown `4xx` is a client error, an unknown `5xx` a server error.
</Note>

## Roster sync row errors

[`PUT /v1/employees/sync`](/guides/roster-sync) reports problems with individual rows **inside a `200` response**, in its `errors` and `warnings` arrays, while the valid rows still apply. Those row codes (`duplicate_external_id`, `external_id_mismatch`, `unknown_department` and others) are listed in the [roster sync guide](/guides/roster-sync#row-errors-and-warnings).

## Retrying safely

* **Retry** `429`, `409` (after `Retry-After`), `500` and network errors, with exponential backoff and jitter, for example 1, 2, 4 and 8 seconds. Give up after a few attempts.
* **Do not retry** other `4xx` responses unchanged: they fail the same way every time.
* All read endpoints and the roster sync are **idempotent**, so a retry after a timeout never duplicates anything.

## Contacting support

Email [contact@teambuilder.ge](mailto:contact@teambuilder.ge) with:

* the `request_id`,
* the endpoint and the approximate time (with time zone),
* what you expected and what happened.

The request ID lets us find the exact request in our logs. Never include your API key: we do not need it, and anyone who sees it could use it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.