API Reference
Errors and limits
How errors are shaped, what each code means, and the limits on requests.
Read an error
Errors are JSON. Branch your code on data.code, which won't change. why and fix are written for the developer reading them.
{
"error": true,
"status": 403,
"message": "This API key needs the employee:read scope",
"data": {
"code": "API_KEY_SCOPE_MISSING",
"why": "The key is valid, but it wasn't given employee:read when it was created.",
"fix": "Create a new key with this scope in Settings, under Developer."
}
}
A 400 also lists the problems under data.fieldErrors, by field, and problems with the request as a whole under data.formErrors. A 429 says how long to wait in a Retry-After header and in data.retryAfterSeconds.
Error codes
| Status | data.code | When it happens |
|---|---|---|
| 400 | API_QUERY_INVALID | A query parameter, or an ID in the path, is unknown or not in the right form |
| 400 | REQUEST_BODY_INVALID | The body has a field that is unknown, missing or out of range |
| 400 | METRIC_OBSERVATION_INVALID | The body of Send a metric value doesn't match the required fields |
| 401 | API_KEY_INVALID | The key is missing, wrong, expired or revoked |
| 403 | API_KEY_SCOPE_MISSING | The key wasn't given the scope this endpoint needs |
| 403 | PLAN_UPGRADE_REQUIRED | Your plan doesn't include the API |
| 403 | PLAN_HEADCOUNT_LIMIT | Adding this person would take you past the employees your plan covers |
| 403 | COMPANY_CLOSED | Your company has closed its Teambrite account |
| 404 | EMPLOYEE_NOT_FOUND | No employee in your company has this ID. data.employeeIds lists them when you sent several |
| 404 | GROUP_NOT_FOUND | Your company has no active group with this ID. data.groupIds lists them when you sent several |
| 404 | METRIC_OBSERVATION_NOT_FOUND | Your company has no metric value with this ID |
| 409 | METRIC_IDEMPOTENCY_CONFLICT | The idempotency key was already used with a different employee, metric or value |
| 409 | EMPLOYEE_EMAIL_TAKEN | Another employee has this email. data.employeeId says who |
| 409 | EMPLOYEE_EXTERNAL_ID_TAKEN | Another employee has this externalId. data.employeeId says who |
| 409 | GROUP_NAME_TAKEN | An active group with the same parent has this name. data.groupId says which |
| 409 | GROUP_PARENT_INVALID | The parent would put a group inside itself, or nest groups too deeply |
| 409 | GROUP_IN_USE | The group still has active members, active subgroups or programs |
| 411 | REQUEST_LENGTH_REQUIRED | The request didn't declare its length |
| 413 | REQUEST_TOO_LARGE | The body is over 1 MB |
| 422 | EMPLOYEE_INACTIVE | The employee is no longer active. data.employeeIds lists them when you sent several |
| 422 | METRIC_NOT_FOUND | Your company has no metric with this key |
| 422 | METRIC_ARCHIVED | This metric has been archived |
| 429 | API_KEY_RATE_LIMITED | The key is over 600 requests a minute |
| 429 | COMPANY_RATE_LIMITED | Your company is over 120 read requests a minute |
| 500 | METRIC_OBSERVATION_FAILED | A problem on our side. Resend with the same idempotency key |
Limits
- Requests: 600 a minute for each key. Over that, you get a
429. Wait for the number of seconds inRetry-After, then send it again. - Read requests: 120 a minute for your whole company, because some of them forecast up to a year of rewards. AI apps connected to your company share this limit. Get a metric value doesn't count toward it.
- Body size: 1 MB, with a declared
Content-Length.