Browse Docs
On This Page

Errors

Network reference: For the full cross-tool error code reference, see tools.fast/api/docs/errors.

Error envelope

All API errors return a JSON object with at least two fields:

{
  "error": "machine.readable_code",
  "detail": "Human-readable explanation."
}

Some errors include additional context fields. URL fetch errors include an isRetryable boolean indicating whether the request can be retried (e.g. transient network failures vs permanent validation errors).

400 Bad Request

Invalid request payload, parameters, or content type.

Invalid content type
{
  "error": "request.invalid_content_type",
  "detail": "multipart/form-data or application/json required."
}
Empty file
{
  "error": "request.empty_file",
  "detail": "Uploaded file is empty."
}
No files provided
{
  "error": "request.no_files",
  "detail": "Exactly one file must be provided."
}
Invalid extension
{
  "error": "request.invalid_extension",
  "detail": "File extension '.mp3' is not accepted by this compressor."
}

URL fetch errors (400)

Returned when URL-based input (inputUrl) fails validation or the remote server returns an error.

Invalid URL
{
  "error": "url_fetch.invalid_url",
  "detail": "inputUrl is required in JSON body.",
  "isRetryable": false
}
Invalid scheme
{
  "error": "url_fetch.invalid_scheme",
  "detail": "Only HTTPS URLs are allowed.",
  "isRetryable": false
}
Private IP blocked
{
  "error": "url_fetch.private_ip",
  "detail": "URL resolved to blocked IP address (private/reserved).",
  "isRetryable": false
}
Mutually exclusive
{
  "error": "url_fetch.mutually_exclusive",
  "detail": "Cannot provide both a file upload and inputUrl. Use one or the other.",
  "isRetryable": false
}
Output URL reserved
{
  "error": "url_fetch.output_url_reserved",
  "detail": "outputUrl is reserved for future use and not yet supported.",
  "isRetryable": false
}
Remote server error
{
  "error": "url_fetch.http_error",
  "detail": "Remote server returned 503 Service Unavailable.",
  "isRetryable": true
}

401 Unauthorized

The API key is missing, invalid, or not allowed from the caller's IP.

{
  "error": "api_key.invalid_or_ip_not_allowed",
  "detail": "X-Fast-Api-Key was provided but is invalid for this request (or IP not allowlisted)."
}

This error intentionally does not distinguish between an invalid key and an IP not in the allowlist.

402 Payment Required

The caller's account does not have enough credits.

{
  "error": "entitlements.insufficient_credits",
  "detail": "Insufficient credits. Required: 5, Available: 2"
}

403 Forbidden

The resource exists but the caller does not own it, or the action is not allowed for the caller's account.

Job forbidden
{
  "error": "jobs.forbidden",
  "detail": "You do not have access to this job."
}
URL input not allowed for guests
{
  "error": "url_fetch.guest_not_allowed",
  "detail": "URL-based input is not available for guest users. Please sign in.",
  "isRetryable": false
}

404 Not Found

The requested job does not exist.

{
  "error": "jobs.not_found",
  "detail": null
}

409 Conflict

The request conflicts with the current state of the resource.

Job not ready
{
  "error": "jobs.not_ready",
  "detail": "Job is still processing or waiting to start."
}
Not cancellable
{
  "error": "jobs.not_cancellable",
  "detail": "Cannot cancel completed, failed, or canceled jobs."
}
Not deletable
{
  "error": "jobs.not_deletable",
  "detail": "Cannot delete a job that is still queued or running. Cancel it first."
}

410 Gone

The job completed but its output artifacts have expired and been cleaned up. Output artifacts are retained for 1 hour after job completion, then automatically deleted. To clean up immediately after downloading, call DELETE /compress/job/{id}.

{
  "error": "jobs.expired",
  "detail": "Job artifacts were deleted on 2025-01-15 12:00:00Z after the retention period expired."
}

413 Payload Too Large

The uploaded file exceeds the per-compressor or global size limit.

{
  "error": "request.file_too_large",
  "detail": "File exceeds the maximum allowed size.",
  "megabytes": 50
}

429 Too Many Requests

The caller has been throttled. Check the Retry-After header.

Rate limited
{
  "error": "rate_limited",
  "detail": "Too many requests. Retry after 12 seconds."
}
Queue limit exceeded
{
  "error": "queue.limit_exceeded",
  "detail": "Too many queued jobs. Wait for existing jobs to complete."
}
URL fetch rate limited
{
  "error": "url_fetch.rate_limited",
  "detail": "Too many concurrent URL fetches. Please wait and retry.",
  "isRetryable": true
}

Headers on 429 responses:

HeaderDescription
Retry-AfterSeconds until you can retry

Best practice: implement exponential backoff in your client, or honour the Retry-After value directly.

5xx Server Error

Server-side errors are rare but possible. Retry with exponential backoff (1s, 2s, 4s, 8s, max 30s). If errors persist, contact support@tools.fast.

Error codes reference

CodeStatusDescription
request.invalid_content_type400Must use multipart/form-data or application/json
request.no_files400No file attached
request.empty_file400Uploaded file has zero bytes
request.invalid_extension400File extension not accepted by compressor
request.multiple_files400Only one file per request
request.file_too_large413File exceeds size limit
api_key.invalid_or_ip_not_allowed401Bad API key or IP not in allowlist
entitlements.insufficient_credits402Not enough credits
jobs.forbidden403Job owned by another user
jobs.not_found404Job ID does not exist
jobs.not_ready409Download requested before job finishes
jobs.not_cancellable409Job already completed/failed
jobs.not_deletable409Cannot delete queued/running jobs — cancel first
jobs.expired410Output artifacts cleaned up
rate_limited429IP rate limit exceeded
queue.limit_exceeded429Too many queued jobs
compress.invalid_webhook400Webhook URL or secret failed validation
compress.unsupported_format400File format not recognized by the universal compressor
compress.{format}.validation.unsupported_format400File format not accepted by the format-specific compressor
estimate.unsupported_format400No compressor found for the requested format
schema.unsupported_format400No compressor found for the requested format
url_fetch.invalid_url400URL is missing, empty, or malformed
url_fetch.invalid_scheme400Only HTTPS allowed
url_fetch.private_ip400URL resolved to private/reserved IP (SSRF blocked)
url_fetch.dns_failure400DNS resolution failed for the URL host
url_fetch.timeout400Remote server did not respond in time
url_fetch.too_large400Remote file exceeds size limit
url_fetch.invalid_content400Remote server returned an empty response
url_fetch.http_error400Remote server returned an error status
url_fetch.redirect_loop400Redirect chain exceeded maximum hops
url_fetch.redirect_denied400Redirect target resolved to private/reserved IP
url_fetch.domain_circuit_open400Domain temporarily blocked due to repeated failures
url_fetch.url_expired400Presigned URL has expired (S3, GCS, Azure SAS)
url_fetch.no_filename400Could not determine filename from URL or response headers
url_fetch.mutually_exclusive400Cannot provide both file upload and inputUrl
url_fetch.output_url_reserved400outputUrl is not yet supported
url_fetch.guest_not_allowed403URL input requires a signed-in account
url_fetch.rate_limited429Too many concurrent URL fetches
compare.not_ready409Job not yet succeeded for comparison
compare.expired410Output artifacts cleaned up
compare.timeout504Preview generation timed out
server.internal_error500Unexpected server error — retry with exponential backoff
Copied.