INVALID_INPUT | 400 | active | Invalid input. The request failed validation or its body could not be parsed. details.issues lists each problem as { location, path, message }. |
UNAUTHORIZED | 401 | active | Unauthorized. No valid credential. Send Authorization: Bearer <API key or access token>. Missing, malformed, unknown, revoked and expired credentials all return this same body. |
FORBIDDEN | 403 | active | Forbidden. The credential is valid but may not do this. details.reason is one of insufficient_scope (with details.requiredScope, and details.requiredScopes when any of several scopes is accepted), api_key_limit_reached (with details.limit), scope_not_grantable, environment_not_grantable, account_conflict, upload_quota_exceeded (with details.kind count or bytes and details.limit; delete uploads to free space), webhook_limit_reached (with details.limit, webhooks per environment), project_limit_reached (with details.limit, projects per account), style_limit_reached (with details.limit, styles per account), live_key_required (billing checkouts need a live key or an access token; test keys never buy) or billing_account_flagged (a refund left the account short of credits it had already used; contact support before buying again). |
NOT_FOUND | 404 | active | Not found. No /v1 endpoint exists at this path (details echoes { method, path }), or the addressed resource does not exist for this caller. |
METHOD_NOT_ALLOWED | 405 | active | Method not allowed. The path exists but does not support this HTTP method. See the Allow header and details.allowedMethods. |
PAYLOAD_TOO_LARGE | 413 | active | Payload too large. The request body exceeds the endpoint limit. details.maxBytes gives the limit. |
UPLOAD_NOT_READY | 409 | active | Upload not ready. The upload cannot be used or completed in its current state. details.reason is object_missing (no file was uploaded to the presigned URL yet: upload it, then retry; the upload stays pending), expired (the upload expired before it was completed), failed (with details.errorCode) or deleted. details.path names the field; for a screenshot set retry it can be ["styleId"] (the set’s copy of its brand kit logo has expired). |
IDEMPOTENCY_CONFLICT | 409 | active | Idempotency conflict. This Idempotency-Key was already used by this account for a different request (another body, or a credential of the other environment). details.generationId is the generation created with it (details.screenshotSetId for POST /screenshot-sets, details.styleId for POST /styles, details.checkoutId for POST /billing/checkout, also while that checkout is still being created). Use a new key for a new request. |
GENERATION_STATE_CONFLICT | 409 | active | Generation state conflict. The generation cannot do this in its current state. details.status is its status and details.action is cancel (only a generation that has not started yet can be canceled) or delete (only a finished generation can be deleted). |
SCREENSHOT_SET_STATE_CONFLICT | 409 | active | Screenshot set state conflict. The screenshot set cannot do this in its current state. details.status is the set status and details.action is retry (no image is failed or canceled, or every one used its 5 attempts; nothing was charged), cancel (the set already finished), delete (images are still queued or running: cancel the set or wait) or archive (no image has succeeded yet). |
WEBHOOK_STATE_CONFLICT | 409 | active | Webhook state conflict. The webhook cannot do this in its current state. details.action is test (a disabled webhook receives no test event: enable it first). |
BILLING_STATE_CONFLICT | 409 | active | Billing state conflict. The plan cannot do this in its current state; nothing was charged. details.reason is subscription_exists (the account already has a plan: change it instead), checkout_pending (a plan checkout is still open: finish it, or retry later), no_subscription (the account has no plan), same_plan (already on that plan), canceling (the plan ends at the period end: uncancel it first), past_due (a payment is overdue: update the payment method in the portal) or no_customer (no payment account is linked to this account yet). |
IMAGE_TOO_LARGE | 413 | active | Image too large. An uploaded image is too large. details.reason is bytes (the file exceeds details.maxBytes, 20 MB) or pixels (more than details.maxPixels pixels, 50 megapixels, or an edge longer than details.maxEdge, 16384 pixels). |
UNSUPPORTED_FORMAT | 415 | active | Unsupported format. An uploaded file is not a PNG, JPEG or WebP image (checked from its bytes, never from its name or declared type). details.reason is unsupported_type, heic (HEIC/HEIF photos are not supported; export as PNG or JPEG), corrupt (the image could not be decoded) or type_mismatch (the uploaded file is not the contentType declared when presigning). |
NOT_A_SCREENSHOT | 422 | active | Not a screenshot. The input image does not look like an app screenshot: its size or shape is not a screen (checked when you create the generation; details.path names the input), or it carries camera capture data such as an exposure time (checked before any image is generated; the generation fails with this error.code and its credit is refunded). Upload a screenshot taken on the device. |
URL_FETCH_FAILED | 422 | active | URL fetch failed. The image URL could not be fetched. Only https:// URLs on port 443 that resolve to public addresses are fetched, with at most 3 redirects and 15 seconds in total. details.reason is blocked_destination, dns_failure, connect_failed, tls_error, timeout, too_many_redirects, insecure_redirect (a redirect to a non-https URL), http_status (with details.status) or empty_body. |
WEBHOOK_URL_REJECTED | 422 | active | Webhook URL rejected. The webhook URL is well formed but cannot be used. details.reason is blocked_destination (the host is or resolves to a private, loopback, link-local or otherwise non-public address; every DNS answer must be public) or dns_failure (the host does not resolve). The same check runs again before every delivery. |
INSUFFICIENT_CREDITS | 402 | active | Insufficient credits. The account does not have enough credits for this operation; nothing was created or charged. details.requiredCredits is the cost, details.availableCredits the current balance and details.topUpUrl where to get more credits. Test keys (ss_test_…) never need credits. |
RATE_LIMITED | 429 | active | Rate limited. Too many requests. Retry after the number of seconds in the Retry-After header (details.retryAfterSeconds). details.scope is key or user and details.policy is requests (per-minute request rate of the API key or of the whole account, with details.limit and details.windowSeconds; see the RateLimit headers) daily_generations (the account reached its generations for this UTC day, details.limit), webhook_tests (test events of one webhook per hour, details.limit) or billing_checkouts (checkouts created by the account in the last hour, details.limit). Without details.scope, too many failed authentication attempts came from this IP. |
CONCURRENCY_LIMITED | 429 | active | Concurrency limited. Too many generations of this account are in progress. Retry after the number of seconds in the Retry-After header (details.retryAfterSeconds); details.limit is the number allowed at once (details.scope user, details.policy concurrent_generations). |
INTERNAL_ERROR | 500 | active | Internal error. An unexpected error occurred. Quote the requestId when contacting support. |
GENERATION_FAILED | 502 | active | Generation failed. Appears as the error.code of a failed generation (never as an HTTP status): the image could not be generated. Its credit was refunded; create a new generation to try again. |
SERVICE_UNAVAILABLE | 503 | active | Service unavailable. A dependency is unavailable (on /v1/health, details contains the health report), or uploads are busy (Retry-After): retry after that many seconds. |
BILLING_UNAVAILABLE | 503 | active | Billing unavailable. Credits cannot be bought right now; nothing was charged. details.reason is disabled (web payments are switched off), not_configured (payments are not set up on this server), provider_error (the payment provider did not answer; retry later, with the same Idempotency-Key if you sent one) or webhook_not_configured (payment notifications are not accepted yet). |
GENERATION_TIMEOUT | 504 | active | Generation timeout. Appears as the error.code of a failed generation (never as an HTTP status): generating the image took too long. Its credit was refunded; create a new generation to try again. |