{"openapi":"3.1.0","info":{"title":"Sakuranbo AI","version":"0.1.0","description":"One API for text, image, and video generation models. The model catalog and cost estimates need no API key. The account endpoints (`/v1/key` and `/v1/balance`), the chat endpoints (`/v1/chat/completions` and `/v1/messages`), the image endpoints (`/v1/images/generations` and `/v1/images/edits`), the video endpoints (`/v1/videos`), the job endpoints (`/v1/jobs`), and the webhook endpoints (`/v1/webhook-endpoints`) need one."},"servers":[{"url":"https://api.sakuranbo.ai"}],"tags":[{"name":"Models","description":"Model catalog with prices."},{"name":"Estimate","description":"Cost estimates that match the Playground."},{"name":"Chat","description":"Text generation with OpenAI and Anthropic compatible endpoints. Needs an API key and a prepaid balance."},{"name":"Images","description":"Generate and edit images. Needs an API key. A request waits for the result and answers with the images, or with a job to follow if it takes too long."},{"name":"Videos","description":"Generate videos. Needs an API key. A request answers at once with a video to follow until it completes, which takes minutes."},{"name":"Account","description":"The API key in use and the prepaid balance. Needs an API key."},{"name":"Jobs","description":"Generations that run in the background. Get, cancel, and list your jobs (images and videos), and download the files they produce. Needs an API key, except for the signed file URLs."},{"name":"Webhooks","description":"Receive events as signed HTTP POST requests at a URL you register. Deliveries follow the Standard Webhooks specification (https://www.standardwebhooks.com), so an official library can verify them.\n\nEach delivery carries `webhook-id` (the event ID, the same on every retry), `webhook-timestamp` (Unix seconds, new on every attempt), and `webhook-signature` (one or more space-separated `v1,<base64>` values). The signature is an HMAC-SHA256 of `<webhook-id>.<webhook-timestamp>.<raw body>` with the endpoint's secret, which is `whsec_` followed by a base64 key. Verify against the raw body, check that the timestamp is within 5 minutes, and use `webhook-id` to skip events you already handled.\n\nAfter `rotate-secret`, each delivery carries a signature for the new secret and one for the previous secret for 24 hours.\n\nAnswer with a `2xx` status within 15 seconds. Any other answer (redirects are not followed) or a timeout is retried with growing delays, 8 attempts in about 31.5 hours. A `410 Gone` stops the endpoint. Deliveries are kept in the delivery log for 30 days, and a delivery that succeeded or ran out of retries can be retried by hand."},{"name":"Reports","description":"Report generated content that breaks the content policy. No API key is needed."},{"name":"Meta","description":"Service status."}],"externalDocs":{"description":"Documentation","url":"https://sakuranbo.ai/docs/"},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"An API key from the dashboard, sent as `Authorization: Bearer <API key>`."},"ApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"The same API key, sent as `x-api-key`. Only `/v1/messages` accepts it."}},"schemas":{"WebhookJobSucceeded":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["job.succeeded"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/Job"}},"required":["id","type","timestamp","data"]},"Job":{"type":"object","properties":{"id":{"type":"string","example":"job_0123456789abcdef0123456789abcdef"},"object":{"type":"string","enum":["image","video"],"description":"What the job generates."},"model":{"type":"string","example":"sakuranbo/cherryimage-1.0-pro"},"status":{"type":"string","enum":["queued","in_progress","completed","failed","cancelled","expired"],"description":"`queued` and `in_progress` are running. `completed`, `failed`, `cancelled`, and `expired` are final."},"progress":{"type":["integer","null"],"minimum":0,"maximum":100,"description":"Percent done, when the upstream reports it. A video without a reported value gets an estimate from the elapsed time and the duration; it stays below 100 until the job completes. Otherwise `null`."},"created_at":{"type":"string","example":"2026-10-22T09:00:00.000Z"},"completed_at":{"type":["string","null"]},"expires_at":{"type":["string","null"],"description":"When the outputs are deleted (ISO 8601, UTC). Set when the job completes; `null` before."},"error":{"type":["object","null"],"properties":{"message":{"type":"string","example":"Model not found."},"type":{"type":"string","example":"not_found_error"},"code":{"type":"string","enum":["invalid_request","unauthorized","balance_insufficient","key_limit_exceeded","forbidden","account_suspended","not_found","model_not_found","method_not_allowed","idempotency_conflict","payload_too_large","content_policy_violation","rate_limited","concurrency_limited","internal_error","upstream_error","upstream_unavailable","webhooks_unavailable"],"example":"model_not_found"},"param":{"type":["string","null"],"description":"The request parameter that caused the error, if any.","example":"model"},"request_id":{"type":"string","example":"req_0123456789abcdef0123456789abcdef"},"doc_url":{"type":"string","example":"https://example.com/docs/errors/#model_not_found"},"details":{"type":"object","additionalProperties":{},"description":"Extra machine-readable context. For a fixed set of values, `allowed` lists the accepted values. For a numeric range, `minimum` and `maximum` give the limits."}},"required":["message","type","code","param","request_id","doc_url"],"description":"Why the job failed. The same shape as an error response. Set only when `status` is `failed`; a failed job is not charged."},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/JobOutput"},"description":"The generated files. Empty until the job completes and after `expires_at`."},"usage":{"type":["object","null"],"properties":{"output_images":{"type":"integer"}},"required":["output_images"],"description":"What was delivered. `null` until the job completes, and for videos, whose charge is in `cost`."},"cost":{"anyOf":[{"$ref":"#/components/schemas/Cost"},{"type":"null"}],"description":"The amount charged. `null` until the job completes and settles."}},"required":["id","object","model","status","progress","created_at","completed_at","expires_at","error","outputs","usage","cost"]},"JobOutput":{"type":"object","properties":{"url":{"type":"string","description":"A signed URL for the file. It needs no API key and works until `expires_at`. Treat it like a secret."},"content_type":{"type":"string","example":"image/jpeg"},"bytes":{"type":"integer"},"expires_at":{"type":"string","description":"When the URL stops working and the file is deleted (ISO 8601, UTC)."}},"required":["url","content_type","bytes","expires_at"]},"Cost":{"type":"object","properties":{"amount_micro_usd":{"type":"integer"},"amount_usd":{"type":"string","example":"0.045"}},"required":["amount_micro_usd","amount_usd"]},"WebhookJobFailed":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["job.failed"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/Job"}},"required":["id","type","timestamp","data"]},"WebhookJobCancelled":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["job.cancelled"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/Job"}},"required":["id","type","timestamp","data"]},"WebhookDepositCredited":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["deposit.credited"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/WebhookDeposit"}},"required":["id","type","timestamp","data"]},"WebhookDeposit":{"type":"object","properties":{"object":{"type":"string","enum":["deposit"]},"id":{"type":"string","description":"The ID of the deposit in your balance."},"source":{"type":"string","description":"How the deposit was paid, for example `stripe`.","example":"stripe"},"amount":{"type":"object","properties":{"amount_micro_usd":{"type":"integer"},"amount_usd":{"type":"string","example":"25.00"}},"required":["amount_micro_usd","amount_usd"]},"expires_at":{"type":["string","null"],"description":"When the deposited balance expires (ISO 8601, UTC). `null` if it does not expire."},"credited_at":{"type":"string"},"balance":{"anyOf":[{"$ref":"#/components/schemas/Balance"}],"description":"Your balance when the event was prepared; it can include later changes."}},"required":["object","id","source","amount","expires_at","credited_at","balance"]},"Balance":{"type":"object","properties":{"object":{"type":"string","enum":["balance"]},"currency":{"type":"string","enum":["USD"]},"available_micro_usd":{"type":"integer","description":"What new requests can use: the unexpired balance minus the amounts reserved by running requests."},"available_usd":{"type":"string"},"held_micro_usd":{"type":"integer","description":"The amount reserved by running requests until they settle."},"held_usd":{"type":"string"}},"required":["object","currency","available_micro_usd","available_usd","held_micro_usd","held_usd"],"description":"Your prepaid balance: the amount new requests can use, and the amount that running requests have reserved."},"WebhookBalanceLow":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["balance.low"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/WebhookLowBalance"}},"required":["id","type","timestamp","data"]},"WebhookLowBalance":{"type":"object","properties":{"object":{"type":"string","enum":["low_balance"]},"currency":{"type":"string","enum":["USD"]},"available_micro_usd":{"type":"integer","description":"Your available balance after the change that took it below the alert level."},"available_usd":{"type":"string","example":"4.20"},"threshold_micro_usd":{"type":"integer","description":"The alert level you set in the dashboard."},"threshold_usd":{"type":"string","example":"5.00"},"occurred_at":{"type":"string"}},"required":["object","currency","available_micro_usd","available_usd","threshold_micro_usd","threshold_usd","occurred_at"]},"WebhookTestEvent":{"type":"object","properties":{"id":{"type":"string","description":"The event ID. It is also the `webhook-id` header and stays the same on every retry.","example":"evt_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["webhook.test"]},"timestamp":{"type":"string","description":"When the event happened (ISO 8601, UTC).","example":"2026-10-22T09:00:00.000Z"},"data":{"$ref":"#/components/schemas/WebhookTest"}},"required":["id","type","timestamp","data"]},"WebhookTest":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_test"]},"endpoint_id":{"type":"string"},"message":{"type":"string"}},"required":["object","endpoint_id","message"]},"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"environment":{"type":"string","enum":["local","dev","prod"]},"version":{"type":"string"}},"required":["status","environment","version"]},"Status":{"type":"object","properties":{"object":{"type":"string","enum":["status"]},"state":{"type":"string","enum":["ok","unavailable"],"description":"`ok` when the measurements were read. `unavailable` when they could not be read: every number is then `null`."},"generated_at":{"type":["string","null"],"description":"When the measurements were read (ISO 8601). `null` when `state` is `unavailable`."},"min_samples":{"type":"integer","description":"A success rate needs at least this many measured results, and a generation time at least this many successful results. Below it the value is `null` (still being measured)."},"overall":{"type":["object","null"],"properties":{"24h":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured across all models."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."}},"required":["samples","success_rate"]},"7d":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured across all models."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."}},"required":["samples","success_rate"]},"30d":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured across all models."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."}},"required":["samples","success_rate"]}},"required":["24h","7d","30d"],"description":"The success rate across all models."},"models":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"modality":{"type":"string","enum":["text","image","video","audio"]},"windows":{"type":["object","null"],"properties":{"24h":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured, successful or not."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."},"duration_ms":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of successful results the duration is measured from."},"p50":{"type":["integer","null"],"description":"The median duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."},"p95":{"type":["integer","null"],"description":"The 95th percentile duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."}},"required":["samples","p50","p95"]}},"required":["samples","success_rate","duration_ms"]},"7d":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured, successful or not."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."},"duration_ms":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of successful results the duration is measured from."},"p50":{"type":["integer","null"],"description":"The median duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."},"p95":{"type":["integer","null"],"description":"The 95th percentile duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."}},"required":["samples","p50","p95"]}},"required":["samples","success_rate","duration_ms"]},"30d":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of results measured, successful or not."},"success_rate":{"type":["number","null"],"minimum":0,"maximum":1,"description":"The share of results that did not fail with a 5xx status, from 0 to 1. `null` while fewer than `min_samples` results were measured."},"duration_ms":{"type":"object","properties":{"samples":{"type":"integer","description":"The number of successful results the duration is measured from."},"p50":{"type":["integer","null"],"description":"The median duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."},"p95":{"type":["integer","null"],"description":"The 95th percentile duration in milliseconds. `null` while fewer than `min_samples` successful results were measured."}},"required":["samples","p50","p95"]}},"required":["samples","success_rate","duration_ms"]}},"required":["24h","7d","30d"],"description":"`null` when `state` is `unavailable`."}},"required":["id","modality","windows"]}}},"required":["object","state","generated_at","min_samples","overall","models"]},"ModelList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}}},"required":["object","data"]},"Model":{"type":"object","properties":{"id":{"type":"string","example":"sakuranbo/cherryimage-1.0-pro"},"object":{"type":"string","enum":["model"]},"name":{"type":"string"},"vendor":{"type":"string"},"vendor_name":{"type":"string"},"modality":{"type":"string","enum":["text","image","video","audio"],"description":"The primary modality of the model. The `modality` filter of `GET /v1/models` matches this field. `capabilities.output_modalities` lists every output, so a video model that also outputs audio has `video` here and both there."},"tasks":{"type":"array","items":{"type":"string","enum":["chat","text-to-image","image-edit","text-to-video","image-to-video","reference-to-video","text-to-speech"]}},"status":{"type":"string","enum":["preview","ga","deprecated"]},"endpoint":{"type":"string","enum":["/v1/chat/completions","/v1/images/generations","/v1/images/edits","/v1/videos","/v1/audio/speech"],"description":"The generation endpoint that runs this model."},"released_at":{"type":"string","description":"Release date (YYYY-MM-DD). Present only when confirmed."},"updated_at":{"type":"string","description":"Last update date (YYYY-MM-DD) of the catalog entry."},"summary":{"type":"string"},"description":{"type":"string"},"capabilities":{"$ref":"#/components/schemas/ModelCapabilities"},"parameters":{"$ref":"#/components/schemas/ModelParameters"},"pricing":{"type":"array","items":{"$ref":"#/components/schemas/ModelPrice"}},"data_policy":{"type":"object","properties":{"output_retention_days":{"type":"integer","description":"Days generated outputs are kept in storage. 0 means they are not stored."},"stores_prompts":{"type":"boolean"}},"required":["output_retention_days","stores_prompts"]},"links":{"type":"object","properties":{"html":{"type":"string","description":"Model page for people."},"markdown":{"type":"string","description":"Markdown version of the model page."}},"required":["html","markdown"]}},"required":["id","object","name","vendor","vendor_name","modality","tasks","status","endpoint","updated_at","summary","description","capabilities","parameters","pricing","data_policy","links"]},"ModelCapabilities":{"type":"object","properties":{"input_modalities":{"type":"array","items":{"type":"string","enum":["text","image","video","audio"]}},"output_modalities":{"type":"array","items":{"type":"string","enum":["text","image","video","audio"]}},"context_length":{"type":"integer"},"max_output_tokens":{"type":"integer"},"resolutions":{"type":"array","items":{"type":"string"}},"aspect_ratios":{"type":"array","items":{"type":"string"}},"duration_seconds":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"}},"required":["min","max"]},"streaming":{"type":"boolean"},"async":{"type":"boolean"},"audio_output":{"type":"boolean"}},"required":["input_modalities","output_modalities","streaming","async"]},"ModelParameters":{"type":"object","properties":{"type":{"type":"string","enum":["object"]},"required":{"type":"array","items":{"type":"string"}},"properties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ModelParameter"}}},"required":["type","required","properties"],"description":"Input parameters in a JSON Schema style object."},"ModelParameter":{"type":"object","properties":{"type":{"type":"string","enum":["string","integer","number","boolean","array"]},"description":{"type":"string"},"format":{"type":"string"},"enum":{"type":"array","items":{"type":"string"}},"default":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"minimum":{"type":"number"},"maximum":{"type":"number"},"maxLength":{"type":"integer"},"maxItems":{"type":"integer"},"items":{"type":"object","properties":{"type":{"type":"string","enum":["string","object"]},"format":{"type":"string"}},"required":["type"]}},"required":["type","description"]},"ModelPrice":{"type":"object","properties":{"dimension":{"type":"string","enum":["input_token","cached_input_token","output_token","output_image","video_second","input_character"]},"unit":{"type":"string","enum":["per_1m_tokens","per_image","per_second","per_1k_characters"]},"amount_micro_usd":{"type":"integer","description":"Price per unit in micro USD (1 USD = 1,000,000 micro USD)."},"amount_usd":{"type":"string","description":"The same price as a decimal string in USD.","example":"0.045"},"conditions":{"type":"object","additionalProperties":{"type":"string"},"description":"Input values that select this price. An empty object marks the default price."}},"required":["dimension","unit","amount_micro_usd","amount_usd","conditions"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","example":"Model not found."},"type":{"type":"string","example":"not_found_error"},"code":{"type":"string","enum":["invalid_request","unauthorized","balance_insufficient","key_limit_exceeded","forbidden","account_suspended","not_found","model_not_found","method_not_allowed","idempotency_conflict","payload_too_large","content_policy_violation","rate_limited","concurrency_limited","internal_error","upstream_error","upstream_unavailable","webhooks_unavailable"],"example":"model_not_found"},"param":{"type":["string","null"],"description":"The request parameter that caused the error, if any.","example":"model"},"request_id":{"type":"string","example":"req_0123456789abcdef0123456789abcdef"},"doc_url":{"type":"string","example":"https://example.com/docs/errors/#model_not_found"},"details":{"type":"object","additionalProperties":{},"description":"Extra machine-readable context. For a fixed set of values, `allowed` lists the accepted values. For a numeric range, `minimum` and `maximum` give the limits."}},"required":["message","type","code","param","request_id","doc_url"]}},"required":["error"]},"Estimate":{"type":"object","properties":{"object":{"type":"string","enum":["estimate"]},"model":{"type":"string"},"currency":{"type":"string","enum":["USD"]},"total_micro_usd":{"type":"integer"},"total_usd":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/EstimateLine"}},"assumptions":{"type":"array","items":{"type":"string"}}},"required":["object","model","currency","total_micro_usd","total_usd","lines","assumptions"]},"EstimateLine":{"type":"object","properties":{"dimension":{"type":"string","enum":["input_token","cached_input_token","output_token","output_image","video_second","input_character"]},"unit":{"type":"string","enum":["per_1m_tokens","per_image","per_second","per_1k_characters"]},"quantity":{"type":"number"},"unit_price_micro_usd":{"type":"integer"},"unit_price_usd":{"type":"string"},"amount_micro_usd":{"type":"integer"},"amount_usd":{"type":"string"},"conditions":{"type":"object","additionalProperties":{"type":"string"}}},"required":["dimension","unit","quantity","unit_price_micro_usd","unit_price_usd","amount_micro_usd","amount_usd","conditions"]},"EstimateRequest":{"type":"object","properties":{"model":{"type":"string","minLength":1,"maxLength":128,"description":"Model ID in `vendor/model` form."},"input":{"type":"object","additionalProperties":{},"default":{},"description":"Generation input. Only the values that affect price are read. Text: `max_tokens`, and either `prompt_tokens` or `messages`. Images: `resolution` and `n`. Videos: `resolution` and `duration`. Omitted values use the defaults in the `parameters` of the model, and a value outside the range there returns `400` with the limits in `error.details`. `n` is the number of images: an integer from `minimum` to `maximum` of the model's `n` parameter, 1 by default. `prompt_tokens` is for estimates only and is not a parameter of the generation endpoints: the number of input tokens you expect, an integer from 0 to `capabilities.context_length` of the model. Without it, input tokens are approximated from `messages`, which can be lower than the real count, so the total is then not an upper bound."}},"required":["model"],"example":{"model":"sakuranbo/cherryimage-1.0-pro","input":{"resolution":"2k"}}},"ImageResponse":{"type":"object","properties":{"created":{"type":"integer","description":"Unix time in seconds."},"data":{"type":"array","items":{"$ref":"#/components/schemas/ImageData"}},"usage":{"type":"object","properties":{"output_images":{"type":"integer"}},"required":["output_images"]},"cost":{"anyOf":[{"$ref":"#/components/schemas/Cost"}],"description":"The amount charged for the delivered images."},"job_id":{"type":"string","description":"The job that ran the generation. `GET /v1/jobs/{id}` returns it."}},"required":["created","data","usage","cost","job_id"]},"ImageData":{"type":"object","properties":{"url":{"type":"string","description":"A signed URL for the image, when `response_format` is `url` (the default). It needs no API key and works until `expires_at`."},"b64_json":{"type":"string","description":"The base64-encoded image, when `response_format` is `b64_json`. Up to 8 MiB of images are inlined per response; the rest are returned as `url`."},"expires_at":{"type":"string","description":"When `url` stops working and the image is deleted (ISO 8601, UTC)."}}},"ImageGenerationRequest":{"type":"object","properties":{"model":{"type":"string","minLength":1,"maxLength":128,"description":"An image model ID in `vendor/model` form. `GET /v1/models?modality=image` lists them with their parameters.","example":"sakuranbo/cherryimage-1.0-pro"},"prompt":{"type":"string","description":"Describes the image to generate, or the edit to apply. The maximum length is in the `prompt` parameter of the model.","example":"A matte ceramic coffee mug on a walnut desk, soft morning light"},"n":{"type":"number","description":"Number of images. The maximum is in the `n` parameter of the model. The price is per delivered image.","example":1},"resolution":{"type":"string","description":"Output resolution; it sets the price per image. Default `2k`.","example":"2k"},"aspect_ratio":{"type":"string","description":"Aspect ratio of the output. Default `auto`.","example":"1:1"},"output_format":{"type":"string","description":"File format of the output (`jpeg` or `png`). Default `jpeg`.","example":"jpeg"},"response_format":{"type":"string","enum":["url","b64_json"],"default":"url","description":"`url` returns a signed URL for each image. `b64_json` returns the image data inline."}},"required":["model","prompt"],"additionalProperties":false,"example":{"model":"sakuranbo/cherryimage-1.0-pro","prompt":"A matte ceramic coffee mug on a walnut desk, soft morning light","resolution":"2k","aspect_ratio":"4:3"}},"ImageEditRequest":{"type":"object","properties":{"model":{"type":"string","minLength":1,"maxLength":128,"description":"An image model ID in `vendor/model` form. `GET /v1/models?modality=image` lists them with their parameters.","example":"sakuranbo/cherryimage-1.0-pro"},"prompt":{"type":"string","description":"Describes the image to generate, or the edit to apply. The maximum length is in the `prompt` parameter of the model.","example":"A matte ceramic coffee mug on a walnut desk, soft morning light"},"n":{"type":"number","description":"Number of images. The maximum is in the `n` parameter of the model. The price is per delivered image.","example":1},"resolution":{"type":"string","description":"Output resolution; it sets the price per image. Default `2k`.","example":"2k"},"aspect_ratio":{"type":"string","description":"Aspect ratio of the output. Default `auto`.","example":"1:1"},"output_format":{"type":"string","description":"File format of the output (`jpeg` or `png`). Default `jpeg`.","example":"jpeg"},"response_format":{"type":"string","enum":["url","b64_json"],"default":"url","description":"`url` returns a signed URL for each image. `b64_json` returns the image data inline."},"images":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":10,"description":"1 to 10 reference images, in the order the prompt refers to them (\"the first image\", \"the second image\"). Each is an https URL to a public image (PNG, JPEG, WebP, or GIF up to 10 MiB; redirects are not followed) or a `data:image/...;base64,` URI of up to 720 KiB. The whole request body is limited to 1000 KiB.","example":["https://example.com/reference.png"]}},"required":["model","prompt","images"],"additionalProperties":false,"example":{"model":"sakuranbo/cherryimage-1.0-pro","prompt":"Make the mug dark blue","images":["https://example.com/reference.png"]}},"Video":{"allOf":[{"$ref":"#/components/schemas/Job"},{"type":"object","properties":{"object":{"type":"string","enum":["video"]},"model":{"type":"string","example":"sakuranbo/cherry-1.0-pro"},"polling_url":{"type":"string","description":"The URL to `GET` for the current state of this video.","example":"https://api.example.com/v1/videos/job_0123456789abcdef0123456789abcdef"},"eta_seconds":{"type":["integer","null"],"description":"An estimate of the seconds left until the video completes, from the duration and the time since the request. `0` once the estimate has passed. `null` when the job has finished."}},"required":["polling_url","eta_seconds"]}]},"VideoCreateRequest":{"type":"object","properties":{"model":{"type":"string","minLength":1,"maxLength":128,"description":"A video model ID in `vendor/model` form. `GET /v1/models?modality=video` lists them with their parameters.","example":"sakuranbo/cherry-1.0-pro"},"prompt":{"type":"string","description":"Describes the scene, the motion, and the audio. The maximum length is in the `prompt` parameter of the model.","example":"Aerial shot gliding over a misty mountain lake at sunrise, gentle wind and birdsong"},"first_frame":{"type":"string","description":"An image to use as the first frame (image-to-video). An https URL to a public image (PNG, JPEG, WebP, or GIF up to 10 MiB; redirects are not followed) or a `data:image/...;base64,` URI of up to 720 KiB.","example":"https://example.com/first.png"},"last_frame":{"type":"string","description":"An image to use as the last frame. Needs `first_frame`. Accepts the same forms as `first_frame`."},"reference_images":{"type":"array","items":{"type":"string"},"description":"Reference images (reference-to-video), in the order the prompt refers to them (\"Image 1\", \"Image 2\"). The maximum number is in the `reference_images` parameter of the model. Each accepts the same forms as `first_frame`. Cannot be combined with `first_frame` or `last_frame`."},"duration":{"type":"number","description":"Length of the video in seconds; it sets the price together with `resolution`. The range and the default are in the `duration` parameter of the model.","example":5},"resolution":{"type":"string","description":"Output resolution; it sets the price per second. Default `1080p`.","example":"1080p"},"aspect_ratio":{"type":"string","description":"Aspect ratio of the output. Default `adaptive`.","example":"16:9"},"audio":{"type":"boolean","description":"Whether the video has an audio track. The price is the same either way. Default `true`."}},"required":["model","prompt"],"additionalProperties":false,"example":{"model":"sakuranbo/cherry-1.0-pro","prompt":"Aerial shot gliding over a misty mountain lake at sunrise, gentle wind and birdsong","duration":5,"resolution":"1080p","aspect_ratio":"16:9"}},"VideoList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Video"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page. `null` on the last page."}},"required":["object","data","has_more","next_cursor"]},"ApiKey":{"type":"object","properties":{"object":{"type":"string","enum":["api_key"]},"id":{"type":"string","example":"Ab3dEf7hIj0L"},"name":{"type":"string"},"last4":{"type":"string","description":"The last 4 characters of the key."},"environment":{"type":"string","enum":["live","test"]},"created_at":{"type":"string","example":"2026-10-22T09:00:00.000Z"},"expires_at":{"type":["string","null"],"description":"The key stops working at this time (ISO 8601, UTC). `null` means it does not expire."},"limit":{"type":["object","null"],"properties":{"amount_micro_usd":{"type":"integer"},"amount_usd":{"type":"string"},"period":{"type":"string","enum":["none","day","month"],"description":"The period a spending limit is counted over, in UTC calendar days or months. `none` counts the total over the whole life of the key."}},"required":["amount_micro_usd","amount_usd","period"],"description":"The spending limit of the key. `null` means there is no limit."},"usage":{"type":"object","properties":{"period":{"type":"string","enum":["none","day","month"],"description":"The period a spending limit is counted over, in UTC calendar days or months. `none` counts the total over the whole life of the key."},"period_start":{"type":["string","null"],"description":"Start of the current period (ISO 8601, UTC). `null` when the period is `none`."},"resets_at":{"type":["string","null"],"description":"When the usage counter starts over (ISO 8601, UTC). `null` when the period is `none`."},"used_micro_usd":{"type":"integer","description":"Reserved by running requests plus settled spending in the current period."},"used_usd":{"type":"string"},"remaining_micro_usd":{"type":["integer","null"],"description":"What the limit leaves for the current period. `null` when there is no limit."},"remaining_usd":{"type":["string","null"]}},"required":["period","period_start","resets_at","used_micro_usd","used_usd","remaining_micro_usd","remaining_usd"]}},"required":["object","id","name","last4","environment","created_at","expires_at","limit","usage"]},"ChatCompletion":{"type":"object","properties":{"id":{"type":"string","example":"gen_0123456789abcdef0123456789abcdef"},"object":{"type":"string","enum":["chat.completion"]},"created":{"type":"integer"},"model":{"type":"string","example":"sakuranbo/cherrytext-1.0-flash"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"type":"object","properties":{"role":{"type":"string","enum":["assistant"]},"content":{"type":["string","null"]},"reasoning_content":{"type":"string"},"tool_calls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"]}},"required":["id","type","function"]}}},"required":["role","content"]},"finish_reason":{"type":["string","null"]}},"required":["index","message","finish_reason"]}},"usage":{"$ref":"#/components/schemas/ChatUsage"}},"required":["id","object","created","model","choices","usage"]},"ChatUsage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"},"prompt_tokens_details":{"type":"object","properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"]},"cost":{"$ref":"#/components/schemas/UsageCost"}},"required":["prompt_tokens","completion_tokens","total_tokens","prompt_tokens_details","cost"]},"UsageCost":{"type":"object","properties":{"amount_micro_usd":{"type":"integer","example":1250},"amount_usd":{"type":"string","example":"0.00125"}},"required":["amount_micro_usd","amount_usd"],"description":"The amount charged for this request."},"ChatCompletionRequest":{"type":"object","properties":{"model":{"type":"string","example":"sakuranbo/cherrytext-1.0-flash"},"messages":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["system","developer"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},"minItems":1}]},"name":{"type":"string"}},"required":["role","content"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["user"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},"minItems":1}]},"name":{"type":"string"}},"required":["role","content"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},"minItems":1},{"type":"null"}]},"name":{"type":"string"},"tool_calls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":false}},"required":["id","type","function"],"additionalProperties":false}}},"required":["role"],"additionalProperties":{}},{"type":"object","properties":{"role":{"type":"string","enum":["tool"]},"tool_call_id":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1}},"required":["type","text"],"additionalProperties":false},"minItems":1}]}},"required":["role","tool_call_id","content"],"additionalProperties":false}]},"minItems":1},"max_tokens":{"type":"integer"},"max_completion_tokens":{"type":"integer"},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"stop":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":4}],"description":"A stop sequence, or an array of at most 4 stop sequences. An empty array is the same as leaving `stop` out. More than 4 are rejected with `invalid_request`."},"seed":{"type":"integer","minimum":1,"description":"A positive integer (1 or more) that makes sampling repeatable on a best-effort basis. 0 and negative values are rejected with `invalid_request`."},"user":{"type":"string","maxLength":512},"tools":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,64}$"},"description":{"type":"string"},"parameters":{"type":"object","additionalProperties":{}},"strict":{"type":["boolean","null"]}},"required":["name"],"additionalProperties":false}},"required":["type","function"],"additionalProperties":false},"maxItems":128},"tool_choice":{"anyOf":[{"type":"string","enum":["none","auto","required"]},{"type":"object","properties":{"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"],"additionalProperties":false}},"required":["type","function"],"additionalProperties":false}]},"response_format":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["json_object"]}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"schema":{"type":"object","additionalProperties":{}},"strict":{"type":["boolean","null"]}},"required":["name"],"additionalProperties":false}},"required":["type","json_schema"],"additionalProperties":false}]},"n":{"type":"number","enum":[1]},"stream":{"type":"boolean"},"stream_options":{"type":["object","null"],"properties":{"include_usage":{"type":"boolean"}},"additionalProperties":false}},"required":["model","messages"],"additionalProperties":false},"AnthropicMessage":{"type":"object","properties":{"id":{"type":"string","example":"gen_0123456789abcdef0123456789abcdef"},"type":{"type":"string","enum":["message"]},"role":{"type":"string","enum":["assistant"]},"model":{"type":"string","example":"sakuranbo/cherrytext-1.0-flash"},"content":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string"}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","enum":["tool_use"]},"id":{"type":"string"},"name":{"type":"string"},"input":{"type":"object","additionalProperties":{}}},"required":["type","id","name","input"]}]}},"stop_reason":{"type":["string","null"]},"stop_sequence":{"type":["string","null"]},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"cache_creation_input_tokens":{"type":"integer"},"cost":{"$ref":"#/components/schemas/UsageCost"}},"required":["input_tokens","output_tokens","cache_read_input_tokens","cache_creation_input_tokens","cost"]}},"required":["id","type","role","model","content","stop_reason","stop_sequence","usage"]},"AnthropicError":{"type":"object","properties":{"type":{"type":"string","enum":["error"]},"error":{"type":"object","properties":{"type":{"type":"string","example":"invalid_request_error"},"message":{"type":"string"},"code":{"type":"string","example":"invalid_request"},"param":{"type":["string","null"]},"doc_url":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["type","message","code","param","doc_url"]},"request_id":{"type":"string"}},"required":["type","error","request_id"]},"MessagesRequest":{"type":"object","properties":{"model":{"type":"string","example":"sakuranbo/cherrytext-1.0-flash"},"messages":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["user"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1},"cache_control":{}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["tool_result"]},"tool_use_id":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1},"cache_control":{}},"required":["type","text"],"additionalProperties":false}}]},"is_error":{"type":"boolean"},"cache_control":{}},"required":["type","tool_use_id"],"additionalProperties":false}]},"minItems":1}]}},"required":["role","content"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1},"cache_control":{}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["tool_use"]},"id":{"type":"string"},"name":{"type":"string"},"input":{"type":"object","additionalProperties":{}},"cache_control":{}},"required":["type","id","name","input"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["thinking","redacted_thinking"]}},"required":["type"],"additionalProperties":{}}]},"minItems":1}]}},"required":["role","content"],"additionalProperties":false}]},"minItems":1},"system":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string","minLength":1},"cache_control":{}},"required":["type","text"],"additionalProperties":false}}]},"max_tokens":{"type":"integer"},"temperature":{"type":"number","minimum":0,"maximum":1},"top_p":{"type":"number","minimum":0,"maximum":1},"stop_sequences":{"type":"array","items":{"type":"string"},"maxItems":4,"description":"At most 4 stop sequences. An empty array is the same as leaving `stop_sequences` out. More than 4 are rejected with `invalid_request_error`."},"stream":{"type":"boolean"},"tools":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["custom"]},"name":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,64}$"},"description":{"type":"string"},"input_schema":{"type":"object","additionalProperties":{}},"cache_control":{}},"required":["name","input_schema"],"additionalProperties":false},"maxItems":128},"tool_choice":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["auto"]},"disable_parallel_tool_use":{"type":"boolean"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["any"]},"disable_parallel_tool_use":{"type":"boolean"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["none"]}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["tool"]},"name":{"type":"string"},"disable_parallel_tool_use":{"type":"boolean"}},"required":["type","name"],"additionalProperties":false}]}},"required":["model","messages","max_tokens"],"additionalProperties":false},"JobList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Job"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page. `null` on the last page."}},"required":["object","data","has_more","next_cursor"]},"WebhookEndpointWithSecret":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret":{"type":"string","description":"The signing secret (`whsec_` and a base64 value). It is returned only in this response; store it now. Use it with a Standard Webhooks library to verify deliveries.","example":"whsec_ZXhhbXBsZS13ZWJob29rLXNlY3JldC0wMTIzNDU2Nzg="}},"required":["secret"]}]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","example":"we_0123456789abcdef0123456789abcdef"},"object":{"type":"string","enum":["webhook_endpoint"]},"url":{"type":"string"},"description":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["job.succeeded","job.failed","job.cancelled","deposit.credited","balance.low"]}},"enabled":{"type":"boolean","description":"`false` while the endpoint is stopped. Nothing is sent to a stopped endpoint."},"disabled_reason":{"type":["string","null"],"enum":["gone","manual",null],"description":"Why the endpoint is stopped: `gone` when your server answered `410 Gone`, `manual` when it was stopped through the API or the dashboard. `null` while enabled."},"previous_secret_expires_at":{"type":["string","null"],"description":"After `rotate-secret`, deliveries carry a signature for the previous secret too until this time (ISO 8601, UTC). `null` when no rotation is in progress."},"created_at":{"type":"string","example":"2026-10-22T09:00:00.000Z"}},"required":["id","object","url","description","events","enabled","disabled_reason","previous_secret_expires_at","created_at"]},"CreateWebhookEndpoint":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"Where deliveries are sent. Must be an `https` URL on the default port with a public host name; IP addresses, `localhost`, internal names, and URLs with credentials are rejected.","example":"https://example.com/webhooks/cherry"},"events":{"type":"array","items":{"type":"string","enum":["job.succeeded","job.failed","job.cancelled","deposit.credited","balance.low"]},"minItems":1,"description":"The event types this endpoint receives. Omit it to receive every type."},"description":{"type":"string","maxLength":256,"description":"A note for people, up to 256 characters."}},"required":["url"],"additionalProperties":false},"WebhookEndpointList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"required":["object","data"]},"UpdateWebhookEndpoint":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"Where deliveries are sent. Must be an `https` URL on the default port with a public host name; IP addresses, `localhost`, internal names, and URLs with credentials are rejected.","example":"https://example.com/webhooks/cherry"},"events":{"type":"array","items":{"type":"string","enum":["job.succeeded","job.failed","job.cancelled","deposit.credited","balance.low"]},"minItems":1,"description":"The event types this endpoint receives."},"description":{"type":"string","maxLength":256,"description":"A note for people, up to 256 characters."},"enabled":{"type":"boolean","description":"`false` stops deliveries and `true` resumes them. Use `true` to turn on an endpoint that was stopped after a `410 Gone`."}},"additionalProperties":false},"WebhookEndpointDeleted":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_endpoint"]},"deleted":{"type":"boolean","enum":[true]}},"required":["id","object","deleted"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","example":"dlv_0123456789abcdef0123456789abcdef"},"object":{"type":"string","enum":["webhook_delivery"]},"endpoint_id":{"type":"string"},"event_id":{"type":"string","description":"The `webhook-id` of the delivery. It stays the same on every retry, so use it to skip events you already handled.","example":"evt_0123456789abcdef0123456789abcdef"},"event_type":{"type":"string","enum":["job.succeeded","job.failed","job.cancelled","deposit.credited","balance.low","webhook.test"]},"status":{"type":"string","enum":["pending","succeeded","failed"],"description":"`pending` while attempts are running or waiting for the next one. `succeeded` after a `2xx` answer. `failed` after the last retry failed, or after a `410 Gone` or a stop."},"attempts":{"type":"integer"},"last_attempt_at":{"type":["string","null"]},"last_http_status":{"type":["integer","null"]},"last_duration_ms":{"type":["integer","null"]},"last_error":{"type":["string","null"],"enum":["timeout","connection_failed","http_status","url_not_allowed","endpoint_disabled","secret_unavailable",null],"description":"Why the last attempt failed. `null` after a success."},"last_response":{"type":["string","null"],"description":"The first 512 bytes of your server's answer to the last attempt."},"next_attempt_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","object","endpoint_id","event_id","event_type","status","attempts","last_attempt_at","last_http_status","last_duration_ms","last_error","last_response","next_attempt_at","created_at"]},"WebhookDeliveryList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page. `null` on the last page."}},"required":["object","data","has_more","next_cursor"]},"Report":{"type":"object","properties":{"id":{"type":"string","example":"rpt_0123456789abcdef0123456789abcdef"},"object":{"type":"string","enum":["report"]},"created_at":{"type":"string","example":"2026-10-23T00:00:00.000Z"}},"required":["id","object","created_at"]},"ReportRequest":{"type":"object","properties":{"job_id":{"type":"string","pattern":"^job_[0-9a-f]{32}$","description":"The ID of the job that produced the content.","example":"job_0123456789abcdef0123456789abcdef"},"url":{"type":"string","maxLength":2048,"pattern":"^https?:\\/\\/\\S+$","description":"The URL of the generated file (`/v1/files/...`), or the page where the content appears. Send this or `job_id`."},"category":{"type":"string","enum":["minor","non_consensual_real_person","other"],"description":"`minor` is content that involves a minor. `non_consensual_real_person` is content that shows a real person without consent. `other` is any other violation."},"description":{"type":"string","minLength":1,"maxLength":2000,"description":"What is wrong with the content."},"contact":{"type":"string","maxLength":200,"description":"An email address or other contact, if you want a reply."}},"required":["category","description"],"additionalProperties":false}},"parameters":{"IfNoneMatch":{"name":"If-None-Match","in":"header","required":false,"description":"The `ETag` of a response you already have. While the body is unchanged, the answer is `304 Not Modified` with no body.","schema":{"type":"string"},"example":"W/\"0123456789abcdef0123456789abcdef\""}},"headers":{"X-Request-Id":{"description":"The ID of the request, also in `error.request_id` of an error. Send your own `X-Request-Id` (8 to 64 characters of A-Z, a-z, 0-9, `_` or `-`) to correlate requests; otherwise one is generated. Quote it when you contact support.","schema":{"type":"string"},"example":"req_0123456789abcdef0123456789abcdef"},"ETag":{"description":"A weak validator of the body. Send it back as `If-None-Match` to get `304 Not Modified` while the body is unchanged.","schema":{"type":"string"},"example":"W/\"0123456789abcdef0123456789abcdef\""},"Cache-Control":{"description":"How the response may be cached. Responses are `no-store`, except the public catalog (`GET /v1/models` and `GET /v1/models/{vendor}/{model}`) and the status (`GET /v1/status`), which are `public, max-age=60` (`private, max-age=60` when the request has an `Authorization` header), and the signed file download (`GET /v1/files/{token}`), which is `private, max-age=3600`.","schema":{"type":"string"},"example":"no-store"}}},"paths":{"/healthz":{"get":{"operationId":"getHealth","tags":["Meta"],"summary":"Health check","description":"Returns 200 while the API is running. The response is never cached.","responses":{"200":{"description":"The API is running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/status":{"get":{"operationId":"getStatus","tags":["Meta"],"summary":"Get the measured availability and generation time","description":"Returns the success rate and the generation time of every model, and the success rate across all models, for the last 24 hours (`24h`), 7 days (`7d`), and 30 days (`30d`). No API key is required. The numbers are measured on this service after launch. There are no estimates or targets. A result fails when it ends with a 5xx status (an upstream error, or an upstream that does not answer in time). A 4xx result, such as an invalid request or a content policy rejection, counts as a success. An image or video request that is rejected before its job is created is not counted. `success_rate` is 1 minus the share of failures, from 0 to 1. The generation time comes from successful results only. For a text model it is the time from the chat request to the start of the response (for a stream, until the response starts; streaming the content is not included). For an image or video model it is the time from the creation of the job to its completion. `p50` is the median and `p95` the 95th percentile, in milliseconds. A success rate measured from fewer than `min_samples` (20) results, or a generation time measured from fewer than `min_samples` successful results, is `null`, which means it is still being measured. The measurements are read at most every 5 minutes (`generated_at`). If they cannot be read, `state` is `unavailable` and the status is still `200`.","responses":{"200":{"description":"The measured availability and generation time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Status"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"304":{"description":"The body is unchanged since the response with this `If-None-Match` ETag.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}},"parameters":[{"$ref":"#/components/parameters/IfNoneMatch"}]}},"/v1/models":{"get":{"operationId":"listModels","tags":["Models"],"summary":"List models","description":"Returns the model catalog with prices. No API key is required. Filters combine with AND.","parameters":[{"schema":{"type":"string","enum":["text","image","video","audio"],"description":"Return only models whose primary modality (the `modality` field) matches. A video model that also outputs audio is returned for `video`, not for `audio`.","example":"image"},"required":false,"description":"Return only models whose primary modality (the `modality` field) matches. A video model that also outputs audio is returned for `video`, not for `audio`.","name":"modality","in":"query"},{"schema":{"type":"string","enum":["chat","text-to-image","image-edit","text-to-video","image-to-video","reference-to-video","text-to-speech"],"description":"Return only models that support the task.","example":"text-to-image"},"required":false,"description":"Return only models that support the task.","name":"task","in":"query"},{"schema":{"type":"string","enum":["en","ja","zh","ko"],"default":"en","description":"Language of `summary`, `description`, and parameter descriptions.","example":"en"},"required":false,"description":"Language of `summary`, `description`, and parameter descriptions.","name":"locale","in":"query"},{"$ref":"#/components/parameters/IfNoneMatch"}],"responses":{"200":{"description":"The models that match the filters. An empty `data` array means no match.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"304":{"description":"The body is unchanged since the response with this `If-None-Match` ETag.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"400":{"description":"A query parameter is invalid. `error.details.allowed` lists the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/models/{vendor}/{model}":{"get":{"operationId":"getModel","tags":["Models"],"summary":"Get a model","description":"Returns one model by its `vendor/model` ID. No API key is required.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"sakuranbo"},"required":true,"name":"vendor","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"cherryimage-1.0-pro"},"required":true,"name":"model","in":"path"},{"schema":{"type":"string","enum":["en","ja","zh","ko"],"default":"en","description":"Language of `summary`, `description`, and parameter descriptions.","example":"en"},"required":false,"description":"Language of `summary`, `description`, and parameter descriptions.","name":"locale","in":"query"},{"$ref":"#/components/parameters/IfNoneMatch"}],"responses":{"200":{"description":"The model.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Model"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"304":{"description":"The body is unchanged since the response with this `If-None-Match` ETag.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"ETag":{"$ref":"#/components/headers/ETag"}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/estimate":{"post":{"operationId":"createEstimate","tags":["Estimate"],"summary":"Estimate the cost of a generation","description":"Computes the price of a generation from the model and input. This is the same calculation the Playground shows, and the final charge is computed on the server. No API key is required. The request body is limited to 256 KiB.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateRequest"}}}},"responses":{"200":{"description":"The estimate with one line per price dimension.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Estimate"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The body is not valid JSON, a field has the wrong type, or an input value is out of range. `error.details.allowed` lists the accepted values when they are a fixed set, and `error.details.minimum` and `error.details.maximum` give the limits of a numeric range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than the limit (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/images/generations":{"post":{"operationId":"createImageGeneration","tags":["Images"],"summary":"Generate images from a prompt","description":"Generates images from a text prompt. By default the request waits for the result and answers `200` in an OpenAI-style body (`created`, `data`) with `usage`, `cost`, and `job_id` added. If the generation takes longer than the maximum wait (60 seconds), it answers `202` with the job instead, and the generation continues; poll `GET /v1/jobs/{id}`. Send `Prefer: respond-async` to get the `202` at once. The estimated price is reserved first and the delivered images are charged; a failed, rejected, or cancelled generation is not charged. The request body is limited to 64 KiB.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours."},"required":false,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours.","name":"idempotency-key","in":"header"},{"schema":{"type":"string","description":"The `Prefer` header. `respond-async` returns `202` with the job at once, without waiting."},"required":false,"description":"The `Prefer` header. `respond-async` returns `202` with the job at once, without waiting.","name":"prefer","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationRequest"}}}},"responses":{"200":{"description":"The images are ready. `data` has one entry per delivered image. The amount charged is in `cost` and in the `X-Usage-Cost-Usd` header.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"X-Usage-Cost-Usd":{"schema":{"type":"string","description":"The amount charged, in USD."},"required":true,"description":"The amount charged, in USD."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageResponse"}}}},"202":{"description":"The job is still running (or `Prefer: respond-async` was sent). The body is the job; follow it with `GET /v1/jobs/{id}`. Nothing is charged until it completes.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"Location":{"schema":{"type":"string","description":"The URL of the job."},"required":true,"description":"The URL of the job."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"A field is missing, unknown, or out of range (`invalid_request`), or a reference image cannot be used. `error.param` names the field; `error.details.allowed` lists the accepted values of a fixed set, and `error.details.minimum` and `error.details.maximum` give the limits of a number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"402":{"description":"The balance (`balance_insufficient`) or the spending limit of the API key (`key_limit_exceeded`) does not cover the request. `error.details.limit_source` is `balance` or `key`. Nothing is charged, and no job is created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The account is suspended (`account_suspended`). Image, video, and chat requests are refused; the balance, API keys, and jobs stay available. Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"409":{"description":"The `Idempotency-Key` was already used for a different request (`idempotency_conflict`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than the limit (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"422":{"description":"The upstream rejected the prompt, a reference image, or the generated output because of its content policy (`content_policy_violation`). Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"429":{"description":"The upstream is busy (`rate_limited`, `concurrency_limited`). Nothing is charged. Retry after the time in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"502":{"description":"The upstream failed (`upstream_error`), or the job was cancelled while it was awaited. `error.details.job_id` is the job. Nothing is charged, except in the rare case where it could not be confirmed that the request reached the upstream: the reserved amount then stays reserved until it is confirmed whether the request is charged. If it stays reserved, contact support with the job ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"The model is temporarily unavailable (`upstream_unavailable`). Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/images/edits":{"post":{"operationId":"createImageEdit","tags":["Images"],"summary":"Edit images with a prompt","description":"Edits one to ten reference images as the prompt says. It behaves like `POST /v1/images/generations`: it waits for the result by default and answers `202` with the job after the maximum wait. The reference images are sent as JSON (`images`); multipart upload is not supported. Reference image URLs are checked before the request is accepted: they must be public https URLs that return an image. The estimated price is reserved first and the delivered images are charged. The request body is limited to 1000 KiB.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours."},"required":false,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours.","name":"idempotency-key","in":"header"},{"schema":{"type":"string","description":"The `Prefer` header. `respond-async` returns `202` with the job at once, without waiting."},"required":false,"description":"The `Prefer` header. `respond-async` returns `202` with the job at once, without waiting.","name":"prefer","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageEditRequest"}}}},"responses":{"200":{"description":"The images are ready. `data` has one entry per delivered image. The amount charged is in `cost` and in the `X-Usage-Cost-Usd` header.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"X-Usage-Cost-Usd":{"schema":{"type":"string","description":"The amount charged, in USD."},"required":true,"description":"The amount charged, in USD."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageResponse"}}}},"202":{"description":"The job is still running (or `Prefer: respond-async` was sent). The body is the job; follow it with `GET /v1/jobs/{id}`. Nothing is charged until it completes.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"Location":{"schema":{"type":"string","description":"The URL of the job."},"required":true,"description":"The URL of the job."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"A field is missing, unknown, or out of range (`invalid_request`), or a reference image cannot be used. `error.param` names the field; `error.details.allowed` lists the accepted values of a fixed set, and `error.details.minimum` and `error.details.maximum` give the limits of a number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"402":{"description":"The balance (`balance_insufficient`) or the spending limit of the API key (`key_limit_exceeded`) does not cover the request. `error.details.limit_source` is `balance` or `key`. Nothing is charged, and no job is created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The account is suspended (`account_suspended`). Image, video, and chat requests are refused; the balance, API keys, and jobs stay available. Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"409":{"description":"The `Idempotency-Key` was already used for a different request (`idempotency_conflict`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than the limit (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"422":{"description":"The upstream rejected the prompt, a reference image, or the generated output because of its content policy (`content_policy_violation`). Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"429":{"description":"The upstream is busy (`rate_limited`, `concurrency_limited`). Nothing is charged. Retry after the time in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"502":{"description":"The upstream failed (`upstream_error`), or the job was cancelled while it was awaited. `error.details.job_id` is the job. Nothing is charged, except in the rare case where it could not be confirmed that the request reached the upstream: the reserved amount then stays reserved until it is confirmed whether the request is charged. If it stays reserved, contact support with the job ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"The model is temporarily unavailable (`upstream_unavailable`). Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/videos":{"post":{"operationId":"createVideo","tags":["Videos"],"summary":"Generate a video","description":"Starts a video generation and answers `202` with the video at once; it never waits for the result. Poll `GET /v1/videos/{id}` (the `polling_url`) until `status` is `completed`, `failed`, `cancelled`, or `expired`. A video is given up after 30 minutes. Then download the file with `GET /v1/videos/{id}/content` or from `outputs`. Send only `prompt` for text-to-video, add `first_frame` (and `last_frame`) for image-to-video, or `reference_images` for reference-to-video. Image URLs are checked before the request is accepted: they must be public https URLs that return an image. The estimated price (the duration at the price per second of the resolution) is reserved first. When the video completes, it is charged for the seconds the upstream reports, or for the requested `duration` if it reports none, and never more than the reserved amount. A failed, rejected, or cancelled video is not charged. The request body is limited to 1000 KiB.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours."},"required":false,"description":"The `Idempotency-Key` header. Makes a retry safe: the same key with the same request returns the same job and charges once. The same key with a different request returns `409`. A key is kept for 24 hours.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoCreateRequest"}}}},"responses":{"202":{"description":"The video was accepted. Nothing is charged until it completes. `eta_seconds` estimates the wait.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"Location":{"schema":{"type":"string","description":"The URL of the video (`polling_url`)."},"required":true,"description":"The URL of the video (`polling_url`)."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Video"}}}},"400":{"description":"A field is missing, unknown, or out of range (`invalid_request`), the frames and reference images are combined, `last_frame` has no `first_frame`, or an image cannot be used. `error.param` names the field; `error.details.allowed` lists the accepted values of a fixed set, and `error.details.minimum` and `error.details.maximum` give the limits of a number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"402":{"description":"The balance (`balance_insufficient`) or the spending limit of the API key (`key_limit_exceeded`) does not cover the request. `error.details.limit_source` is `balance` or `key`. Nothing is charged, and no video is created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The account is suspended (`account_suspended`). Image, video, and chat requests are refused; the balance, API keys, and jobs stay available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"409":{"description":"The `Idempotency-Key` was already used for a different request (`idempotency_conflict`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than the limit (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"The model is temporarily unavailable (`upstream_unavailable`). Nothing is charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}},"get":{"operationId":"listVideos","tags":["Videos"],"summary":"List videos","description":"Returns the videos of your account, newest first. Pass `next_cursor` as `cursor` to read the next page.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page (1 to 100)."},"required":false,"description":"Items per page (1 to 100).","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"The `next_cursor` of the previous page."},"required":false,"description":"The `next_cursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"string","enum":["queued","in_progress","completed","failed","cancelled","expired"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"One page of videos. An empty `data` array means no video matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoList"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"A query parameter is invalid. `error.details.allowed` lists the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/videos/{id}":{"get":{"operationId":"getVideo","tags":["Videos"],"summary":"Get a video","description":"Returns a video of your account. Poll it every few seconds until `status` is `completed`, `failed`, `cancelled`, or `expired`. `progress` and `eta_seconds` are estimates while it runs. A failed video answers with `200`; its `error` has the same shape as an error response. It is the same job that `GET /v1/jobs/{id}` returns, with `polling_url` and `eta_seconds` added.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"job_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The video.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Video"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no video with this ID (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/videos/{id}/content":{"get":{"operationId":"getVideoContent","tags":["Videos"],"summary":"Download the video file","description":"Redirects (`302`) to the signed URL of the video file of a completed video. The signed URL needs no API key and works until the video's `expires_at`. Follow the redirect with the HTTP client to download the file.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"job_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"302":{"description":"The video is ready. `Location` is the signed URL of the file.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"},"Location":{"schema":{"type":"string","description":"The signed URL of the video file."},"required":true,"description":"The signed URL of the video file."}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no video with this ID, or the video has no file to download (`not_found`): it is still running, it did not complete, or its file has expired. `error.details.status` is the status of a video that exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/videos/{id}/cancel":{"post":{"operationId":"cancelVideo","tags":["Videos"],"summary":"Cancel a video","description":"Cancels a video that is `queued` or `in_progress`. The reserved amount is released and nothing is charged. Cancelling a cancelled video succeeds again. A video that already finished cannot be cancelled.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"job_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The cancelled video.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Video"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The video already finished (`invalid_request`); `error.details.status` is its status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no video with this ID (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/key":{"get":{"operationId":"getKey","tags":["Account"],"summary":"Get the API key in use","description":"Returns the name, the last 4 characters, the expiry, the spending limit, and the usage of the API key that signed the request. Usage counts what running requests have reserved plus what has settled in the current period.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"The API key and its usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/balance":{"get":{"operationId":"getBalance","tags":["Account"],"summary":"Get the prepaid balance","description":"Returns what the account can use for new requests and what running requests have reserved. Amounts are in USD, as integer micro USD and as decimal strings.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"The balance of the account that owns the API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Balance"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/chat/completions":{"post":{"operationId":"createChatCompletion","tags":["Chat"],"summary":"Create a chat completion (OpenAI compatible)","description":"Works with the OpenAI SDKs: set the base URL to this API's `/v1` and use an API key from the dashboard. The balance is held when the request is accepted, using the input size and `max_tokens`, and charged by the tokens the model reports when the response ends. The charge is in `usage.cost` and, for a non-streaming response, in the `X-Usage-Cost-Usd` header. Supported parameters are `messages` (text only; a text part must not be empty, a `content` array must have at least one part, an `assistant` message needs a non-empty `content` or at least one `tool_calls` entry, and the text parts of a `tool` message are joined with line breaks), `max_tokens` or `max_completion_tokens`, `temperature`, `top_p`, `stop`, `seed`, `user`, `tools`, `tool_choice`, `response_format`, `stream`, and `stream_options.include_usage`. Other parameters are rejected with `invalid_request` and `param`. With `stream`, the response is a `text/event-stream` of `chat.completion.chunk` events that ends with `data: [DONE]`. An error after the stream has started is sent as an `error` event.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}}},"responses":{"200":{"description":"The completion, or a stream of chunks when `stream` is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"}},"text/event-stream":{"schema":{"type":"string"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The body is not valid JSON, a parameter is not supported, or a value is out of range (`invalid_request`). `error.param` names the parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"402":{"description":"The balance is not enough (`balance_insufficient`), or the request would exceed the spending limit of the API key (`key_limit_exceeded`). `error.details.limit_source` is `balance` or `key`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The account is suspended (`account_suspended`). The balance, API keys, and jobs stay available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No text model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than 4 MiB (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"429":{"description":"The model provider is rate limiting requests (`rate_limited`). See `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"502":{"description":"The model provider failed or did not respond in time (`upstream_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"The model is temporarily unavailable (`upstream_unavailable`). See `Retry-After` when present.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/messages":{"post":{"operationId":"createMessage","tags":["Chat"],"summary":"Create a message (Anthropic compatible)","description":"Works with the Anthropic SDKs: set the base URL to this API's origin and use an API key from the dashboard, sent as `x-api-key` or as `Authorization: Bearer`. Errors use the Anthropic shape (`{ type: \"error\", error: { type, message } }`), with the same `code`, `param`, and `details` as the other endpoints inside `error`. The model is a catalog model ID, for example `sakuranbo/cherrytext-1.0-flash`, and runs on the same chat model as `/v1/chat/completions`, with the same balance hold and charge. The charge is in `usage.cost` and, for a non-streaming response, in the `X-Usage-Cost-Usd` header. Supported parameters are `messages` (text, `tool_use`, and `tool_result` blocks; a text block must not be empty, a message's `content` array must have at least one block, and an `assistant` message needs a non-empty string `content` or at least one `text` or `tool_use` block), `system`, `max_tokens` (required), `temperature`, `top_p`, `stop_sequences`, `stream`, `tools`, and `tool_choice`. Other parameters are rejected with `invalid_request_error` and `param`. With `stream`, the response is a `text/event-stream` of Anthropic events (`message_start` through `message_stop`). An error after the stream has started is sent as an `error` event.","security":[{"BearerAuth":[]},{"ApiKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagesRequest"}}}},"responses":{"200":{"description":"The message, or a stream of events when `stream` is true.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicMessage"}},"text/event-stream":{"schema":{"type":"string"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The body is not valid JSON, a parameter is not supported, or a value is out of range (`invalid_request`). `error.param` names the parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"402":{"description":"The balance is not enough (`balance_insufficient`), or the request would exceed the spending limit of the API key (`key_limit_exceeded`). `error.details.limit_source` is `balance` or `key`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The account is suspended (`account_suspended`). The balance, API keys, and jobs stay available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"No text model has this ID (`model_not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than 4 MiB (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"429":{"description":"The model provider is rate limiting requests (`rate_limited`). See `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"502":{"description":"The model provider failed or did not respond in time (`upstream_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"The model is temporarily unavailable (`upstream_unavailable`). See `Retry-After` when present.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the Anthropic shape. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500` with `error.type` `api_error` (`internal_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnthropicError"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/files/{token}":{"get":{"operationId":"getFile","tags":["Jobs"],"summary":"Download a generated file","description":"Returns a generated image or video. The `url` of a job output points here, and the token in the URL is its authorization, so no API key is needed. Anyone who has the URL can download the file until `expires_at`; treat the URL like a secret. Range requests are supported. The response is not cached by shared caches (`Cache-Control: private`).","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":1024},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"The file.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/gif":{"schema":{"type":"string","format":"binary"}},"video/mp4":{"schema":{"type":"string","format":"binary"}},"video/webm":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"206":{"description":"The requested byte range of the file.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/gif":{"schema":{"type":"string","format":"binary"}},"video/mp4":{"schema":{"type":"string","format":"binary"}},"video/webm":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"403":{"description":"The URL is not valid, was altered, or has expired (`forbidden`). A URL works until the `expires_at` of its output. Getting the job again returns the same URL, not a new one, and after `expires_at` the `outputs` of the job are empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The file is no longer stored (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/jobs":{"get":{"operationId":"listJobs","tags":["Jobs"],"summary":"List jobs","description":"Returns the jobs of your account, newest first. Filters combine with AND. Pass `next_cursor` as `cursor` to read the next page.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page (1 to 100)."},"required":false,"description":"Items per page (1 to 100).","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"The `next_cursor` of the previous page."},"required":false,"description":"The `next_cursor` of the previous page.","name":"cursor","in":"query"},{"schema":{"type":"string","enum":["queued","in_progress","completed","failed","cancelled","expired"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["image","video"],"description":"`image` or `video`."},"required":false,"description":"`image` or `video`.","name":"object","in":"query"}],"responses":{"200":{"description":"One page of jobs. An empty `data` array means no job matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobList"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"A query parameter is invalid. `error.details.allowed` lists the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/jobs/{id}":{"get":{"operationId":"getJob","tags":["Jobs"],"summary":"Get a job","description":"Returns a job of your account. Use it to follow a generation that returned `202`. Poll it every few seconds until `status` is `completed`, `failed`, `cancelled`, or `expired`. A failed job answers with `200`; its `error` has the same shape as an error response.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"job_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no job with this ID (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/jobs/{id}/cancel":{"post":{"operationId":"cancelJob","tags":["Jobs"],"summary":"Cancel a job","description":"Cancels a job that is `queued` or `in_progress`. The reserved amount is released and nothing is charged. Cancelling a cancelled job succeeds again. A job that already finished cannot be cancelled.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"job_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The cancelled job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The job already finished (`invalid_request`); `error.details.status` is its status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no job with this ID (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints":{"post":{"operationId":"createWebhookEndpoint","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Registers a URL that receives events as signed HTTP POST requests (Standard Webhooks). The response carries the signing `secret` once; store it. Each account can have a limited number of endpoints.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpoint"}}}},"responses":{"201":{"description":"The endpoint, with its signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The body is invalid, the URL is not allowed (`invalid_request`, `param` is `url`), or the account has the maximum number of endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"Webhooks are not available in this environment yet (`webhooks_unavailable`). Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}},"get":{"operationId":"listWebhookEndpoints","tags":["Webhooks"],"summary":"List webhook endpoints","description":"Returns the webhook endpoints of your account, oldest first.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"The endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints/{id}":{"get":{"operationId":"getWebhookEndpoint","tags":["Webhooks"],"summary":"Get a webhook endpoint","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}},"patch":{"operationId":"updateWebhookEndpoint","tags":["Webhooks"],"summary":"Update a webhook endpoint","description":"Changes the URL, the subscribed event types, the description, or whether the endpoint is enabled. Fields you omit stay as they are. Setting `enabled` to `true` resumes an endpoint that was stopped after a `410 Gone`.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpoint"}}}},"responses":{"200":{"description":"The updated endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The body is invalid or the URL is not allowed (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}},"delete":{"operationId":"deleteWebhookEndpoint","tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"Deletes the endpoint together with its delivery log. Deliveries in progress stop.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The endpoint was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointDeleted"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints/{id}/test":{"post":{"operationId":"testWebhookEndpoint","tags":["Webhooks"],"summary":"Send a test event","description":"Sends a `webhook.test` event to this endpoint, whatever event types it subscribes to. The response is the delivery, which is sent in the background; follow it in the delivery log.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"The delivery that was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The endpoint is stopped (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","tags":["Webhooks"],"summary":"Rotate the signing secret","description":"Creates a new signing secret and returns it once. For the next 24 hours deliveries carry a signature for the new secret and one for the previous secret in `webhook-signature`, so you can switch your receiver without losing events. Rotating again during that time drops the oldest secret.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The endpoint, with the new signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"503":{"description":"Webhooks are not available in this environment yet (`webhooks_unavailable`). Retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","tags":["Webhooks"],"summary":"List deliveries","description":"Returns the delivery log of the endpoint, newest first. Deliveries are kept for 30 days.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Items per page (1 to 100)."},"required":false,"description":"Items per page (1 to 100).","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"The `next_cursor` of the previous page."},"required":false,"description":"The `next_cursor` of the previous page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"One page of deliveries. An empty `data` array means there are none.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"A query parameter is invalid (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/webhook-endpoints/{id}/deliveries/{deliveryId}/retry":{"post":{"operationId":"retryWebhookDelivery","tags":["Webhooks"],"summary":"Retry a delivery","description":"Sends a delivery again from the start, with the same `webhook-id`. Only a delivery that succeeded or ran out of retries can be retried.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"we_0123456789abcdef0123456789abcdef"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"dlv_0123456789abcdef0123456789abcdef"},"required":true,"name":"deliveryId","in":"path"}],"responses":{"202":{"description":"The delivery that was queued again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"The delivery is still being sent, or the endpoint is stopped (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"401":{"description":"The API key is missing, malformed, unknown, revoked, or expired (`unauthorized`). The response does not say which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"404":{"description":"The account has no webhook endpoint (or delivery) with this ID (`not_found`). Other accounts' IDs look the same.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}},"/v1/reports":{"post":{"operationId":"createReport","tags":["Reports"],"summary":"Report content","description":"Reports generated content that breaks the content policy. No API key is needed. Send the job ID or the URL of the file. The report is reviewed by the operator; content that involves a minor is handled first. Each address can send a limited number of reports per hour. Browsers on other origins cannot call this endpoint (no CORS): send it from a server, or use the report form on the website.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRequest"}}}},"responses":{"201":{"description":"The report was received. Keep the ID if you contact the operator.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"A field is missing, unknown, or out of range, or neither `job_id` nor `url` is given (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"413":{"description":"The request body is larger than 16 KiB (`payload_too_large`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"429":{"description":"Too many reports from this address (`rate_limited`). Retry after the time in `Retry-After`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"default":{"description":"Any other error, in the common error format. For example, `405 method_not_allowed` (with an `Allow` header) when the path does not support the method, or `500 internal_error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}}}}}},"webhooks":{"job.succeeded":{"post":{"operationId":"webhook_job_succeeded","tags":["Webhooks"],"summary":"Event job.succeeded","description":"A job finished and was charged. `data` is the job, the same as `GET /v1/jobs/{id}`; `data.object` is `image` or `video`, and `data.outputs` holds the signed file URLs.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookJobSucceeded"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}},"job.failed":{"post":{"operationId":"webhook_job_failed","tags":["Webhooks"],"summary":"Event job.failed","description":"A job failed or timed out and was not charged. `data` is the job; `data.status` is `failed` or `expired`. For a `failed` job, `data.error` says why. For an `expired` job, `data.error` is `null`.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookJobFailed"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}},"job.cancelled":{"post":{"operationId":"webhook_job_cancelled","tags":["Webhooks"],"summary":"Event job.cancelled","description":"A job was cancelled and was not charged. `data` is the job.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookJobCancelled"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}},"deposit.credited":{"post":{"operationId":"webhook_deposit_credited","tags":["Webhooks"],"summary":"Event deposit.credited","description":"A paid deposit was added to your balance.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDepositCredited"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}},"balance.low":{"post":{"operationId":"webhook_balance_low","tags":["Webhooks"],"summary":"Event balance.low","description":"Your available balance fell below the alert level you set in the dashboard, because a job was charged, a deposit expired, or the balance was adjusted down. It is sent once each time the balance goes from the level or above to below it, and sent again only after the balance has come back to the level or above. Nothing is sent while no alert level is set, and changing the level does not send an event.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookBalanceLow"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}},"webhook.test":{"post":{"operationId":"webhook_webhook_test","tags":["Webhooks"],"summary":"Event webhook.test","description":"Sent only when you ask for a test event (`POST /v1/webhook-endpoints/{id}/test`), whatever event types the endpoint subscribes to.","parameters":[{"schema":{"type":"string","example":"evt_0123456789abcdef0123456789abcdef"},"required":true,"name":"webhook-id","in":"header"},{"schema":{"type":"string","example":"1790068800"},"required":true,"name":"webhook-timestamp","in":"header"},{"schema":{"type":"string","example":"v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="},"required":true,"name":"webhook-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestEvent"}}}},"responses":{"200":{"description":"Any `2xx` status marks the delivery as received."}}}}}}