{"openapi":"3.1.0","info":{"title":"cheapaiapi","description":"Image, text, and video generation API for production workloads. CheapAIAPI implements the fields and behaviors documented here; it is not a drop-in implementation of every parameter offered by official model APIs. Use this documentation and the generated OpenAPI schema as the compatibility contract.\n\n**Compare current prices.** CheapAIAPI is a prepaid, usage-based API with no monthly or annual subscription. The public catalog contains real starting prices for new customers in [Markdown](https://cheapaiapi.org/pricing.md) and [JSON](https://cheapaiapi.org/pricing.json). See dated, like-for-like comparisons at [cheapaiapi.org/models](https://cheapaiapi.org/models/).\n\n**Get access or a volume discount.** API keys are issued after account approval. Customers with existing production volume may qualify for lower account-specific rates. Use [cheapaiapi.org/contact](https://cheapaiapi.org/contact) to send the exact model, current monthly usage, and average and peak RPS.\n\n**Authenticate.** Click **Authorize** and paste your `sk_cheap_...` key. The docs will attach it as `Authorization: Bearer <key>` for Try it out requests.\n\n**Recommended production flow.**\n1. Call `GET /v1/models` to see your enabled SKUs and prices.\n2. Submit `POST /v1/images/generations?async=true` with `webhook_url`.\n3. Store the returned `id`.\n4. Handle the signed webhook as the primary image completion path; recover with `GET /v1/jobs/{id}` if no callback arrives.\n\n**Video generation.** When video is enabled for your account, submit `POST /v1/videos`, poll `GET /v1/videos/{id}`, and stream the completed MP4 through the authenticated `GET /v1/videos/{id}/content` endpoint. Completed videos are available from `GET /v1/videos/{id}/content` for 23 hours after completion. Download and store each video yourself within that window; it cannot be retrieved afterwards. Use `GET /v1/models` as the source of truth for available video SKUs and prices. `image_url` is the first frame, `last_frame_image_url` is the last frame, and `reference_image_urls` are style/identity images not frames. Standard `seedance-2.0` supports text-to-video plus `image_url`, `last_frame_image_url`, `reference_image_urls`, and `seed`. Standard `seedance-2.5` accepts the same media fields. Defaults are five seconds, 720p, 16:9, audio on. Callers may set `duration` (4-15 for seedance-2.0, 4-30 for seedance-2.5), `resolution`, `aspect_ratio`, and `generate_audio`; price equals the account's per-output-second rate for the selected model and resolution multiplied by duration. `GET /v1/models` returns the current resolution rate card. `4k` output is H.265/HEVC, which some browsers cannot play inline.\n\n**Text completions.** Call `POST /v1/chat/completions` with required `messages`; `model`, `stream`, and `conversation_id` are optional. The endpoint schema is authoritative: text, the `image_url` request shape, function tools, a non-stream JSON completion envelope, and OpenAI-compatible SSE streaming form the integration core. Additional compatibility fields such as `response_format`, `reasoning_effort`, and sampling controls are best-effort passthrough and are not guaranteed across every model. Unrecognized top-level fields are ignored; `user`, `metadata`, `safety_identifier`, `prompt_cache_key`, and `store` are accepted but never forwarded to the model. For accounts with token-priced text enabled, default prices per 1M input/output tokens are `gemini-3.5-flash` ($1.05/$6.30), `gemini-3.1-flash-lite` ($0.175/$1.05), `gemini-3.1-pro` ($1.40/$8.40), `gemini-3.7-flash` ($0.525/$2.625). The authenticated `GET /v1/models` response is authoritative for the caller's enabled SKUs and prices; accounts not yet cut over retain the pricing unit returned there. Only enabled account SKUs appear in `GET /v1/models`. The response is either one JSON completion or an SSE sequence ending in `[DONE]`.\n\n**Stateless Responses API.** `POST /v1/responses` accepts the OpenAI Responses request shape for the same text SKUs at the same token prices: string or message `input`, function tools, `text.format` JSON schema, and named SSE events with `stream: true`. Send the full conversation every time; `previous_response_id` and `store: true` are not supported. Each `id` is `resp_<job id>`; recover it with `GET /v1/responses/{id}` or `GET /v1/jobs/{job id}`. Quickstarts for curl, the `openai` SDKs, and the Vercel AI SDK: [https://cheapaiapi.org/docs/index.md](https://cheapaiapi.org/docs/index.md).\n\n**Long text and files.** The API does not promise one shared context window, file-count limit, or attachment-size limit across all text models. The OpenAI-compatible `image_url` content part accepts a public URL or base64 `data:` URL. Context and media support depend on the selected model.\n\n**Integration rules for coding agents.** `queued` and `running` are pending states, not failures. Result data is available only after `status` is `done`. Use a stable `Idempotency-Key` per client-side job and reuse the same key when retrying after a timeout. Do not send concurrent duplicate create requests for the same client-side job.\n\n\n## Webhook integration\n\nEvery image account can use webhooks. Pass `webhook_url` in the normal\nasynchronous generation request to receive an HTTPS `POST` when the Job reaches\n`done` or `failed`. `custom_data` is an optional JSON object of at most 4096\nserialized bytes; it is stored and echoed unchanged in create, polling, and\ncallback responses, and can also be used without a webhook. Do not put secrets\nin `custom_data`. Chat Completions and video do not accept `webhook_url`.\n\nThe full guide is at https://cheapaiapi.org/docs/webhooks.md.\n\n```json\n{\n  \"model\": \"nano-banana-pro-2k\",\n  \"prompt\": \"Place the product on a clean studio background.\",\n  \"response_format\": \"url\",\n  \"webhook_url\": \"https://api.example.com/webhooks/cheapaiapi\",\n  \"custom_data\": {\"customer_request_id\": \"customer-job-123\"}\n}\n```\n\nSubmit this body to `POST /v1/images/generations?async=true`, store the returned\nJob `id`, and keep `GET /v1/jobs/{id}` as the recovery path. Webhook URLs must be\npublicly reachable HTTPS endpoints. Callback Jobs require\n`response_format: \"url\"` so callback bodies contain durable result URLs rather\nthan large inline image bytes.\n\n### Callback body\n\nThe callback is the frozen terminal projection of the public Job response, with\nan additional stable `event_id`. A successful callback looks like this:\n\n```json\n{\n  \"event_id\": \"0bd05147-b6a0-45fa-b176-9cfe008bb350\",\n  \"id\": \"3e7487ca-a942-4ef0-bc47-4cb8171a2ca8\",\n  \"status\": \"done\",\n  \"model\": \"nano-banana-pro-2k\",\n  \"created_at\": \"2026-07-14T12:20:00+00:00\",\n  \"finished_at\": \"2026-07-14T12:20:14+00:00\",\n  \"custom_data\": {\"customer_request_id\": \"customer-job-123\"},\n  \"data\": [{\"url\": \"https://cheapaiapi.org/v1/jobs/3e7487ca-a942-4ef0-bc47-4cb8171a2ca8/results/0?sig=...\"}],\n  \"error\": null\n}\n```\n\nFor a failed Job, `status` is `failed`, `data` is empty, and `error` contains\nthe same sanitized public error shape returned by polling. The submitted\n`webhook_url` and prompt are not echoed.\n\n### Signing secret and verification\n\nRead `webhook_secret` from `GET /v1/balance` and store it on your backend.\nThe first `GET /v1/balance` or `webhook_url` create creates the secret if the\naccount has none. Do not put it in browser or mobile code.\n\nEvery callback has one signing header:\n\n```text\nX-CheapAIAPI-Signature: t=<unix_timestamp>,v1=<hex_hmac_sha256>\n```\n\nThe signed bytes are `<unix_timestamp>.<exact raw request body>`. Read the raw\nbody before JSON parsing, reject timestamps more than five minutes from your\nclock, and compare digests in constant time.\n\n```python\nimport hashlib\nimport hmac\nimport json\nimport time\n\nfrom fastapi import FastAPI, HTTPException, Request, Response\n\napp = FastAPI()\nWEBHOOK_SECRET = \"<from GET /v1/balance webhook_secret>\"\n\n\ndef verify_signature(header: str, raw_body: bytes) -> bool:\n    try:\n        parts = dict(part.split(\"=\", 1) for part in header.split(\",\"))\n        timestamp = int(parts[\"t\"])\n        supplied = parts[\"v1\"]\n    except (KeyError, TypeError, ValueError):\n        return False\n    if abs(int(time.time()) - timestamp) > 300:\n        return False\n    signed = f\"{timestamp}.\".encode() + raw_body\n    expected = hmac.new(\n        WEBHOOK_SECRET.encode(), signed, hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, supplied)\n\n\n@app.post(\"/webhooks/cheapaiapi\")\nasync def receive_webhook(request: Request) -> Response:\n    raw_body = await request.body()\n    signature = request.headers.get(\"X-CheapAIAPI-Signature\", \"\")\n    if not verify_signature(signature, raw_body):\n        raise HTTPException(status_code=400, detail=\"invalid signature\")\n    event = json.loads(raw_body)\n    # Insert event[\"event_id\"] into an inbox table with a UNIQUE constraint,\n    # and apply your business effect in the same database transaction.\n    return Response(status_code=204)\n```\n\nReturn any `2xx` quickly to acknowledge delivery. Transient delivery failures\nare retried automatically, so the same signed `event_id` may arrive more than\nonce. Deduplicate by `event_id`; on a duplicate, skip the business effect and\nreturn `2xx`. If no callback arrives, recover with `GET /v1/jobs/{id}`.\n\nUse webhooks as the primary completion signal for production image volume and\npolling only as a recovery path. For workloads above 1,000 generation Jobs per day\nthis is especially important: it removes polling traffic and polling-interval\ndelay; it does not reduce generation time. The full guide is\nhttps://cheapaiapi.org/docs/webhooks.md.\n\n\n**Image inputs.** `image` accepts public `https://` URLs or `data:image/<mime>;base64,...` URIs. Empty `image` means text-to-image.\n\n**Responses.** Every generation response includes a job `id`, even if the request later finishes asynchronously. Result URLs are served from cheapaiapi result endpoints. Generation and job responses may include `usage.cost_usd` and `usage.balance_remaining_usd`; these are customer-facing amounts only. `balance_remaining_usd` is the available balance at response time, so parallel requests can make responses arrive out of balance order.\n\n**Errors.** Customer-facing errors use a small stable taxonomy: `RateLimited`, `UpstreamDown`, `NoFunds`, `InvalidPrompt`, `Unauthorized`.","version":"0.1.0.2"},"servers":[{"url":"https://cheapaiapi.org","description":"Production"}],"paths":{"/v1/balance":{"get":{"tags":["Account"],"summary":"Get account balance","description":"Return the authenticated account's available USD balance and the image webhook HMAC secret. Pass `webhook_url` on `POST /v1/images/generations?async=true`. Store `webhook_secret` on your backend to verify `X-CheapAIAPI-Signature`.","operationId":"get_balance_v1_balance_get","responses":{"200":{"description":"Available account balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/usage":{"get":{"tags":["Account"],"summary":"Get usage","description":"Return aggregate job counts and spend for the authenticated account.","operationId":"get_usage_v1_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO-8601 lower bound (inclusive). Defaults to 30 days ago.","title":"From"},"description":"ISO-8601 lower bound (inclusive). Defaults to 30 days ago."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO-8601 upper bound (exclusive). Defaults to now.","title":"To"},"description":"ISO-8601 upper bound (exclusive). Defaults to now."}],"responses":{"200":{"description":"Usage totals for the selected time range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"400":{"description":"Invalid usage time range.","content":{"application/json":{"example":{"error":{"message":"`from` must be earlier than `to`.","type":"invalid_request_error","param":"from","code":"invalid_range"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/jobs":{"get":{"tags":["Jobs"],"summary":"List jobs","description":"Return the authenticated Customer Account's Jobs newest first across all of its API keys. Pages use an opaque cursor and contain durable request metadata plus Customer Ledger charges only. Prompts, input/output media, result URLs, provider attempts, provider identities, internal costs, and raw diagnostic payloads are never included. Job and billing metadata is retained independently from the shorter media-retention policy.","operationId":"list_jobs_v1_jobs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Account-wide customer-safe Job history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerJobHistoryResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"400":{"description":"The pagination cursor is invalid."}}}},"/v1/transactions":{"get":{"tags":["Account"],"summary":"List transactions","description":"Return balance-changing Customer Ledger events newest first across the authenticated Customer Account. The signed amount is positive for credits and negative for usage debits. Zero-value internal audit events and private operator notes are not exposed. Pages use an opaque cursor.","operationId":"list_transactions_v1_transactions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Account-wide Customer Ledger transaction history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerTransactionHistoryResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"400":{"description":"The pagination cursor is invalid."}}}},"/v1/jobs/{job_id}":{"get":{"tags":["Jobs"],"summary":"Get job","description":"Return the customer-safe state for one image, video, or chat job. For a chat completion, strip the `chatcmpl-` prefix from the completion `id` and poll this path until `status` is `done` or `failed`. `queued` and `running` are pending states. Image results are in `data` only when `status` is `done`. A completed chat job includes the persisted public completion in `response`. When the create request included `webhook_url`, the same terminal state is also sent as a signed callback. Prefer that callback; this GET is the recovery path.","operationId":"get_job_v1_jobs__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Public job state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobLookupResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No job exists for the supplied id.","content":{"application/json":{"example":{"error":{"message":"No job with that id.","type":"invalid_request_error","code":"job_not_found"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/models":{"get":{"tags":["Models"],"summary":"List enabled models","description":"Return model SKUs enabled for the account, including mutually exclusive per-call, per-output-second video, or input/output token pricing in USD.","operationId":"list_models_v1_models_get","responses":{"200":{"description":"Models enabled for the authenticated Customer Account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelListResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}}}}},"422":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/chat/completions":{"post":{"tags":["Chat"],"summary":"Create chat completion","description":"Create an OpenAI-compatible text completion. The guaranteed integration contract covers required messages, optional model and stream, text and the image_url request shape, one completion, function tools, a non-stream JSON completion envelope, and OpenAI-compatible SSE streaming. A standard assistant function tool_calls message followed by role=tool is accepted unchanged. Only function-type tools are accepted; tool_choice supports auto, required, none, or a named function. image_url accepts a public HTTPS URL or base64 data URI; HTTPS images are downloaded by us and sent to the model as bytes, never as your URL. Content parts may be text, image_url, or input_audio. Additional documented compatibility fields such as response_format, reasoning_effort, and sampling are best-effort passthrough; behavior can vary by model. Unrecognized top-level fields are ignored. user, metadata, safety_identifier, prompt_cache_key, store, and participant names are accepted but never forwarded to the model. webhook_url and custom_data are not accepted for Chat Completions. n may be omitted or set to integer 1; multiplying fields are unsupported; use only one of max_tokens and max_completion_tokens, up to 65,536. Context and media support depend on the selected model. Successful responses always include terminal prompt, completion, and total token counts used for customer billing.","operationId":"create_chat_completion_v1_chat_completions_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}}},"responses":{"200":{"description":"With stream=false, returns one OpenAI-compatible JSON completion. With stream=true, returns text/event-stream; its final JSON event contains usage and is followed by data: [DONE].","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}},"text/event-stream":{"schema":{"type":"string"},"example":"data: {\"id\":\"chatcmpl-018f5f1c-7b19-7e4a-a5c1-0d44fe93aa10\",\"object\":\"chat.completion.chunk\",\"model\":\"gemini-3.5-flash\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"Hello!\"},\"finish_reason\":\"stop\"}]}\n\ndata: {\"id\":\"chatcmpl-018f5f1c-7b19-7e4a-a5c1-0d44fe93aa10\",\"object\":\"chat.completion.chunk\",\"model\":\"gemini-3.5-flash\",\"choices\":[],\"usage\":{\"prompt_tokens\":12,\"completion_tokens\":8,\"total_tokens\":20}}\n\ndata: [DONE]\n\n"}},"headers":{"X-Chat-Completion-Id":{"description":"Recoverable chatcmpl-<Job UUID> for SSE responses.","schema":{"type":"string"}},"X-Conversation-Id":{"description":"Conversation identifier when one is returned.","schema":{"type":"string"}}}},"408":{"description":"The non-stream delivery deadline elapsed while the Job continued in the background. Strip the `chatcmpl-` prefix from `X-Chat-Completion-Id` and poll `GET /v1/jobs/{uuid}`.","headers":{"X-Chat-Completion-Id":{"description":"Exact recoverable chatcmpl-<Job UUID> identifier.","schema":{"type":"string"}},"X-Should-Retry":{"description":"Always false; recover the existing Job instead of replaying POST.","schema":{"type":"string","enum":["false"]}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/responses":{"post":{"tags":["Responses"],"summary":"Create a response","description":"Create a stateless text response in the OpenAI Responses format, as one JSON object or typed SSE events. Send the full conversation each request in `input`: a string, messages, function calls and their outputs, or `item_reference` items naming output items of your earlier responses. `previous_response_id`, `conversation`, and `store: true` are rejected. `id` is `resp_<job id>`; recover via `GET /v1/responses/{id}` or `GET /v1/jobs/{job id}`.\n\nSupported: `function` tools, `tool_choice`, `parallel_tool_calls`, `instructions`, `text.format` (`text`, `json_object`, `json_schema`), `temperature`, `top_p`, `max_output_tokens` (default and maximum 65,536), and `metadata` (echoed). Accepted as no-ops: `user`, `safety_identifier`, `prompt_cache_key`, `service_tier`, `stream_options`, `include`, `reasoning`, `truncation`, replayed `reasoning` input items, and `output_text` annotations. Other unknown top-level fields are ignored.\n\nNot supported (HTTP 400): hosted, `custom`, and grammar tools; image, file, and audio input parts; `background`; `prompt` templates; `top_logprobs`; `max_tool_calls`.","operationId":"create_response_v1_responses_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesRequest"}}}},"responses":{"200":{"description":"With stream=false, returns one terminal Response object. With stream=true, returns named text/event-stream events ending in response.completed, response.incomplete, or response.failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesTerminalResponse"}},"text/event-stream":{"schema":{"type":"string"},"example":"event: response.output_text.delta\ndata: {\"type\":\"response.output_text.delta\",\"sequence_number\":3,\"output_index\":0,\"content_index\":0,\"item_id\":\"ri_0_0\",\"delta\":\"Hello\",\"logprobs\":[]}\n\n"}},"headers":{"X-Response-Id":{"description":"Recoverable resp_<Job UUID> identifier.","schema":{"type":"string"}}}},"400":{"description":"Invalid or unsupported request: `unknown_parameter`, `invalid_value`, `model_not_found` (unknown or unpriced model), or `input_too_large` (the serialized request exceeds the maximum prompt size).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Insufficient account balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"408":{"description":"The non-stream delivery deadline elapsed while the response continued. Retrieve it with GET /v1/responses/{id} using X-Response-Id.","headers":{"X-Response-Id":{"description":"Exact recoverable resp_<Job UUID> identifier.","schema":{"type":"string"}},"X-Should-Retry":{"description":"Always false; retrieve the existing response.","schema":{"type":"string","enum":["false"]}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Idempotency conflict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"502":{"description":"The response failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"No compatible Responses route.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/responses/{response_id}":{"get":{"tags":["Responses"],"summary":"Retrieve a response","description":"Return the Response object for a `resp_<uuid>` id from your account: the final response once it is completed, or its in-progress or failed state. The same Job is also visible at GET /v1/jobs/{uuid}.","operationId":"retrieve_response_v1_responses__response_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_id","in":"path","required":true,"schema":{"type":"string","title":"Response Id"}}],"responses":{"200":{"description":"The Response object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesTerminalResponse"}}}},"404":{"description":"No response with that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/images/generations":{"post":{"tags":["Images"],"summary":"Create image generation","description":"Create an image generation job. Use `?async=true` for production workloads, pass `webhook_url`, and store the returned `id`. Read `webhook_secret` from `GET /v1/balance`. Recover with `GET /v1/jobs/{id}` if no callback arrives. Treat `queued` and `running` as pending states, not errors; `data` is empty until `done`. Use a stable `Idempotency-Key` when retrying after a timeout. Do not send concurrent duplicate create requests for the same client-side job. Image output is URL-only: omit `response_format` or set it to `url`, then download the image from `data[].url`.","operationId":"generate_v1_images_generations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"async","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Async"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationRequest"}}}},"responses":{"200":{"description":"Image generation job state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"authentication_error","code":"invalid_api_key"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Invalid request body or unsupported image output format. Use `response_format=url` or omit the field.","content":{"application/json":{"examples":{"invalid_parameter":{"value":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}}},"unsupported_response_format":{"value":{"error":{"message":"`b64_json` output is not supported. Use `response_format=\"url\"` (or omit `response_format`) and download the generated image from `data[].url`. Integration docs: https://cheapaiapi.org/docs","type":"invalid_request_error","param":"response_format","code":"unsupported_response_format"}}}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"example":{"error":{"message":"Too many requests. Please retry later.","type":"rate_limit_exceeded","code":"rate_limit_exceeded"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"Temporary service error.","content":{"application/json":{"example":{"error":{"message":"An internal server error occurred. Please retry; if the issue persists, contact support.","type":"server_error","code":"server_error"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"400":{"description":"Invalid image generation request.","content":{"application/json":{"example":{"error":{"message":"Request validation failed.","type":"invalid_request_error","param":"prompt","code":"invalid_parameter"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"402":{"description":"Account balance is too low for this request.","content":{"application/json":{"example":{"error":{"message":"Insufficient balance for this request.","type":"insufficient_quota","code":"insufficient_balance"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"Webhook intake is temporarily unavailable.","content":{"application/json":{"example":{"error":{"message":"Webhook callbacks and custom correlation data are temporarily unavailable. Try again later.","type":"server_error","param":"webhook_url","code":"webhook_temporarily_unavailable"}},"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"202":{"description":"The job was queued for asynchronous processing. Handle the signed webhook, or recover with `GET /v1/jobs/{id}`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationResponse"}}}}}}},"/v1/videos":{"post":{"tags":["Videos"],"summary":"Create video","description":"Create one asynchronous video using the supported official Seedance generation fields: content, duration, resolution, ratio, and generate_audio. Standard models accept inline image, reference-video, and reference-audio base64 data URIs as well as HTTPS. Seedance 2.0 accepts 4-15 seconds (default 5); Seedance 2.5 requires an explicit duration of 4-30 seconds, or -1 for a video edit of a reference video (output keeps the edited clip's 4-30 second length, ratio=adaptive, priced as the total reference-video seconds rounded up). Defaults are 720p, ratio=adaptive, and audio on. Price is the account's USD-per-second rate for the requested model and resolution, multiplied by duration. With reference videos the with-video rate applies to billed seconds: total reference-video seconds rounded up plus output seconds, at least 5/3 of the output seconds rounded up. nsfw_check: When true, prompts and images get an extra content-moderation pass before generation and flagged requests fail with a content-policy error at no charge. The model's built-in safety system always applies. Default false. Poll `GET /v1/videos/{id}` until the status is `completed` or `failed`, then download completed output. Completed videos are available from `GET /v1/videos/{id}/content` for 23 hours after completion. Download and store each video yourself within that window; it cannot be retrieved afterwards.","operationId":"create_video_v1_videos_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoCreateRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoResource"}}}},"400":{"description":"Unknown, unavailable, or unpriced video model."},"401":{"description":"Missing or invalid API key."},"402":{"description":"Insufficient balance."},"404":{"description":"Video resource not found."},"409":{"description":"Idempotency key reused with a different request body."},"422":{"description":"Request validation failed."},"429":{"description":"Too many active jobs."},"500":{"description":"Unexpected server error."},"503":{"description":"Video generation is temporarily unavailable."}}}},"/v1/videos/{video_id}":{"get":{"tags":["Videos"],"summary":"Get video","description":"Return the customer-safe state of one video. Completed videos are available from `GET /v1/videos/{id}/content` for 23 hours after completion. Download and store each video yourself within that window; it cannot be retrieved afterwards.","operationId":"get_video_v1_videos__video_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"video_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Video Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoResource"}}}},"400":{"description":"Unknown, unavailable, or unpriced video model."},"401":{"description":"Missing or invalid API key."},"402":{"description":"Insufficient balance."},"404":{"description":"Video resource not found."},"409":{"description":"Idempotency key reused with a different request body."},"422":{"description":"Request validation failed."},"429":{"description":"Too many active jobs."},"500":{"description":"Unexpected server error."},"503":{"description":"Video generation is temporarily unavailable."}}}},"/v1/videos/{video_id}/content":{"get":{"tags":["Videos"],"summary":"Download video content","description":"Stream completed video content (MP4, or MOV when requested with output_format=mov) through the API domain. `variant=last_frame` streams the clip's last frame image (JPEG, PNG, or WebP) when the video was created with return_last_frame=true. A single HTTP byte Range is supported. Completed videos are available from `GET /v1/videos/{id}/content` for 23 hours after completion. Download and store each video yourself within that window; it cannot be retrieved afterwards.","operationId":"get_video_content_v1_videos__video_id__content_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"video_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Video Id"}},{"name":"variant","in":"query","required":false,"schema":{"enum":["video","last_frame"],"type":"string","description":"video (default) or last_frame.","default":"video","title":"Variant"},"description":"video (default) or last_frame."},{"name":"Range","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range"}}],"responses":{"200":{"description":"Successful Response"},"401":{"description":"Missing or invalid API key."},"404":{"description":"Video resource not found."},"409":{"description":"Video generation has not completed."},"410":{"description":"Generated video content has expired."},"416":{"description":"Invalid or unsatisfiable byte range."},"502":{"description":"Video content could not be fetched safely."},"503":{"description":"Video streaming capacity is temporarily exhausted."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ApiErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ErrorEnvelope","description":"Stable error envelope for client handling."}},"additionalProperties":false,"type":"object","required":["error"],"title":"ApiErrorResponse","description":"OpenAI-compatible customer-facing error response.","example":{"error":{"code":"invalid_model","message":"The request could not be processed.","param":"model","type":"invalid_request_error"}}},"AspectRatio":{"type":"string","enum":["auto","4:3","3:4","16:9","9:16","2:3","3:2","1:1","4:5","5:4","21:9"],"title":"AspectRatio","description":"Supported image aspect ratios."},"BalanceResponse":{"properties":{"balance_usd":{"type":"string","title":"Balance Usd","description":"Available account balance as a decimal string."},"currency":{"type":"string","const":"USD","title":"Currency","description":"Balance currency.","default":"USD"},"webhook_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Secret","description":"HMAC secret for image Job webhooks. Present on API-key `GET /v1/balance` only. Store it on your backend. Created on first API-key read or first `webhook_url` Job if missing."}},"additionalProperties":false,"type":"object","required":["balance_usd"],"title":"BalanceResponse","description":"``GET /v1/balance`` response.","example":{"balance_usd":"25.50","currency":"USD","webhook_secret":"whsec_example"}},"ChatCompletionChoice":{"properties":{"index":{"type":"integer","minimum":0.0,"title":"Index"},"message":{"$ref":"#/components/schemas/ChatCompletionMessage"},"finish_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finish Reason"},"logprobs":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Logprobs"}},"additionalProperties":false,"type":"object","required":["index","message"],"title":"ChatCompletionChoice","description":"One non-streaming chat completion choice."},"ChatCompletionMessage":{"properties":{"role":{"type":"string","const":"assistant","title":"Role","default":"assistant"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"reasoning_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning Content","description":"Optional model reasoning content when the selected SKU returns it."},"refusal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refusal"},"function_call":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Function Call"},"tool_calls":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Calls"},"annotations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Annotations"},"audio":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Audio"}},"additionalProperties":false,"type":"object","title":"ChatCompletionMessage","description":"Assistant message in a non-streaming chat completion choice."},"ChatCompletionRequest":{"properties":{"model":{"type":"string","enum":["gemini-3.5-flash","gemini-3.1-flash-lite","gemini-3.1-pro","gemini-3.7-flash"],"title":"Model","default":"gemini-3.5-flash"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","minItems":1,"title":"Messages"},"stream":{"type":"boolean","title":"Stream","default":false},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Top P"},"n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N"},"stop":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stop"},"max_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Tokens"},"max_completion_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Completion Tokens"},"presence_penalty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Presence Penalty"},"frequency_penalty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Frequency Penalty"},"logit_bias":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Logit Bias"},"user":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"response_format":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response Format"},"tools":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tools"},"tool_choice":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tool Choice"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"reasoning_effort":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning Effort"},"stream_options":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Stream Options"},"logprobs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Logprobs"},"top_logprobs":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Top Logprobs"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"moderation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Moderation"},"modalities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Modalities"},"prediction":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prediction"},"audio":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Audio"},"web_search_options":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Web Search Options"},"verbosity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verbosity"},"prompt_cache_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Key"},"prompt_cache_options":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prompt Cache Options"},"prompt_cache_retention":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Cache Retention"},"safety_identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Safety Identifier"},"extra_body":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Extra Body"},"function_call":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Function Call"},"functions":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Functions"},"best_of":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Best Of"},"candidate_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Candidate Count"},"num_return_sequences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Return Sequences"}},"additionalProperties":true,"type":"object","required":["messages"],"title":"ChatCompletionRequest","description":"Public chat request with forward-compatible parameter passthrough."},"ChatCompletionResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Recoverable chatcmpl-<Job UUID> identifier."},"object":{"type":"string","const":"chat.completion","title":"Object","default":"chat.completion"},"created":{"type":"integer","title":"Created","description":"Unix timestamp supplied with the completion."},"model":{"type":"string","title":"Model","description":"The requested public cheapaiapi model SKU."},"choices":{"items":{"$ref":"#/components/schemas/ChatCompletionChoice"},"type":"array","title":"Choices"},"usage":{"$ref":"#/components/schemas/ChatCompletionUsage","description":"Terminal token usage. Present in the JSON response and in the final JSON event before [DONE] when stream=true."},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"}},"additionalProperties":false,"type":"object","required":["id","created","model","choices","usage"],"title":"ChatCompletionResponse","description":"OpenAI-compatible non-streaming text completion response.","example":{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Hello! How can I help?","role":"assistant"}}],"created":1784589000,"id":"chatcmpl-018f5f1c-7b19-7e4a-a5c1-0d44fe93aa10","model":"gemini-3.5-flash","object":"chat.completion","usage":{"completion_tokens":8,"prompt_tokens":12,"total_tokens":20}}},"ChatCompletionTokenDetails":{"properties":{"reasoning_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Reasoning Tokens"},"audio_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Audio Tokens"},"accepted_prediction_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Accepted Prediction Tokens"},"rejected_prediction_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Rejected Prediction Tokens"}},"additionalProperties":false,"type":"object","title":"ChatCompletionTokenDetails","description":"Optional completion-token breakdown returned by the text model."},"ChatCompletionUsage":{"properties":{"prompt_tokens":{"type":"integer","minimum":0.0,"title":"Prompt Tokens","description":"Input tokens billed at the model's input-token rate."},"completion_tokens":{"type":"integer","minimum":0.0,"title":"Completion Tokens","description":"Output tokens billed at the model's output-token rate, including reasoning tokens when the model reports them."},"total_tokens":{"type":"integer","minimum":0.0,"title":"Total Tokens","description":"Sum of prompt_tokens and completion_tokens."},"prompt_tokens_details":{"anyOf":[{"$ref":"#/components/schemas/ChatPromptTokenDetails"},{"type":"null"}]},"completion_tokens_details":{"anyOf":[{"$ref":"#/components/schemas/ChatCompletionTokenDetails"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"title":"ChatCompletionUsage","description":"Authoritative token counts used for this completion's Customer Charge."},"ChatImagePart":{"properties":{"type":{"type":"string","const":"image_url","title":"Type"},"image_url":{"$ref":"#/components/schemas/ChatImageURL"},"prompt_cache_breakpoint":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prompt Cache Breakpoint"}},"type":"object","required":["type","image_url"],"title":"ChatImagePart","description":"Image or file passed using the OpenAI-compatible wire shape."},"ChatImageURL":{"properties":{"url":{"type":"string","title":"Url"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["url"],"title":"ChatImageURL","description":"URL or data URI carried by an ``image_url`` content part."},"ChatMessage":{"properties":{"role":{"type":"string","enum":["system","developer","user","assistant","tool","function"],"title":"Role"},"content":{"anyOf":[{"type":"string"},{"items":{"anyOf":[{"$ref":"#/components/schemas/ChatTextPart"},{"$ref":"#/components/schemas/ChatImagePart"},{"additionalProperties":true,"type":"object"}]},"type":"array"},{"type":"null"}],"title":"Content"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"tool_calls":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Calls"},"tool_call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool Call Id"},"function_call":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Function Call"},"refusal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refusal"},"audio":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Audio"},"annotations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Annotations"}},"type":"object","required":["role"],"title":"ChatMessage","description":"One lossless OpenAI-compatible chat-history message.\n\nTool loops replay provider-authored assistant messages. Some upstreams\nembed a mandatory opaque signature inside ``tool_calls`` and require that\nexact object in the next request, so nested compatibility fields must never\nbe projected away here."},"ChatPromptTokenDetails":{"properties":{"cached_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Cached Tokens"},"audio_tokens":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Audio Tokens"}},"additionalProperties":false,"type":"object","title":"ChatPromptTokenDetails","description":"Optional prompt-token breakdown returned by the text model."},"ChatTextPart":{"properties":{"type":{"type":"string","const":"text","title":"Type"},"text":{"type":"string","title":"Text"},"prompt_cache_breakpoint":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prompt Cache Breakpoint"}},"type":"object","required":["type","text"],"title":"ChatTextPart","description":"One OpenAI-compatible text content part."},"CustomerJobHistoryItem":{"properties":{"id":{"type":"string","title":"Id","description":"CheapAIAPI Job UUID."},"model":{"type":"string","title":"Model","description":"Customer-facing model SKU."},"kind":{"type":"string","title":"Kind","description":"Product kind such as image, chat, or video."},"status":{"type":"string","enum":["queued","running","done","failed"],"title":"Status"},"created_at":{"type":"string","title":"Created At"},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finished At"},"duration_ms":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Duration Ms","description":"Request-to-terminal duration when the Job is terminal."},"billing_status":{"type":"string","enum":["pending","not_charged","charged","partially_refunded","refunded"],"title":"Billing Status"},"charged_usd":{"type":"string","title":"Charged Usd","description":"Ledger debit linked to this Job."},"refunded_usd":{"type":"string","title":"Refunded Usd","description":"Customer Ledger refunds linked to this Job."},"net_spent_usd":{"type":"string","title":"Net Spent Usd","description":"Charge minus linked refunds."},"currency":{"type":"string","const":"USD","title":"Currency","default":"USD"},"error":{"anyOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["id","model","kind","status","created_at","billing_status","charged_usd","refunded_usd","net_spent_usd"],"title":"CustomerJobHistoryItem","description":"One durable customer-visible Job record without request or provider data."},"CustomerJobHistoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CustomerJobHistoryItem"},"type":"array","title":"Data"},"has_more":{"type":"boolean","title":"Has More"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"additionalProperties":false,"type":"object","required":["data","has_more"],"title":"CustomerJobHistoryResponse","description":"Cursor page of account-wide durable Job records.","example":{"data":[{"billing_status":"charged","charged_usd":"0.06","created_at":"2026-08-28T12:00:00+00:00","currency":"USD","duration_ms":12000,"finished_at":"2026-08-28T12:00:12+00:00","id":"00000000-0000-4000-8000-000000000000","kind":"image","model":"nano-banana-pro-2k","net_spent_usd":"0.06","refunded_usd":"0","status":"done"}],"has_more":true,"next_cursor":"eyJ2IjoxLCIuLi4iOiIuLi4ifQ"}},"CustomerTransactionHistoryItem":{"properties":{"id":{"type":"string","title":"Id","description":"Stable Customer Ledger transaction UUID."},"type":{"type":"string","enum":["topup","debit","refund","adjustment"],"title":"Type"},"amount_usd":{"type":"string","title":"Amount Usd","description":"Signed balance delta. Credits are positive and debits are negative."},"currency":{"type":"string","const":"USD","title":"Currency","default":"USD"},"created_at":{"type":"string","title":"Created At"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id","description":"Related Job UUID for a usage debit or refund, when present."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Customer-facing model SKU of the related Job, when present."}},"additionalProperties":false,"type":"object","required":["id","type","amount_usd","created_at"],"title":"CustomerTransactionHistoryItem","description":"One balance-changing Customer Ledger event."},"CustomerTransactionHistoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CustomerTransactionHistoryItem"},"type":"array","title":"Data"},"has_more":{"type":"boolean","title":"Has More"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"additionalProperties":false,"type":"object","required":["data","has_more"],"title":"CustomerTransactionHistoryResponse","description":"Cursor page of account-wide balance-changing transactions.","example":{"data":[{"amount_usd":"-0.06","created_at":"2026-08-28T12:00:12+00:00","currency":"USD","id":"aaaaaaaa-0000-4000-8000-000000000000","job_id":"00000000-0000-4000-8000-000000000000","model":"nano-banana-pro-2k","type":"debit"}],"has_more":false}},"ErrorEnvelope":{"properties":{"type":{"type":"string","title":"Type"},"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message","description":"Human-readable public error text. For moderated content-policy refusals, this may contain a localized user-facing explanation of why generation was rejected; other failures use stable generic text."},"param":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Param"}},"additionalProperties":false,"type":"object","required":["type","code","message"],"title":"ErrorEnvelope","description":"Error details for failed jobs."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageDataItem":{"properties":{"url":{"type":"string","title":"Url"},"revised_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revised Prompt"}},"additionalProperties":false,"type":"object","required":["url"],"title":"ImageDataItem","description":"One element in the ``data`` array of a successful response."},"ImageGenerationRequest":{"properties":{"model":{"type":"string","maxLength":128,"minLength":1,"title":"Model","description":"SKU from `GET /v1/models`, e.g. `nano-banana-pro-1k`."},"prompt":{"type":"string","maxLength":262144,"minLength":1,"title":"Prompt","description":"Generation or edit instruction."},"response_format":{"type":"string","const":"url","title":"Response Format","description":"Image output format. Only `url` is supported. Omit this field or set it to `url`, then download the image from `data[].url`.","default":"url"},"aspect_ratio":{"anyOf":[{"$ref":"#/components/schemas/AspectRatio"},{"type":"null"}],"description":"Optional aspect ratio. Use `auto` to let the model decide; otherwise must be one of the closed enum."},"prompt_optimization":{"type":"boolean","title":"Prompt Optimization","description":"Defaults to false, disabling provider-side prompt rewriting. Set to true to request safe-prompt rewriting when the selected route supports it.","default":false},"image":{"items":{"type":"string"},"type":"array","maxItems":14,"title":"Image","description":"Reference images for img2img / multi-ref edit. Each entry is either a public `https://` URL OR a `data:image/<mime>;base64,...` URI. Empty list = pure text-to-image. `nano-banana-2.1-*` and `nano-banana-2-lite-*` SKUs allow 14; `nano-banana-pro-*` SKUs allow 14; the base `nano-banana` family allows 4; `gpt-image-*` allows 10; every other image SKU allows at most 10. In the model-limit map the longest matching selector wins.","x-cheapaiapi-model-max-items":{"default":10,"gpt-image-*":10,"nano-banana":4,"nano-banana-*":4,"nano-banana-2":14,"nano-banana-2-*":14,"nano-banana-2.1-*":14,"nano-banana-pro":14,"nano-banana-pro-*":14}},"extra":{"additionalProperties":true,"type":"object","title":"Extra","description":"Optional model- and route-specific advanced generation options. Existing keys remain accepted for compatibility; unsupported keys may be ignored. Do not rely on an option unless support has been confirmed for the selected account and SKU."},"_meta":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Meta","description":"Optional caller metadata for your own support/debugging context. Not used for model routing."},"webhook_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Webhook Url","description":"Optional HTTPS endpoint called once the job reaches `done` or `failed`. Callbacks are signed with the account webhook secret and may be retried."},"custom_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Data","description":"Optional JSON object echoed unchanged in generation responses, job polling, and callbacks when a callback is requested. Compact UTF-8 serialization must be at most 4096 bytes."}},"additionalProperties":false,"type":"object","required":["model","prompt"],"title":"ImageGenerationRequest","description":"``POST /v1/images/generations`` body.\n\nUse ``model`` from ``GET /v1/models`` and a required non-empty ``prompt``.\n``image`` is optional for image-to-image or multi-reference edits; omit it\nfor text-to-image.\n\nProduction clients should prefer ``?async=true``, pass ``webhook_url``,\nand store the returned job ``id``. Recover with ``GET /v1/jobs/{id}`` if\nno callback arrives. Send a stable ``Idempotency-Key`` per client-side\njob and reuse it when retrying after a timeout.","example":{"_meta":{"request_id":"catalog-shot-001"},"aspect_ratio":"1:1","custom_data":{"request_id":"catalog-shot-001"},"extra":{},"image":["https://example.com/input.png"],"model":"nano-banana-pro-2k","prompt":"Place the product on a clean studio background.","prompt_optimization":false,"response_format":"url","webhook_url":"https://example.com/webhooks/cheapaiapi"}},"ImageGenerationResponse":{"properties":{"id":{"type":"string","title":"Id"},"created":{"type":"integer","title":"Created"},"status":{"type":"string","enum":["queued","running","done","failed"],"title":"Status"},"data":{"items":{"$ref":"#/components/schemas/ImageDataItem"},"type":"array","title":"Data"},"error":{"anyOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"type":"null"}]},"usage":{"anyOf":[{"$ref":"#/components/schemas/ResponseUsage"},{"type":"null"}]},"custom_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Data","description":"Optional caller correlation data echoed unchanged."}},"additionalProperties":false,"type":"object","required":["id","created","status"],"title":"ImageGenerationResponse","description":"``POST /v1/images/generations`` body, both happy + ``running`` paths.\n\nOn ``status=\"done\"``: ``data`` is populated, ``error`` is null.\nOn ``status=\"running\"``: ``data=[]``; recover with ``GET /v1/jobs/{id}``\nif no webhook arrives.\nOn ``status=\"queued\"``: same as running but for ``?async=true`` returns.\nOn ``status=\"failed\"``: ``data=[]``, ``error`` populated.","examples":[{"created":1770000000,"data":[],"id":"00000000-0000-4000-8000-000000000000","status":"queued","usage":{"balance_remaining_usd":42.5,"cost_usd":0.06}},{"created":1770000000,"data":[],"id":"00000000-0000-4000-8000-000000000000","status":"running","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}},{"created":1770000000,"data":[{"url":"https://cheapaiapi.org/v1/jobs/00000000-0000-4000-8000-000000000000/results/0?sig=example"}],"id":"00000000-0000-4000-8000-000000000000","status":"done","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}}],"example":{"created":1770000000,"data":[{"url":"https://cheapaiapi.org/v1/jobs/00000000-0000-4000-8000-000000000000/results/0?sig=example"}],"id":"00000000-0000-4000-8000-000000000000","status":"done","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}}},"ImageInputCapabilities":{"properties":{"max_items":{"type":"integer","minimum":1.0,"title":"Max Items","description":"Hard maximum number of items accepted in the request `image` array."},"accepted_formats":{"items":{"type":"string","enum":["https_url","data_image_base64_uri"]},"type":"array","title":"Accepted Formats","description":"Provider-neutral forms accepted for every `image` item."}},"additionalProperties":false,"type":"object","required":["max_items","accepted_formats"],"title":"ImageInputCapabilities","description":"Reference-image inputs accepted by one image SKU."},"JobLookupResponse":{"properties":{"id":{"type":"string","title":"Id"},"created_at":{"type":"string","title":"Created At"},"status":{"type":"string","enum":["queued","running","done","failed"],"title":"Status"},"model":{"type":"string","title":"Model"},"finished_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finished At"},"data":{"items":{"$ref":"#/components/schemas/ImageDataItem"},"type":"array","title":"Data"},"error":{"anyOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"type":"null"}]},"usage":{"anyOf":[{"$ref":"#/components/schemas/ResponseUsage"},{"type":"null"}]},"custom_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Data","description":"Optional caller correlation data echoed unchanged."},"response":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Response","description":"Persisted response for a completed chat job. Image jobs use data instead."}},"additionalProperties":false,"type":"object","required":["id","created_at","status","model"],"title":"JobLookupResponse","description":"``GET /v1/jobs/{id}``. Superset of ``ImageGenerationResponse`` for poll-recovery.","examples":[{"created_at":"2026-06-29T12:00:00+00:00","id":"00000000-0000-4000-8000-000000000000","model":"nano-banana-pro-2k","status":"running","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}},{"created_at":"2026-06-29T12:00:00+00:00","data":[{"url":"https://cheapaiapi.org/v1/jobs/00000000-0000-4000-8000-000000000000/results/0?sig=example"}],"finished_at":"2026-06-29T12:00:12+00:00","id":"00000000-0000-4000-8000-000000000000","model":"nano-banana-pro-2k","status":"done","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}},{"created_at":"2026-06-29T12:00:00+00:00","error":{"code":"UpstreamDown","message":"The generation could not be completed right now. Please retry the request.","type":"server_error"},"finished_at":"2026-06-29T12:00:12+00:00","id":"00000000-0000-4000-8000-000000000000","model":"nano-banana-pro-2k","status":"failed","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}}],"example":{"created_at":"2026-06-29T12:00:00+00:00","data":[{"url":"https://cheapaiapi.org/v1/jobs/00000000-0000-4000-8000-000000000000/results/0?sig=example"}],"finished_at":"2026-06-29T12:00:12+00:00","id":"00000000-0000-4000-8000-000000000000","model":"nano-banana-pro-2k","status":"done","usage":{"balance_remaining_usd":42.44,"cost_usd":0.06}}},"LegacyVideoCreateRequest":{"properties":{"model":{"type":"string","enum":["seedance-2.0","seedance-2.5","seedance-2.5-nsfw"],"title":"Model","description":"The fixed public video model SKU."},"prompt":{"type":"string","maxLength":30000,"minLength":1,"title":"Prompt","description":"Text instruction for the generated video. Up to 10,000 characters for seedance-2.0 and 30,000 for Seedance 2.5 models."},"duration":{"type":"integer","maximum":30.0,"minimum":4.0,"title":"Duration","description":"Generated length in seconds: 4 to 15 for seedance-2.0, 4 to 30 for Seedance 2.5 models. Default 5.","default":5},"resolution":{"type":"string","enum":["480p","720p","1080p","4k"],"title":"Resolution","description":"Output resolution. seedance-2.0 accepts 480p, 720p, 1080p, and 4k. seedance-2.5 accepts 480p, 720p, and 1080p. Retained compatibility models keep their frozen resolution contract.","default":"720p"},"aspect_ratio":{"type":"string","enum":["16:9","9:16","1:1","4:3","3:4","21:9","adaptive"],"title":"Aspect Ratio","description":"Output aspect ratio. Default 16:9.","default":"16:9"},"generate_audio":{"type":"boolean","title":"Generate Audio","description":"Whether to generate audio with the clip. Default true.","default":true},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Url","description":"Optional HTTPS or inline data:image/...;base64 first-frame image. This becomes the first frame of the clip, not a style reference. Use image_url; input_image is not accepted. The URL must return image bytes directly without authentication or cookies and remain publicly downloadable until generation finishes. A browser preview or sharing-page URL is not an image URL."},"seed":{"anyOf":[{"type":"integer","maximum":4294967295.0,"minimum":-1.0},{"type":"null"}],"title":"Seed","description":"Random seed that controls the randomness of generated content, -1 by default (replaced by a random number). The same seed value for the same request gives similar results, but complete consistency is not guaranteed."},"nsfw_check":{"type":"boolean","title":"Nsfw Check","description":"When true, prompts and images get an extra content-moderation pass before generation and flagged requests fail with a content-policy error at no charge. The model's built-in safety system always applies. Default false.","default":false},"last_frame_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Frame Image Url","description":"Optional HTTPS or inline data:image/...;base64 last-frame image. This is the final frame of the clip, not a style reference and not the first frame. The URL must return image bytes directly without authentication or cookies and remain publicly downloadable until generation finishes."},"reference_image_urls":{"items":{"type":"string"},"type":"array","maxItems":30,"title":"Reference Image Urls","description":"Optional HTTPS or inline data:image/...;base64 reference images (style or identity). Not a first or last frame. Entries are numbered from 1 in array order, so the prompt may refer to the first URL as `@Image1`, the second as `@Image2`, and so on. First/last-frame images are not part of this numbering. The total of first frame, last frame, and reference images may not exceed 9 for seedance-2.0 or 30 for Seedance 2.5 models. Every URL must return image bytes directly without authentication or cookies and remain publicly downloadable until generation finishes."},"reference_audio_urls":{"items":{"type":"string"},"type":"array","maxItems":10,"title":"Reference Audio Urls","description":"Optional HTTPS or inline data:audio/wav|mpeg;base64 audio references (up to 15 MB each) for Seedance 2.5 models only. At most 10 tracks with no more than 30 seconds combined. They guide the whole generation (for example rhythm or synchronization); prompt tags cannot select an individual track. Audio references do not change the generation price."}},"additionalProperties":false,"type":"object","required":["model","prompt"],"title":"LegacyVideoCreateRequest","description":"Retained flat request vocabulary for existing integrations and retries.","example":{"aspect_ratio":"16:9","duration":5,"image_url":"https://example.com/first-frame.jpg","model":"seedance-2.0","prompt":"A paper boat crossing a rainy street.","resolution":"720p"}},"ModelCapabilities":{"properties":{"image_input":{"$ref":"#/components/schemas/ImageInputCapabilities"}},"additionalProperties":false,"type":"object","required":["image_input"],"title":"ModelCapabilities","description":"Typed request capabilities attached to an authenticated model row."},"ModelInfo":{"properties":{"id":{"type":"string","title":"Id","description":"Public model SKU to pass in generation requests."},"pricing_unit":{"type":"string","enum":["per_call","per_output_second_by_resolution","per_million_tokens"],"title":"Pricing Unit","description":"How this model is billed. Other price fields are omitted."},"price_per_call_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Price Per Call Usd","description":"Current per-call price as a decimal string."},"input_price_per_million_tokens_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Price Per Million Tokens Usd","description":"Current input-token price per one million tokens."},"output_price_per_million_tokens_usd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Price Per Million Tokens Usd","description":"Current output-token price per one million tokens."},"price_per_output_second_usd_by_resolution":{"anyOf":[{"additionalProperties":{"type":"string"},"propertyNames":{"enum":["480p","720p","1080p","4k"]},"type":"object"},{"type":"null"}],"title":"Price Per Output Second Usd By Resolution","description":"Current video price per output second for each supported resolution."},"currency":{"type":"string","const":"USD","title":"Currency","description":"Pricing currency.","default":"USD"},"object":{"type":"string","const":"model","title":"Object","description":"OpenAI-compatible object type.","default":"model"},"owned_by":{"type":"string","const":"cheapaiapi","title":"Owned By","description":"OpenAI-compatible owner label.","default":"cheapaiapi"},"capabilities":{"anyOf":[{"$ref":"#/components/schemas/ModelCapabilities"},{"type":"null"}],"description":"Provider-neutral request capabilities for this enabled SKU."}},"additionalProperties":false,"type":"object","required":["id","pricing_unit"],"title":"ModelInfo","description":"One public model row from ``GET /v1/models``."},"ModelListResponse":{"properties":{"object":{"type":"string","const":"list","title":"Object","description":"OpenAI-compatible object type.","default":"list"},"data":{"items":{"$ref":"#/components/schemas/ModelInfo"},"type":"array","title":"Data","description":"Public image, video, and text generation models enabled for the account."}},"additionalProperties":false,"type":"object","required":["data"],"title":"ModelListResponse","description":"``GET /v1/models`` response.","example":{"data":[{"capabilities":{"image_input":{"accepted_formats":["https_url","data_image_base64_uri"],"max_items":14}},"currency":"USD","id":"nano-banana-pro-2k","object":"model","owned_by":"cheapaiapi","price_per_call_usd":"0.0950","pricing_unit":"per_call"},{"currency":"USD","id":"seedance-2.0","price_per_output_second_usd_by_resolution":{"1080p":"0.5500","480p":"0.1150","4k":"1.2500","720p":"0.2500"},"pricing_unit":"per_output_second_by_resolution"},{"currency":"USD","id":"gemini-3.5-flash","input_price_per_million_tokens_usd":"1.0500","output_price_per_million_tokens_usd":"6.3000","pricing_unit":"per_million_tokens"}],"object":"list"}},"ResponseUsage":{"properties":{"cost_usd":{"type":"number","title":"Cost Usd","description":"Amount charged or reserved for this request."},"balance_remaining_usd":{"type":"number","title":"Balance Remaining Usd","description":"Available account balance at response time after this request is accounted for."}},"additionalProperties":false,"type":"object","required":["cost_usd","balance_remaining_usd"],"title":"ResponseUsage","description":"Customer-facing money usage for one response."},"ResponsesError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"additionalProperties":false,"type":"object","required":["code","message"],"title":"ResponsesError"},"ResponsesFunctionCallItem":{"properties":{"type":{"type":"string","const":"function_call","title":"Type"},"call_id":{"type":"string","maxLength":512,"minLength":1,"title":"Call Id"},"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"arguments":{"type":"string","title":"Arguments"},"status":{"anyOf":[{"type":"string","enum":["in_progress","completed","incomplete"]},{"type":"null"}],"title":"Status"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},"additionalProperties":false,"type":"object","required":["type","call_id","name","arguments"],"title":"ResponsesFunctionCallItem"},"ResponsesFunctionCallOutput":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"type":{"type":"string","const":"function_call","title":"Type","default":"function_call"},"status":{"type":"string","enum":["completed","incomplete"],"title":"Status"},"call_id":{"type":"string","title":"Call Id"},"name":{"type":"string","title":"Name"},"arguments":{"type":"string","title":"Arguments"}},"additionalProperties":false,"type":"object","required":["status","call_id","name","arguments"],"title":"ResponsesFunctionCallOutput","description":"Function call output from the Responses API."},"ResponsesFunctionCallOutputItem":{"properties":{"type":{"type":"string","const":"function_call_output","title":"Type"},"call_id":{"type":"string","maxLength":512,"minLength":1,"title":"Call Id"},"output":{"type":"string","title":"Output"},"status":{"anyOf":[{"type":"string","enum":["in_progress","completed","incomplete"]},{"type":"null"}],"title":"Status"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},"additionalProperties":false,"type":"object","required":["type","call_id","output"],"title":"ResponsesFunctionCallOutputItem"},"ResponsesFunctionTool":{"properties":{"type":{"type":"string","const":"function","title":"Type"},"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters"},"strict":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strict"}},"additionalProperties":false,"type":"object","required":["type","name"],"title":"ResponsesFunctionTool","description":"The only tool kind qualified for this first public slice."},"ResponsesIncompleteDetails":{"properties":{"reason":{"type":"string","enum":["max_output_tokens","content_filter"],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["reason"],"title":"ResponsesIncompleteDetails"},"ResponsesInputTextPart":{"properties":{"type":{"type":"string","enum":["input_text","output_text"],"title":"Type"},"text":{"type":"string","title":"Text"},"annotations":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Annotations"},"logprobs":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Logprobs"}},"additionalProperties":false,"type":"object","required":["type","text"],"title":"ResponsesInputTextPart"},"ResponsesInputTokenDetails":{"properties":{"cache_write_tokens":{"type":"integer","minimum":0.0,"title":"Cache Write Tokens"},"cached_tokens":{"type":"integer","minimum":0.0,"title":"Cached Tokens"}},"additionalProperties":false,"type":"object","required":["cache_write_tokens","cached_tokens"],"title":"ResponsesInputTokenDetails"},"ResponsesItemReference":{"properties":{"type":{"type":"string","const":"item_reference","title":"Type"},"id":{"type":"string","maxLength":512,"minLength":1,"title":"Id"}},"additionalProperties":false,"type":"object","required":["type","id"],"title":"ResponsesItemReference","description":"A reference to an output item of an earlier response from this account."},"ResponsesMessageItem":{"properties":{"type":{"type":"string","const":"message","title":"Type","default":"message"},"role":{"type":"string","enum":["system","developer","user","assistant"],"title":"Role"},"content":{"anyOf":[{"type":"string"},{"items":{"anyOf":[{"$ref":"#/components/schemas/ResponsesInputTextPart"},{"$ref":"#/components/schemas/ResponsesRefusalPart-Input"}]},"type":"array"}],"title":"Content"},"status":{"anyOf":[{"type":"string","enum":["in_progress","completed","incomplete"]},{"type":"null"}],"title":"Status"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},"additionalProperties":false,"type":"object","required":["role","content"],"title":"ResponsesMessageItem"},"ResponsesMessageOutput":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"type":{"type":"string","const":"message","title":"Type","default":"message"},"role":{"type":"string","const":"assistant","title":"Role","default":"assistant"},"status":{"type":"string","enum":["completed","incomplete"],"title":"Status"},"content":{"items":{"anyOf":[{"$ref":"#/components/schemas/ResponsesOutputTextPart"},{"$ref":"#/components/schemas/ResponsesRefusalPart-Output"}]},"type":"array","title":"Content"}},"additionalProperties":false,"type":"object","required":["status","content"],"title":"ResponsesMessageOutput","description":"Assistant message output from the Responses API."},"ResponsesOutputTextPart":{"properties":{"type":{"type":"string","const":"output_text","title":"Type","default":"output_text"},"text":{"type":"string","title":"Text"},"annotations":{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":0,"title":"Annotations"}},"additionalProperties":false,"type":"object","required":["text"],"title":"ResponsesOutputTextPart","description":"One public assistant text part from the Responses API."},"ResponsesOutputTokenDetails":{"properties":{"reasoning_tokens":{"type":"integer","minimum":0.0,"title":"Reasoning Tokens"}},"additionalProperties":false,"type":"object","required":["reasoning_tokens"],"title":"ResponsesOutputTokenDetails"},"ResponsesReasoningInputItem":{"properties":{"type":{"type":"string","const":"reasoning","title":"Type"}},"additionalProperties":true,"type":"object","required":["type"],"title":"ResponsesReasoningInputItem","description":"A reasoning item replayed by a client; accepted and never sent upstream."},"ResponsesRefusalPart-Input":{"properties":{"type":{"type":"string","const":"refusal","title":"Type"},"refusal":{"type":"string","title":"Refusal"}},"additionalProperties":false,"type":"object","required":["type","refusal"],"title":"ResponsesRefusalPart"},"ResponsesRefusalPart-Output":{"properties":{"type":{"type":"string","const":"refusal","title":"Type","default":"refusal"},"refusal":{"type":"string","title":"Refusal"}},"additionalProperties":false,"type":"object","required":["refusal"],"title":"ResponsesRefusalPart","description":"One public assistant refusal part from the Responses API."},"ResponsesRequest":{"properties":{"model":{"type":"string","title":"Model","default":"gemini-3.5-flash"},"input":{"anyOf":[{"type":"string"},{"items":{"anyOf":[{"$ref":"#/components/schemas/ResponsesMessageItem"},{"$ref":"#/components/schemas/ResponsesFunctionCallItem"},{"$ref":"#/components/schemas/ResponsesFunctionCallOutputItem"},{"$ref":"#/components/schemas/ResponsesReasoningInputItem"},{"$ref":"#/components/schemas/ResponsesItemReference"}]},"type":"array"}],"title":"Input"},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"},"stream":{"type":"boolean","title":"Stream","default":false},"store":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Store","default":false},"previous_response_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Previous Response Id"},"conversation":{"title":"Conversation"},"max_output_tokens":{"anyOf":[{"type":"integer","maximum":65536.0,"minimum":1.0},{"type":"null"}],"title":"Max Output Tokens"},"tools":{"anyOf":[{"items":{"$ref":"#/components/schemas/ResponsesFunctionTool"},"type":"array","maxItems":128},{"type":"null"}],"title":"Tools"},"tool_choice":{"anyOf":[{"type":"string","enum":["none","auto","required"]},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tool Choice"},"parallel_tool_calls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Parallel Tool Calls"},"text":{"anyOf":[{"$ref":"#/components/schemas/ResponsesTextConfig"},{"type":"null"}]},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature"},"top_p":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Top P"},"metadata":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":16},{"type":"null"}],"title":"Metadata"},"user":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"User"},"safety_identifier":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Safety Identifier"},"prompt_cache_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Prompt Cache Key"},"truncation":{"anyOf":[{"type":"string","enum":["disabled","auto"]},{"type":"null"}],"title":"Truncation"},"service_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Tier"},"stream_options":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Stream Options"},"include":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Include"},"reasoning":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Reasoning"}},"type":"object","required":["input"],"title":"ResponsesRequest","description":"Stateless public Responses request.\n\nHarmless OpenAI fields are accepted as local no-ops; only the fields in\n``_UPSTREAM_FIELDS`` ever reach the supplier."},"ResponsesTerminalResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Recoverable resp_<Job UUID> identifier."},"object":{"type":"string","const":"response","title":"Object","default":"response"},"created_at":{"type":"integer","title":"Created At","description":"Unix seconds when the request was accepted."},"status":{"type":"string","enum":["queued","in_progress","completed","incomplete","failed"],"title":"Status"},"error":{"anyOf":[{"$ref":"#/components/schemas/ResponsesError"},{"type":"null"}]},"incomplete_details":{"anyOf":[{"$ref":"#/components/schemas/ResponsesIncompleteDetails"},{"type":"null"}]},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"},"max_output_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Output Tokens"},"metadata":{"additionalProperties":{"type":"string"},"type":"object","title":"Metadata"},"model":{"type":"string","title":"Model","description":"The requested public cheapaiapi model SKU."},"output":{"items":{"anyOf":[{"$ref":"#/components/schemas/ResponsesMessageOutput"},{"$ref":"#/components/schemas/ResponsesFunctionCallOutput"}]},"type":"array","title":"Output"},"parallel_tool_calls":{"type":"boolean","title":"Parallel Tool Calls"},"previous_response_id":{"type":"null","title":"Previous Response Id"},"reasoning":{"type":"null","title":"Reasoning"},"service_tier":{"type":"string","const":"default","title":"Service Tier","default":"default"},"store":{"type":"boolean","const":false,"title":"Store","default":false},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"},"text":{"additionalProperties":true,"type":"object","title":"Text"},"tool_choice":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"}],"title":"Tool Choice"},"tools":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Tools"},"top_p":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Top P"},"truncation":{"type":"string","const":"disabled","title":"Truncation","default":"disabled"},"usage":{"anyOf":[{"$ref":"#/components/schemas/ResponsesTokenUsage"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["id","created_at","status","model","output","parallel_tool_calls","text","tool_choice","tools"],"title":"ResponsesTerminalResponse","description":"The OpenAI Response object returned by ``/v1/responses``.","example":{"created_at":1790000000,"id":"resp_018f5f1c-7b19-7e4a-a5c1-0d44fe93aa10","metadata":{},"model":"gemini-3.7-flash","object":"response","output":[{"content":[{"annotations":[],"text":"Hello!","type":"output_text"}],"id":"ri_018f5f1c7b197e4aa5c10d44fe93aa10_0","role":"assistant","status":"completed","type":"message"}],"parallel_tool_calls":true,"service_tier":"default","status":"completed","store":false,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"truncation":"disabled","usage":{"input_tokens":12,"input_tokens_details":{"cache_write_tokens":0,"cached_tokens":0},"output_tokens":8,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":20}}},"ResponsesTextConfig":{"properties":{"format":{"anyOf":[{"$ref":"#/components/schemas/ResponsesTextFormat"},{"type":"null"}]},"verbosity":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Verbosity"}},"additionalProperties":false,"type":"object","title":"ResponsesTextConfig"},"ResponsesTextFormat":{"properties":{"type":{"type":"string","enum":["text","json_object","json_schema"],"title":"Type","default":"text"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Schema"},"strict":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strict"}},"additionalProperties":false,"type":"object","title":"ResponsesTextFormat","description":"Qualified Responses text output shape."},"ResponsesTokenUsage":{"properties":{"input_tokens":{"type":"integer","minimum":0.0,"title":"Input Tokens"},"output_tokens":{"type":"integer","minimum":0.0,"title":"Output Tokens"},"total_tokens":{"type":"integer","minimum":0.0,"title":"Total Tokens"},"input_tokens_details":{"$ref":"#/components/schemas/ResponsesInputTokenDetails"},"output_tokens_details":{"$ref":"#/components/schemas/ResponsesOutputTokenDetails"}},"additionalProperties":false,"type":"object","required":["input_tokens","output_tokens","total_tokens","input_tokens_details","output_tokens_details"],"title":"ResponsesTokenUsage","description":"Authoritative terminal token counts used for billing."},"Seedance20CreateRequest":{"properties":{"model":{"type":"string","const":"seedance-2.0","title":"Model"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/SeedanceTextContent"},{"$ref":"#/components/schemas/SeedanceImageContent"},{"$ref":"#/components/schemas/SeedanceAudioContent"},{"$ref":"#/components/schemas/SeedanceVideoContent"}],"discriminator":{"propertyName":"type","mapping":{"audio_url":"#/components/schemas/SeedanceAudioContent","image_url":"#/components/schemas/SeedanceImageContent","text":"#/components/schemas/SeedanceTextContent","video_url":"#/components/schemas/SeedanceVideoContent"}}},"type":"array","maxItems":16,"minItems":1,"title":"Content","description":"Exactly one non-empty text item, with optional frame images or reference media: up to nine ordered reference images, up to 3 reference videos (total at most 15 seconds) and up to 3 audio references. Audio requires a reference image or video. First/last-frame images cannot be combined with reference media. With reference videos the price uses billed seconds: total reference-video seconds rounded up plus output seconds, at least 5/3 of the output seconds rounded up, at the with-video rate."},"duration":{"type":"integer","maximum":15.0,"minimum":4.0,"title":"Duration","default":5},"resolution":{"type":"string","enum":["480p","720p","1080p","4k"],"title":"Resolution","description":"Output resolution. 4k output is H.265/HEVC, which some browsers cannot play inline.","default":"720p"},"ratio":{"type":"string","enum":["16:9","9:16","1:1","4:3","3:4","21:9","adaptive"],"title":"Ratio","default":"adaptive"},"generate_audio":{"type":"boolean","title":"Generate Audio","default":true},"seed":{"anyOf":[{"type":"integer","maximum":4294967295.0,"minimum":-1.0},{"type":"null"}],"title":"Seed","description":"Random seed that controls the randomness of generated content, -1 by default (replaced by a random number). The same seed value for the same request gives similar results, but complete consistency is not guaranteed."},"nsfw_check":{"type":"boolean","title":"Nsfw Check","description":"When true, prompts and images get an extra content-moderation pass before generation and flagged requests fail with a content-policy error at no charge. The model's built-in safety system always applies. Default false.","default":false},"return_last_frame":{"type":"boolean","title":"Return Last Frame","description":"Also keep the clip's last frame as an image. Download it from `GET /v1/videos/{id}/content?variant=last_frame` after completion, for example as the first frame of a follow-up clip.","default":false}},"additionalProperties":false,"type":"object","required":["model","content"],"title":"Seedance20CreateRequest","description":"Seedance 2.0: text, frame inputs, or image/video/audio references."},"Seedance25CreateRequest":{"properties":{"model":{"type":"string","const":"seedance-2.5","title":"Model"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/SeedanceTextContent"},{"$ref":"#/components/schemas/SeedanceImageContent"},{"$ref":"#/components/schemas/SeedanceAudioContent"},{"$ref":"#/components/schemas/SeedanceVideoContent"}],"discriminator":{"propertyName":"type","mapping":{"audio_url":"#/components/schemas/SeedanceAudioContent","image_url":"#/components/schemas/SeedanceImageContent","text":"#/components/schemas/SeedanceTextContent","video_url":"#/components/schemas/SeedanceVideoContent"}}},"type":"array","maxItems":51,"minItems":1,"title":"Content","description":"Exactly one non-empty text item, with optional frame images or up to 30 ordered reference images, 10 reference videos (total at most 30 seconds) and 10 audio references. Audio references must total no more than 30 seconds. Frame inputs require ratio=adaptive and cannot be combined with reference media. With reference videos the price uses billed seconds: total reference-video seconds rounded up plus output seconds, at least 5/3 of the output seconds rounded up, at the with-video rate."},"omni_reference_task_type":{"anyOf":[{"type":"string","enum":["auto","reference","edit","extend"]},{"type":"null"}],"title":"Omni Reference Task Type","description":"Seedance 2.5 only. Task type for reference media: auto (default, inferred from the prompt), reference (a new shot guided by the reference video), edit (edit the reference video, with duration -1), or extend (continue the reference video). reference, edit, and extend need at least one reference video. A request that does not fit the declared type fails with a full refund."},"duration":{"type":"integer","maximum":30.0,"minimum":-1.0,"title":"Duration","description":"Required output length in seconds, from 4 to 30. seedance-2.5 with at least one reference video also accepts -1 (the request runs as a video edit of the reference video): the output keeps the edited reference video's length, which must be 4 to 30 seconds, and ratio must be adaptive. A -1 request is priced as if duration were the total reference-video seconds rounded up (at most 30).","examples":[5,-1]},"resolution":{"type":"string","enum":["480p","720p","1080p"],"title":"Resolution","description":"Supported output resolutions are 480p, 720p, and 1080p.","default":"720p"},"ratio":{"type":"string","enum":["16:9","9:16","1:1","4:3","3:4","21:9","adaptive"],"title":"Ratio","default":"adaptive"},"generate_audio":{"type":"boolean","title":"Generate Audio","default":true},"seed":{"anyOf":[{"type":"integer","maximum":4294967295.0,"minimum":-1.0},{"type":"null"}],"title":"Seed","description":"Random seed that controls the randomness of generated content, -1 by default (replaced by a random number). The same seed value for the same request gives similar results, but complete consistency is not guaranteed."},"nsfw_check":{"type":"boolean","title":"Nsfw Check","description":"When true, prompts and images get an extra content-moderation pass before generation and flagged requests fail with a content-policy error at no charge. The model's built-in safety system always applies. Default false.","default":false},"return_last_frame":{"type":"boolean","title":"Return Last Frame","description":"Also keep the clip's last frame as an image. Download it from `GET /v1/videos/{id}/content?variant=last_frame` after completion, for example as the first frame of a follow-up clip.","default":false},"watermark":{"type":"boolean","title":"Watermark","description":"Request a watermark on the generated video. Appearance is not guaranteed. Default false.","default":false},"output_format":{"type":"string","enum":["mp4","mov"],"title":"Output Format","description":"Container of the generated video: mp4 (default) or mov.","default":"mp4"}},"additionalProperties":false,"type":"object","required":["model","content","duration"],"title":"Seedance25CreateRequest","description":"Standard public Seedance 2.5, including 1080p output."},"Seedance25NsfwCreateRequest":{"properties":{"model":{"type":"string","const":"seedance-2.5-nsfw","title":"Model"},"content":{"items":{"oneOf":[{"$ref":"#/components/schemas/SeedanceTextContent"},{"$ref":"#/components/schemas/SeedanceImageContent"},{"$ref":"#/components/schemas/SeedanceAudioContent"},{"$ref":"#/components/schemas/SeedanceVideoContent"}],"discriminator":{"propertyName":"type","mapping":{"audio_url":"#/components/schemas/SeedanceAudioContent","image_url":"#/components/schemas/SeedanceImageContent","text":"#/components/schemas/SeedanceTextContent","video_url":"#/components/schemas/SeedanceVideoContent"}}},"type":"array","maxItems":51,"minItems":1,"title":"Content","description":"Exactly one non-empty text item, with optional frame images or up to 30 ordered reference images, 10 reference videos (total at most 30 seconds) and 10 audio references. Audio references must total no more than 30 seconds. Frame inputs require ratio=adaptive and cannot be combined with reference media. With reference videos the price uses billed seconds: total reference-video seconds rounded up plus output seconds, at least 5/3 of the output seconds rounded up, at the with-video rate."},"omni_reference_task_type":{"anyOf":[{"type":"string","enum":["auto","reference","edit","extend"]},{"type":"null"}],"title":"Omni Reference Task Type","description":"Seedance 2.5 only. Task type for reference media: auto (default, inferred from the prompt), reference (a new shot guided by the reference video), edit (edit the reference video, with duration -1), or extend (continue the reference video). reference, edit, and extend need at least one reference video. A request that does not fit the declared type fails with a full refund."},"duration":{"type":"integer","maximum":30.0,"minimum":-1.0,"title":"Duration","description":"Required output length in seconds, from 4 to 30. seedance-2.5 with at least one reference video also accepts -1 (the request runs as a video edit of the reference video): the output keeps the edited reference video's length, which must be 4 to 30 seconds, and ratio must be adaptive. A -1 request is priced as if duration were the total reference-video seconds rounded up (at most 30).","examples":[5,-1]},"resolution":{"type":"string","enum":["480p","720p"],"title":"Resolution","description":"Supported output resolutions are 480p and 720p.","default":"720p"},"ratio":{"type":"string","enum":["16:9","9:16","1:1","4:3","3:4","21:9","adaptive"],"title":"Ratio","default":"adaptive"},"generate_audio":{"type":"boolean","title":"Generate Audio","default":true},"seed":{"anyOf":[{"type":"integer","maximum":4294967295.0,"minimum":-1.0},{"type":"null"}],"title":"Seed","description":"Random seed that controls the randomness of generated content, -1 by default (replaced by a random number). The same seed value for the same request gives similar results, but complete consistency is not guaranteed."},"nsfw_check":{"type":"boolean","title":"Nsfw Check","description":"When true, prompts and images get an extra content-moderation pass before generation and flagged requests fail with a content-policy error at no charge. The model's built-in safety system always applies. Default false.","default":false},"return_last_frame":{"type":"boolean","title":"Return Last Frame","description":"Also keep the clip's last frame as an image. Download it from `GET /v1/videos/{id}/content?variant=last_frame` after completion, for example as the first frame of a follow-up clip.","default":false},"watermark":{"type":"boolean","title":"Watermark","description":"Request a watermark on the generated video. Appearance is not guaranteed. Default false.","default":false},"output_format":{"type":"string","enum":["mp4","mov"],"title":"Output Format","description":"Container of the generated video: mp4 (default) or mov.","default":"mp4"}},"additionalProperties":false,"type":"object","required":["model","content","duration"],"title":"Seedance25NsfwCreateRequest","description":"Retained account-scoped compatibility schema; unavailable for new enablement."},"SeedanceAudioContent":{"properties":{"type":{"type":"string","const":"audio_url","title":"Type"},"audio_url":{"$ref":"#/components/schemas/SeedanceAudioSource"},"role":{"type":"string","const":"reference_audio","title":"Role"}},"additionalProperties":false,"type":"object","required":["type","audio_url","role"],"title":"SeedanceAudioContent","description":"A whole-generation audio reference."},"SeedanceAudioSource":{"properties":{"url":{"type":"string","title":"Url","description":"HTTPS audio URL or data:audio/wav;base64,<bytes> or data:audio/mpeg;base64,<bytes> for standard models. Up to 15 MB decoded per track. The URL must return audio bytes without authentication or cookies and remain downloadable until generation finishes. Retained compatibility requests may require HTTPS. Bytes are privately retained and rehosted for generation."}},"additionalProperties":false,"type":"object","required":["url"],"title":"SeedanceAudioSource","description":"HTTPS or inline WAV/MP3 bytes for standard video models."},"SeedanceImageContent":{"properties":{"type":{"type":"string","const":"image_url","title":"Type"},"image_url":{"$ref":"#/components/schemas/SeedanceImageSource"},"role":{"type":"string","enum":["first_frame","last_frame","reference_image"],"title":"Role","description":"Image role. Omitting role selects first_frame. Frame inputs cannot be combined with reference media. Reference images retain their array order.","default":"first_frame"}},"additionalProperties":false,"type":"object","required":["type","image_url"],"title":"SeedanceImageContent","description":"An image with its official first-frame, last-frame, or reference role."},"SeedanceImageSource":{"properties":{"url":{"type":"string","title":"Url","description":"HTTPS image URL or data:image/<format>;base64,<bytes> for standard models. HTTPS images: PNG, JPEG, WebP, BMP, TIFF, GIF, AVIF, or HEIC/HEIF. Inline PNG, JPEG, WebP, BMP, TIFF, GIF, or AVIF. Each image smaller than 30 MB, 300–6000 pixels per dimension, aspect ratio 0.4–2.5. Retained compatibility requests may require HTTPS. Bytes are privately retained and rehosted for generation."}},"additionalProperties":false,"type":"object","required":["url"],"title":"SeedanceImageSource","description":"HTTPS or inline image bytes for standard video models."},"SeedanceTextContent":{"properties":{"type":{"type":"string","const":"text","title":"Type"},"text":{"type":"string","maxLength":30000,"minLength":1,"title":"Text","description":"The prompt: up to 10,000 characters for seedance-2.0 and 30,000 for Seedance 2.5 models. Refer to reference media in the prompt as @image1, @image2, …, @video1, …. Numbering starts at 1 and counts each media type separately, in the order the items appear in `content`. Only `reference_image` items count as images."}},"additionalProperties":false,"type":"object","required":["type","text"],"title":"SeedanceTextContent","description":"The single required text instruction in content."},"SeedanceVideoContent":{"properties":{"type":{"type":"string","const":"video_url","title":"Type"},"video_url":{"$ref":"#/components/schemas/SeedanceVideoSource"},"role":{"type":"string","const":"reference_video","title":"Role"}},"additionalProperties":false,"type":"object","required":["type","video_url","role"],"title":"SeedanceVideoContent","description":"A reference video for motion, camera, or editing guidance.\n\nMP4 or MOV, at most 50 MB (200 MB by HTTPS URL on seedance-2.5), each clip\nat least 2 seconds; 480p to 720p,\nor up to 1080p on standard seedance-2.5. A prompt that restyles or\nchanges the clip itself is treated as a video edit, which keeps the\nclip's length: on seedance-2.5 send duration=-1 with ratio=adaptive\n(edited clip 4 to 30 seconds), optionally with\nomni_reference_task_type=edit. To extend the clip send\nomni_reference_task_type=extend; to use it as motion/camera guidance,\ndescribe a new shot with an explicit output duration."},"SeedanceVideoSource":{"properties":{"url":{"type":"string","title":"Url","description":"HTTPS video URL or data:video/mp4;base64,<bytes> or data:video/quicktime;base64,<bytes> for standard models. Up to 50 MB per clip (200 MB per HTTPS clip on seedance-2.5); 200 MB total input media per Job. Inline clips stay at 50 MB decoded. Base64 adds about one third to JSON size; your ingress may impose a lower limit. Retained compatibility requests may require HTTPS. Each clip is 2-15 seconds (seedance-2.0) or 2-30 seconds (seedance-2.5) at 480p-720p (409,600-927,408 pixels per frame); standard seedance-2.5 also accepts 1080p (up to 2,211,840 pixels)."}},"additionalProperties":false,"type":"object","required":["url"],"title":"SeedanceVideoSource","description":"HTTPS or inline MP4/MOV bytes for standard video models."},"UsageByModelItem":{"properties":{"model":{"type":"string","title":"Model","description":"Public model SKU."},"total_calls":{"type":"integer","title":"Total Calls","description":"Total jobs created in the selected time window."},"successful_calls":{"type":"integer","title":"Successful Calls","description":"Jobs that completed successfully."},"failed_calls":{"type":"integer","title":"Failed Calls","description":"Jobs that failed."},"total_spent_usd":{"type":"string","title":"Total Spent Usd","description":"Total debited amount as a decimal string."}},"additionalProperties":false,"type":"object","required":["model","total_calls","successful_calls","failed_calls","total_spent_usd"],"title":"UsageByModelItem","description":"Usage aggregates for one public model SKU."},"UsageResponse":{"properties":{"from":{"type":"string","title":"From","description":"Inclusive start of the usage window."},"to":{"type":"string","title":"To","description":"Exclusive end of the usage window."},"total_calls":{"type":"integer","title":"Total Calls","description":"Total jobs created in the selected time window."},"successful_calls":{"type":"integer","title":"Successful Calls","description":"Jobs that completed successfully."},"failed_calls":{"type":"integer","title":"Failed Calls","description":"Jobs that failed."},"total_spent_usd":{"type":"string","title":"Total Spent Usd","description":"Total debited amount as a decimal string."},"currency":{"type":"string","const":"USD","title":"Currency","description":"Usage currency.","default":"USD"},"by_model":{"items":{"$ref":"#/components/schemas/UsageByModelItem"},"type":"array","title":"By Model","description":"Usage grouped by public model SKU."}},"additionalProperties":false,"type":"object","required":["from","to","total_calls","successful_calls","failed_calls","total_spent_usd","by_model"],"title":"UsageResponse","description":"``GET /v1/usage`` response.","example":{"by_model":[{"failed_calls":2,"model":"nano-banana-pro-2k","successful_calls":40,"total_calls":42,"total_spent_usd":"1.26"}],"currency":"USD","failed_calls":2,"from":"2026-06-01T00:00:00+00:00","successful_calls":40,"to":"2026-06-29T00:00:00+00:00","total_calls":42,"total_spent_usd":"1.26"}},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VideoCreateRequest":{"oneOf":[{"$ref":"#/components/schemas/Seedance20CreateRequest"},{"$ref":"#/components/schemas/Seedance25CreateRequest"},{"$ref":"#/components/schemas/Seedance25NsfwCreateRequest"}],"title":"VideoCreateRequest","description":"Create a video using the supported official Seedance content contract.","discriminator":{"propertyName":"model","mapping":{"seedance-2.0":"#/components/schemas/Seedance20CreateRequest","seedance-2.5":"#/components/schemas/Seedance25CreateRequest","seedance-2.5-nsfw":"#/components/schemas/Seedance25NsfwCreateRequest"}}},"VideoResource":{"properties":{"id":{"type":"string","title":"Id"},"object":{"type":"string","const":"video","title":"Object","default":"video"},"created_at":{"type":"integer","title":"Created At","description":"Unix timestamp in UTC."},"status":{"type":"string","enum":["queued","in_progress","completed","failed"],"title":"Status"},"model":{"type":"string","enum":["seedance-2.0","seedance-2.5","seedance-2.5-nsfw"],"title":"Model"},"completed_at":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Completed At","description":"Unix timestamp in UTC, present only after terminal completion."},"error":{"anyOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"type":"null"}]},"duration":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration","description":"Requested output seconds. For a duration -1 edit this is the billed length (total reference-video seconds rounded up), not a measured output length."},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution","description":"Requested output resolution."},"ratio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ratio","description":"Requested aspect ratio."},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed","description":"The seed, present only when the request sent one."},"output_format":{"anyOf":[{"type":"string","const":"mov"},{"type":"null"}],"title":"Output Format","description":"Present only for mov output; otherwise the video is MP4."},"return_last_frame":{"anyOf":[{"type":"boolean","const":true},{"type":"null"}],"title":"Return Last Frame","description":"Present when the request asked for the last frame; after completion download it from `GET /v1/videos/{id}/content?variant=last_frame`."}},"additionalProperties":false,"type":"object","required":["id","created_at","status","model"],"title":"VideoResource","description":"Recoverable state returned by both create and poll endpoints."}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"Paste your `sk_cheap_...` API key. Need access? Request a quote at https://cheapaiapi.org/contact.","scheme":"bearer","bearerFormat":"API key (sk_cheap_...)"}}},"tags":[{"name":"Chat","description":"Create non-streaming or SSE-streaming text completions."},{"name":"Responses","description":"Create stateless OpenAI-compatible responses as JSON or typed SSE events."},{"name":"Images","description":"Create image generation jobs and retrieve completed image data."},{"name":"Videos","description":"Create video jobs, poll their status, and stream completed media."},{"name":"Jobs","description":"Poll durable image generation jobs after async submission or disconnects."},{"name":"Models","description":"List public model SKUs and account-specific pricing units and rates."},{"name":"Account","description":"Inspect balance and usage for the authenticated account."}]}