Errors

Handle stable error codes

Every non-2xx API response uses the same envelope so callers can branch on code, log request_id, and retry safely when appropriate.

RESTBearer authJSON responses

Error envelope

Response
{
  "error": {
    "code": "validation_error",
    "message": "source_url must be an https URL",
    "request_id": "req_01HXYZ..."
  }
}

Server-side only. Keep API keys out of client bundles.

Errors

Every non-2xx response shares the same envelope.

JSON
{
  "error": {
    "code": "validation_error",
    "message": "source_url must be an https URL",
    "request_id": "req_01HXYZ..."
  }
}

Branch on error.code — it is the stable contract. Include request_id when you escalate.

Error codes

CodeStatusMeaningCaller action
unauthorized401Authorization header missing or malformed.Send `Authorization: Bearer $AIFACESWAP_API_KEY` and retry.
invalid_api_key401Bearer token does not match a live API key.Issue a new key in /dashboard/api-keys and replace the token.
validation_error400Request body or query failed schema validation.Fix the offending field per the `message`. Do not retry blindly.
source_unreachable400`source_url` or `target_url` resolved to a non-public address or failed DNS.Host the asset on a public HTTPS URL and retry.
unsupported_media_type415Content-Type is not `application/json`, or fetched media is outside the allowlist for the declared `type`.Send `Content-Type: application/json` and supply correctly typed URLs.
payload_too_large413Fetched `source_url` or `target_url` exceeds the per-type byte cap.Re-encode or shrink the asset to fit the image/GIF cap.
nsfw_content_detected422One or more inputs were flagged by the content analyser.Use different inputs. This is terminal — retrying with the same URLs will fail again.
insufficient_credits402Credit balance below the computed cost for this swap.Top up at /pricing, then retry with a fresh `Idempotency-Key`.
rate_limited429Per-minute (60 req/min) sliding-window budget exceeded.Back off until `Retry-After` seconds, or `x-ratelimit-reset` (unix epoch), elapses.
rate_limited_daily429Daily cap (10,000 req/day, UTC) exceeded.Wait until 00:00 UTC. Spread bursty workloads across the day.
rate_limited_concurrent429More than 10 in-flight `POST /swaps` for this API key.Wait for an existing swap to finalise (poll `GET /swaps/{taskId}` or use a webhook), then retry.
not_found404Task does not exist, was cleaned up, or is owned by a different key.Confirm the `taskId` and that it was created by this key. Identical envelope is returned for foreign tasks.
method_not_allowed405HTTP method not supported by this endpoint (e.g. POST to `/me`).Use the documented method.
api_temporarily_disabled503Public API feature flag is off, or required NSFW checks have not completed yet.Honour `Retry-After`; if absent, back off exponentially.
internal_error500Queue, DB, or Redis side-effect failed; credits and idempotency claim are rolled back before the response.Safe to retry. Include the `request_id` from the error envelope if you escalate.