Errors and rate limits
The error format, the error code catalog and the rate limit headers.
Error format
All errors follow RFC 9457 Problem Details, returned as application/problem+json:
{
"type": "https://api.lingohub.com/errors/validation-failed",
"title": "Validation failed",
"status": 422,
"detail": "The request contains invalid fields.",
"instance": "/v2/projects",
"code": "validation_failed",
"request_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"errors": [
{
"pointer": "#/name",
"parameter": null,
"code": "minLength",
"detail": "must be at least 2 characters long"
}
]
}| Field | Meaning |
|---|---|
code | Machine-readable error code. Use it, not title or detail, in your error handling. |
type | Link to a page that explains the error. |
title | Short, constant summary of the error. |
status | HTTP status code. |
detail | Human-readable explanation of this occurrence. |
instance | Path of the request that failed. |
request_id | Correlation ID, also in the X-Request-ID header. Quote it when you contact support. |
errors | Rejected fields or parameters, when the problem concerns specific input. pointer locates a body field (JSON Pointer), parameter a query, path or header parameter or a multipart field. |
required_permission | On 403, the permission the API key is missing. |
A resource your key isn't allowed to see can return 404 resource_not_found, the same as one that doesn't exist.
Error codes
| Code | HTTP status | Meaning |
|---|---|---|
invalid_json | 400 | Invalid JSON |
invalid_parameter | 400 | Invalid parameter |
unexpected_request_body | 400 | Unexpected request body |
missing_parameter | 400 | Missing parameter |
unknown_parameter | 400 | Unknown parameter |
invalid_filter | 400 | Invalid filter |
invalid_cursor | 400 | Invalid cursor |
bad_request | 400 | Bad request |
missing_api_key | 401 | Missing API key |
invalid_api_key | 401 | Invalid API key |
expired_api_key | 401 | Expired API key |
revoked_api_key | 401 | Revoked API key |
disabled_api_key | 401 | Disabled API key |
insufficient_permissions | 403 | Insufficient permissions |
resource_not_found | 404 | Resource not found |
route_not_found | 404 | Route not found |
method_not_allowed | 405 | Method not allowed |
not_acceptable | 406 | Not acceptable |
precondition_failed | 412 | Precondition failed |
content_too_large | 413 | Content too large |
unsupported_media_type | 415 | Unsupported media type |
already_exists | 409 | Already exists |
idempotency_outcome_unknown | 409 | Idempotency outcome unknown |
idempotency_key_in_use | 409 | Idempotency key in use |
stack_not_empty | 409 | Stack not empty |
branch_not_ready | 409 | Branch not ready |
backup_not_ready | 409 | Backup not ready |
backup_in_use | 409 | Backup in use |
distribution_release_not_ready | 409 | Distribution release not ready |
distribution_release_counts_unavailable | 409 | Distribution release counts unavailable |
distribution_release_empty | 409 | Distribution release empty |
import_not_cancellable | 409 | Import not cancellable |
task_not_open | 409 | Task not open |
task_not_closable | 409 | Task not closable |
task_not_skippable | 409 | Task not skippable |
default_branch_protected | 409 | Default branch protected |
owner_membership_protected | 409 | Owner membership protected |
source_language_protected | 409 | Source language protected |
branch_limit_reached | 409 | Branch limit reached |
context_image_limit_reached | 409 | Context image limit reached |
translation_order_pending | 409 | Translation order pending |
git_integration_not_configured | 409 | Git integration not configured |
git_integration_unauthorized | 409 | Git integration unauthorized |
conflict | 409 | Conflict |
validation_failed | 422 | Validation failed |
idempotency_key_mismatch | 422 | Idempotency key mismatch |
rate_limit_exceeded | 429 | Rate limit exceeded |
internal_error | 500 | Internal error |
upstream_error | 502 | Upstream error |
service_unavailable | 503 | Service unavailable |
upstream_timeout | 504 | Upstream timeout |
Rate limits
Requests are limited per API key and per workspace, where the workspace limit counts all of its keys together. When you exceed either limit, the API answers 429 rate_limit_exceeded with a Retry-After header that gives the seconds to wait.
Responses to authenticated requests also carry the RateLimit and RateLimit-Policy headers (IETF draft):
RateLimit-Policylists the policies that apply, each with its request quotaqper window ofwseconds.RateLimitreports the policy closest to rejection: the requests remaining right now (r) and the seconds until the full quota is available again (t). For example:"api-key";r=42;t=7.
Use these headers to pace your requests instead of waiting for a 429. They are advisory: they're missing when a request fails authentication or the limiter state is briefly unknown.
A 429 never makes it safe to repeat a write whose outcome you don't know. See Safe retries and conditional updates.
Updated about 2 hours ago