Errors
When a request fails, the API returns the standard envelope with success: false and an error object:
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Validation error: Enter a team name. at \"name\""
}
}
code: a stable, machine-readable string. Branch on this in your code. Do not parse the message.message: a human-readable description. For validation, permission and business-rule errors, it says what failed. For a temporary or job failure, it says what to do. For an internal error, it is generic, so that it does not show internal details.
Status codes
| HTTP status | code | When it happens |
|---|---|---|
400 | BAD_REQUEST | The request did not pass validation (a field, a path parameter or a query parameter), or it breaks a business rule |
400 | VALIDATION_FAILED | The request is well-formed, but a value cannot be used. For example, an uploaded file is not a supported image, a data query has an unknown field ID, or a data query failed without a cause |
401 | UNAUTHORIZED | The token is missing, malformed, expired or revoked |
402 | PAYMENT_REQUIRED | The team's plan is cancelled. Reactivate the plan to make changes |
402 | PLAN_LIMIT_REACHED | Enabling the account would go over the plan's per-connector account limit |
403 | FORBIDDEN | The key holder is not a member of the team, or the key's intended use is not API |
403 | INSUFFICIENT_ROLE | The key holder's role does not include the team permission that the endpoint needs |
403 | INSUFFICIENT_PERMISSIONS | The API key does not have the scope that the endpoint needs. The message names the missing scope |
404 | NOT_FOUND | The resource does not exist, or it belongs to another team |
409 | CONFLICT | The request conflicts with the current state. For example, the account is already assigned to the client |
413 | PAYLOAD_TOO_LARGE | The request body or the uploaded file is larger than the limit |
429 | TOO_MANY_REQUESTS | You went over a rate limit |
429 | PROVIDER_RATE_LIMITED | The ad platform or data source limited a data query. Wait, then send it again |
500 | INTERNAL_SERVER_ERROR | An unexpected error on our side |
503 | UPSTREAM_JOB_TIMEOUT | A data query did not finish within the time limit of the server |
504 | None | The request took too long and stopped before our API replied. The body is not JSON. At this time, a data query that takes more than about 60 seconds can get this |
A failed data query can also return the code of its cause, for example AUTH_TOKEN_EXPIRED when a connection must be reconnected. The run-query errors list each one. Use the HTTP status to decide if you can retry, and the code to find the cause.
Permission and seat errors
Each of these has its own code rather than one FORBIDDEN, because each has a different fix. A client that cannot tell them apart cannot tell the caller what to do. See Roles and permissions.
| HTTP status | code | What it means | How to fix it |
|---|---|---|---|
403 | INSUFFICIENT_ROLE | The key holder's role does not include the team permission that the endpoint needs. | Ask an Admin for a role that includes it. A seat will not help. |
403 | SEAT_REQUIRED | The key holder's role allows this, but they have no seat in the team. Every permission that needs a seat is withheld. | Ask an Admin to assign them a seat. Changing their role will not help. |
403 | ROLE_NOT_ASSIGNABLE | You tried to assign a role that includes permissions you do not hold yourself. | Ask someone with those permissions to assign it. |
403 | CANNOT_ACT_ON_MEMBER | The member you are changing holds permissions you do not. You can only change members whose permissions are a smaller set than yours. An equal role is refused too. | Ask an Admin. |
403 | CANNOT_ACT_ON_SELF | You cannot change your own role or seat, not even to reduce it. | Ask another Admin to do it. |
403 | CANNOT_ACT_ON_OWNER | Nobody can change the team owner's role or remove the team owner. | Contact support to change who the owner is. |
402 | SEAT_LIMIT_REACHED | Every seat on the plan is assigned. | Unassign a seat, or add seats to the plan. |
SEAT_REQUIRED and INSUFFICIENT_ROLE look similar, but they are different problems. INSUFFICIENT_ROLE means the role does not include the action, so somebody has to change the role. SEAT_REQUIRED means the role does include it and nobody has assigned a seat, so somebody has to assign one. If you tell a customer the wrong one, you send them to the wrong colleague.Examples
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Invalid UUID: \"abc\""
}
}
The key holder is not a member of the team, or the team does not exist. The message is the same in both cases.
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "Access denied"
}
}
The message names the key holder, the team permission and their role.
{
"success": false,
"error": {
"code": "INSUFFICIENT_ROLE",
"message": "[email protected] is not allowed to use connections.delete. This needs a role that includes it; their role is viewer."
}
}
The key does not have the scope that this endpoint needs. The message names it.
{
"success": false,
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "This API key is missing the `clients:delete` permission required for this endpoint. Grant it to the key under Settings → API Keys (https://hub.twominutereports.com/settings?tab=user-api-keys), or use a key that has it."
}
}
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Client not found"
}
}
{
"success": false,
"error": {
"code": "PAYMENT_REQUIRED",
"message": "Your team's plan has been cancelled. Please reactivate your subscription to continue."
}
}