Dokumentation
AnleitungenErrors

Errors

Fotovid returns RFC 9457 problem details with a stable, machine-readable error code. Branch on the code, not the message.

When a request fails, Fotovid returns an RFC 9457 problem details body with the media type application/problem+json. Successful synchronous responses are plain JSON with no status field — a 2xx is success, everything else is a problem document.

Shape

{
  "type": "https://api.fotovid.co/errors/validation-error",
  "title": "Validation Error",
  "status": 400,
  "code": "VALIDATION_INVALID_ARGUMENT",
  "detail": "source_url must be a valid http(s) URL",
  "request_id": "req_01JAB...",
  "errors": [
    { "field": "source_url", "code": "VALIDATION_INVALID_ARGUMENT", "message": "must be a valid URL" }
  ]
}
FieldAlways presentMeaning
typeURI identifying the error category.
titleShort, human-readable summary. May be reworded over time.
statusHTTP status code, mirrors the response line.
codeStable UPPER_SNAKE application code. Branch on this.
detailHuman-readable, per-occurrence message (public-safe).
request_idCorrelation id — include it in support requests.
errors[]Per-field breakdown for validation failures (field, code, message).

Branch on code, never on detail, title, or status alone. One HTTP status maps to several codes — e.g. 429 can be RATE_LIMIT_EXCEEDED, RESOURCE_LIMIT_EXCEEDED, or CONCURRENT_LIMIT_EXCEEDED, and 413 can be REQUEST_BODY_TOO_LARGE or SOURCE_TOO_LARGE. detail and title are human-readable and may change.

The code contract

Error codes are additive-only: new codes are added over time, but a shipped code is never renamed or repurposed. Treat any code your client doesn't recognize as a generic failure bucketed by status — and don't crash on it.

Common codes

Client / validation

CodeStatusWhen
VALIDATION_INVALID_ARGUMENT400A parameter is invalid.
VALIDATION_MISSING_FIELD400A required field is missing.
REQUEST_BODY_INVALID_JSON400Body isn't valid JSON.
UNKNOWN_TASK_TYPE400Unrecognized type.
CONTENT_TYPE_UNSUPPORTED415Request Content-Type unsupported.
REQUEST_BODY_TOO_LARGE413The request body is too large.

Auth / permission

CodeStatusWhen
AUTH_MISSING_TOKEN401No API key supplied.
AUTH_INVALID_TOKEN401Invalid or malformed key.
AUTH_TOKEN_EXPIRED401Key expired.
PERMISSION_FORBIDDEN403Authenticated but not allowed.
INSUFFICIENT_CREDITS402Not enough credit balance to run the job.

Resources & tasks

CodeStatusWhen
TASK_NOT_FOUND404No such task.
TASK_NOT_CANCELABLE409Task already in a terminal state.
TASK_ALREADY_CANCELED409Task already canceled.
RESOURCE_NOT_FOUND404Generic resource not found.

Source media & processing

CodeStatusWhen
SOURCE_UNREACHABLE502Couldn't fetch source_url.
SOURCE_TOO_LARGE413Source media exceeds the size cap.
UNSUPPORTED_MEDIA415Source format not supported.
PROCESSING_TIMEOUT504Exceeded the synchronous time budget — retry via async.
PROCESSING_FAILED500Processing failed.
SERVICE_UNAVAILABLE503Temporarily unavailable / sync pool full. Carries a Retry-After header (seconds) — honor it before retrying, as with 429.

Rate limiting

CodeStatusWhen
RATE_LIMIT_EXCEEDED429Request-rate limit (L1).
RESOURCE_LIMIT_EXCEEDED429Generation-rate limit (L2).
CONCURRENT_LIMIT_EXCEEDED429Too many concurrent tasks (L3).

See Rate limits for the headers and how to back off.