Errors and rate limits
Diagnose failed requests and retry safely using structured error responses.
Errors use RFC 9457 Problem Details with Content-Type: application/problem+json. Inspect code, status, retryable, and the server-generated requestId.
Some 503 responses during deployment draining use application/json, as declared in the endpoint reference. Check the content type before parsing an error, and use Retry-After when supplied.
{
"type": "urn:neatlogs:problem:validation-error",
"title": "Bad Request",
"status": 400,
"detail": "The public API request is invalid.",
"instance": "/api/v1/public/project",
"code": "VALIDATION_ERROR",
"requestId": "req_0123456789abcdef0123456789abcdef",
"retryable": false,
"errors": [
{
"code": "invalid_type",
"message": "Invalid value type.",
"path": "x-project-id"
}
]
}Validation errors are optional. The response also includes X-Request-Id; preserve that ID when contacting support. Success responses include the same server-owned requestId field.
| HTTP status | Common code | What to do |
|---|---|---|
400 | VALIDATION_ERROR, MALFORMED_JSON, PUBLIC_API_INVALID_CURSOR | Fix the request; restart an expired cursor chain. |
401 | UNAUTHORIZED | Check the credential and host, then sign in again or rotate the token. |
403 | FORBIDDEN | Check the required scope, current role, project binding, and entitlement. |
404 | NOT_FOUND | Check the selected context and resource ID. Resources can be hidden by authorization, and an operation may be unavailable. |
409 | CONFLICT or an idempotency code | Read current state or follow the idempotency recovery rules. |
413, 415 | PAYLOAD_TOO_LARGE, UNSUPPORTED_MEDIA_TYPE | Reduce the payload or use the declared content type. |
429 | RATE_LIMITED | Respect Retry-After and reduce request concurrency. |
500 | INTERNAL_ERROR or a response-contract failure | Retain the request ID; resolve unknown write outcomes before retrying. |
503 | SERVICE_UNAVAILABLE or another availability code | Retry only when the problem is retryable, with bounded backoff. |
Endpoint pages list their declared response statuses; the downloadable OpenAPI file contains the complete error schemas.
GUEST_REVIEW_COMPLETION_RETRY_REQUIRED is a 503 after the guest review response has been committed, while completion processing remains pending. Keep the same guest token, item, answers, and idempotency key when retrying. Do not create a second review or assume that the response was rolled back. Use bounded retries and retain the request ID if completion continues to fail.
Rate-limit headers
Limits apply across credentials, actors, projects, organizations, and operation classes. Rotating tokens or switching projects does not guarantee more capacity. Read the actual headers on the response instead of assuming a fixed global quota.
Service-account administration mutations and service-account token minting, rotation and revocation use the shared security-lifecycle class. Its default token bucket holds 10 requests per applicable bucket and replenishes at 10 requests per hour. When an empty bucket is otherwise idle, one request slot replenishes in about six minutes; there is no fixed hourly reset boundary. Credential, actor, organization and other applicable buckets are checked together. Different endpoints, service accounts or tokens can therefore consume the same capacity; changing IDs does not provide a new independent quota.
Plan setup, rotation and cleanup together, leaving capacity for revocation. On 429, honor the returned Retry-After before retrying rather than assuming a six-minute delay is always sufficient. The response headers describe the actual limiting bucket and take precedence over these defaults.
| Header | Meaning |
|---|---|
RateLimit-Limit | Capacity of the limiting request bucket |
RateLimit-Remaining | Remaining capacity in that bucket |
RateLimit-Reset | Unix timestamp in seconds when the limiting bucket fully replenishes |
Retry-After | Minimum delay before retrying a throttled or retryable request |
X-NeatLogs-RateLimit-Policy | Applied policy identifier |
Use bounded exponential backoff with jitter after the indicated delay. Retry a write with the exact original idempotency key and request; sending a new key after an unknown outcome can duplicate work.
