{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Doitong Models API","version":"2026-10-20","summary":"Image, video, audio and other AI models behind one REST interface, priced like the upstream in USD.","description":"One POST /run/{model} for every model (add ?wait= to get the result in the same call), one GET /requests/{id} for status, exact prices from POST /quote/{model}, output files on our storage (kept forever, paid per GB-month, or 7 days for free: the account setting or ?storage=) and signed webhooks. Model ids contain slashes; they are written as is in the path. Prices are API credits paid from the account's API balance: 1000 API credits = 1 USD, every price object carries the USD amount (add ?currency=rub for roubles). Typed per-model paths: this document carries the featured models by default; add ?category=<id>, ?model=<id> or ?models=all for others (the generic /run/{model_id} accepts every model of GET /models).","contact":{"name":"Doitong","url":"https://doitong.com/developers"}},"servers":[{"url":"https://api.doitong.ru/v1","description":"Doitong API"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Models","description":"The model catalog."},{"name":"Run","description":"Quote and run models."},{"name":"Requests","description":"Status, results and cancellation of runs."},{"name":"Files","description":"Upload input files."},{"name":"Account","description":"API balance (API credits), key limits and file storage."},{"name":"MCP","description":"Model Context Protocol endpoint for AI agents."}],"paths":{"/models":{"get":{"operationId":"listModels","tags":["Models"],"summary":"List models","security":[],"parameters":[{"name":"q","in":"query","required":false,"description":"Words that must all appear in the id, name, maker or tags.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Category id.","schema":{"type":"string","enum":["text-to-image","image-to-image","text-to-video","image-to-video","reference-to-video","video-to-video","lipsync","upscale","background-removal","text-to-speech","speech-to-text","text-to-music","audio","video-to-audio","image-to-3d","text-to-3d","3d","training","llm","vision","other"]}},{"name":"lab","in":"query","required":false,"description":"Model maker, by name or slug (any case).","schema":{"type":"string"}},{"name":"family","in":"query","required":false,"description":"Variants group id (the family field of a model).","schema":{"type":"string"}},{"name":"mode","in":"query","required":false,"description":"Price mode.","schema":{"type":"string","enum":["exact","measured","estimate","metered"]}},{"$ref":"#/components/parameters/Limit"},{"name":"cursor","in":"query","required":false,"description":"next_cursor of the previous page.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Currency"}],"responses":{"200":{"description":"A page of models.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"}}}},"400":{"$ref":"#/components/responses/Error"}}}},"/models/{model_id}":{"get":{"operationId":"getModel","tags":["Models"],"summary":"Get a model","security":[],"parameters":[{"$ref":"#/components/parameters/ModelId"},{"$ref":"#/components/parameters/Currency"}],"responses":{"200":{"description":"The model.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelDetail"}}}},"404":{"$ref":"#/components/responses/Error"}}}},"/categories":{"get":{"operationId":"listCategories","tags":["Models"],"summary":"List categories","security":[],"responses":{"200":{"description":"Categories that have models.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryList"}}}}}}},"/quote/{model_id}":{"post":{"operationId":"quoteModel","tags":["Run"],"summary":"Quote a run of any model","description":"Same body as run; returns the exact API credits and USD. A key is optional; with one the answer also says whether the API balance and the key can pay.","security":[{},{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ModelId"},{"$ref":"#/components/parameters/Currency"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelInput"}}}},"responses":{"200":{"description":"The exact price.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"}}}},"/run/{model_id}":{"post":{"operationId":"runModel","tags":["Run"],"summary":"Run any model","parameters":[{"$ref":"#/components/parameters/ModelId"},{"$ref":"#/components/parameters/Wait"},{"name":"webhook_url","in":"query","required":false,"description":"https URL that receives a signed POST when the request finishes.","schema":{"type":"string","format":"uri"}},{"name":"storage","in":"query","required":false,"description":"Where the output files go: permanent (kept until deleted, paid per GB-month) or temporary (free, deleted after 7 days). Default: the account setting (GET /account → storage.mode).","schema":{"$ref":"#/components/schemas/StorageMode"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Same key + same body returns the same request instead of a second charge.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelInput"}}}},"responses":{"200":{"description":"Finished within wait, or an idempotent replay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"202":{"description":"Accepted; poll GET /requests/{id}.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"402":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/requests":{"get":{"operationId":"listRequests","tags":["Requests"],"summary":"List this account's requests","parameters":[{"$ref":"#/components/parameters/Limit"},{"name":"status","in":"query","required":false,"description":"Only this status.","schema":{"$ref":"#/components/schemas/RequestStatus"}},{"name":"model","in":"query","required":false,"description":"Only this model id.","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"next_cursor of the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestList"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/requests/{request_id}":{"get":{"operationId":"getRequest","tags":["Requests"],"summary":"Get a request","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/Wait"},{"name":"logs","in":"query","required":false,"description":"Set to 1 to include the latest log lines.","schema":{"type":"string","enum":["0","1"]}}],"responses":{"200":{"description":"The request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"404":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/requests/{request_id}/cancel":{"post":{"operationId":"cancelRequest","tags":["Requests"],"summary":"Cancel a request","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"Canceled (refunded), or already canceled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelResult"}}}},"202":{"description":"The model is already working; cancellation was requested.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelResult"}}}},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/requests/{request_id}/files":{"delete":{"operationId":"deleteRequestFiles","tags":["Requests"],"summary":"Delete a request's output files","description":"Deletes our copies of the output files now and stops their storage charge. The request keeps its URLs with storage.expired = true. Idempotent; a request still running is a 409.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"description":"The request, files deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/files":{"post":{"operationId":"createUpload","tags":["Files"],"summary":"Create an upload URL","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadRequest"}}}},"responses":{"201":{"description":"Upload with PUT, then pass file_url as a model input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"422":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/account":{"get":{"operationId":"getAccount","tags":["Account"],"summary":"API balance and key limits","parameters":[{"$ref":"#/components/parameters/Currency"}],"responses":{"200":{"description":"The account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/account/storage":{"patch":{"operationId":"updateStorageSettings","tags":["Account"],"summary":"Set the default file storage","description":"permanent (default): output files are kept until you delete them, 100 API credits per GB per month from the API balance. temporary: free, deleted after 7 days. Applies to new requests; ?storage= on a run overrides it.","parameters":[{"$ref":"#/components/parameters/Currency"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageSettingsUpdate"}}}},"responses":{"200":{"description":"The storage settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageSettings"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/mcp":{"post":{"operationId":"mcp","tags":["MCP"],"summary":"MCP endpoint (JSON-RPC 2.0, Streamable HTTP)","description":"Tools: search_models, get_model, quote, run, get_request, cancel_request, list_requests, create_upload, get_account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"JSON-RPC response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}},"202":{"description":"Notification accepted (no body)."},"401":{"description":"No API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}}}}},"/run/pixelcut/product-photo":{"post":{"operationId":"runPixelcutProductPhoto","tags":["Run"],"summary":"Run Pixelcut Product Photo","description":"Product image compositor: cuts out the item and places it on a new canvas with background, margins and shadow Price: $0.024 / image.","parameters":[{"$ref":"#/components/parameters/Wait"},{"name":"webhook_url","in":"query","required":false,"description":"https URL that receives a signed POST when the request finishes.","schema":{"type":"string","format":"uri"}},{"name":"storage","in":"query","required":false,"description":"Where the output files go: permanent (kept until deleted, paid per GB-month) or temporary (free, deleted after 7 days). Default: the account setting (GET /account → storage.mode).","schema":{"$ref":"#/components/schemas/StorageMode"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Same key + same body returns the same request instead of a second charge.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PixelcutProductPhotoInput"}}}},"responses":{"200":{"description":"Finished within wait, or an idempotent replay.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Request"},{"type":"object","properties":{"output":{"anyOf":[{"$ref":"#/components/schemas/PixelcutProductPhotoOutput"},{"type":"null"}]}}}]}}}},"202":{"description":"Accepted; poll GET /requests/{id}.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Request"},{"type":"object","properties":{"output":{"anyOf":[{"$ref":"#/components/schemas/PixelcutProductPhotoOutput"},{"type":"null"}]}}}]}}}},"402":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"}}}},"/quote/pixelcut/product-photo":{"post":{"operationId":"quotePixelcutProductPhoto","tags":["Run"],"summary":"Quote Pixelcut Product Photo","description":"Price: $0.024 / image.","security":[{},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PixelcutProductPhotoInput"}}}},"responses":{"200":{"description":"The exact price.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key (doitong_…) as \"Authorization: Bearer <key>\". \"X-API-Key: <key>\" also works."}},"parameters":{"ModelId":{"name":"model_id","in":"path","required":true,"description":"Model id; may contain slashes (e.g. flux/schnell), written as is.","schema":{"type":"string"}},"RequestId":{"name":"request_id","in":"path","required":true,"schema":{"type":"string","pattern":"^req_[a-z0-9]+$"}},"Limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},"Currency":{"name":"currency","in":"query","required":false,"description":"rub adds rouble amounts (rate × 1.3) next to USD; usd leaves them out. Default: rub on api.doitong.ru and doitong.ru, usd elsewhere.","schema":{"type":"string","enum":["usd","rub"]}},"Wait":{"name":"wait","in":"query","required":false,"description":"Hold the call up to this many seconds (max 20) and return the finished request if it completes in time.","schema":{"type":"number","minimum":0,"maximum":20}}},"responses":{"Error":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"ModelInput":{"type":"object","additionalProperties":true,"description":"The model's parameters. See GET /models/{model_id} for its input_schema."},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["type","code","message"],"properties":{"type":{"type":"string","enum":["invalid_request","authentication_error","permission_error","not_found","insufficient_credits","budget_exceeded","conflict","rate_limited","upstream_error","service_unavailable","internal_error"]},"code":{"type":"string"},"message":{"type":"string"},"param":{"type":["string","null"]},"details":{"type":"array","items":{"type":"object","properties":{"param":{"type":"string"},"message":{"type":"string"}}}},"request_id":{"type":["string","null"]},"doc_url":{"type":"string","format":"uri"}}}}},"Price":{"type":"object","description":"Unit price. 1000 API credits = 1 USD (the upstream price).","properties":{"credits":{"type":["number","null"],"description":"API credits per unit (exact prices may have decimals)."},"usd":{"type":["string","null"],"description":"USD per unit, e.g. \"0.112\"."},"rub":{"type":"string","description":"RUB per unit, only with currency=rub or on the RU hosts."},"unit":{"type":"string"},"from_credits":{"type":["integer","null"],"description":"Cheapest plausible single run, in API credits. For a metered model (charged by usage): the typical run, never above hold_credits; a run can settle lower."},"from_usd":{"type":["string","null"]},"from_rub":{"type":"string"},"display":{"type":["string","null"],"description":"e.g. \"$0.112 / second\"."},"credits_display":{"type":["string","null"],"description":"e.g. \"112 API credits / second\"."},"rub_display":{"type":"string","description":"e.g. \"≈ 14.56 ₽ / секунду\" (RU only)."},"mode":{"type":["string","null"],"enum":["exact","measured","estimate","metered",null],"description":"exact: the price is computed from the input; measured: from the length / size of the input files, read before the run; estimate: a flat price per run. All are what a run charges (POST /quote returns the exact amount). metered: charged by actual usage (tokens, seconds of generated speech, processing time) at this unit price — a run holds hold_credits at most and the rest is refunded after it."},"hold_credits":{"type":"integer","description":"metered only: the most a run with the default input can cost (POST /quote gives it for your input)."},"hold_usd":{"type":"string"},"typical_credits":{"type":"integer","description":"metered only: a typical run."},"typical_usd":{"type":"string"},"per":{"type":"string","description":"measured only: what the unit is counted on, e.g. input_video, input_audio, output_video, output_image."},"label":{"type":"string","description":"measured: e.g. \"Price per second of your input video\"; metered: \"Charged by usage\"."}}},"Model":{"type":"object","required":["id","name","category"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"lab":{"type":"string"},"category":{"type":"string"},"summary":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"output_kind":{"type":"string"},"thumbnail_url":{"type":["string","null"]},"price":{"$ref":"#/components/schemas/Price"},"docs_url":{"type":"string","format":"uri"},"family":{"type":["string","null"],"description":"Variants group (GET /models?family=)."}}},"ModelDetail":{"allOf":[{"$ref":"#/components/schemas/Model"},{"type":"object","properties":{"description":{"type":"string"},"family":{"type":["string","null"]},"input_schema":{"type":"object"},"output_schema":{"type":"object"},"required_params":{"type":"array","items":{"type":"string"}},"aliases":{"type":"object","additionalProperties":{"type":"string"}},"pricing":{"type":"object"},"example_input":{"type":"object"},"family_ids":{"type":"array","items":{"type":"string"}},"markdown_url":{"type":"string","format":"uri"}}}]},"ModelList":{"type":"object","required":["object","data"],"properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Model"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"Category":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"count":{"type":"integer"}}},"CategoryList":{"type":"object","required":["object","data"],"properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}},"Quote":{"type":"object","required":["object","model","credits"],"properties":{"object":{"const":"quote"},"model":{"type":"string"},"credits":{"type":"integer","description":"API credits this run charges (1000 = 1 USD)."},"usd":{"type":"string","description":"The same amount in USD, e.g. \"0.56\"."},"rub":{"type":"string","description":"In roubles (rate × 1.3), only with currency=rub or on the RU hosts."},"unit":{"type":"string"},"quantity":{"type":"number"},"unit_credits":{"type":"number"},"mode":{"enum":["exact","measured","estimate","metered"],"description":"exact: priced from the input. measured: priced from the length / size of the input files, which were measured for this quote (see measurements; a run with the same files within an hour charges this). estimate: a flat price per run from the typical cost of this model. All are exactly what the run charges. metered: credits is the HOLD — the most this run can cost, debited when it starts; after the run it is settled to the actual usage and the rest is refunded automatically (see hold, typical, and the request's cost.settled)."},"hold":{"type":"object","description":"metered only: { credits, usd (, rub) } — the most the run can cost."},"typical":{"type":["object","null"],"description":"metered only: { credits, usd (, rub) } of a typical run."},"settlement":{"const":"usage","description":"metered only: the run is charged its actual usage."},"label":{"type":"string","description":"\"Price per run\", \"Estimated price per run\" or, measured, e.g. \"Price per second of your input video\"."},"measurements":{"type":"object","description":"measured only: per input param what was measured ({ seconds, width, height, fps, frames, kind })."},"display":{"type":["string","null"]},"breakdown":{"type":["string","null"]},"input":{"type":"object","description":"The normalized input that was priced."},"warnings":{"type":"array","items":{"type":"string"}},"balance_credits":{"type":"integer","description":"API balance in API credits. Only with an API key."},"balance_usd":{"type":"string","description":"Only with an API key."},"affordable":{"type":"boolean","description":"Only with an API key."},"key_budget_remaining":{"type":["integer","null"],"description":"Only with an API key; API credits; null when the key has no cap."},"top_up_url":{"type":"string","format":"uri","description":"Present when the API balance is too low."}}},"RequestStatus":{"type":"string","enum":["queued","running","succeeded","failed","canceled"]},"Output":{"type":"object","required":["type","url"],"properties":{"type":{"type":"string","enum":["image","video","audio","file","3d"]},"url":{"type":"string","format":"uri"},"content_type":{"type":["string","null"]},"file_size":{"type":["integer","null"]},"width":{"type":["integer","null"]},"height":{"type":["integer","null"]},"duration":{"type":["number","null"]},"stored":{"type":"boolean"},"expired":{"type":"boolean","description":"Present (true) once our copy was deleted; the URL no longer works."}}},"StorageMode":{"type":"string","enum":["permanent","temporary"]},"StorageSettingsUpdate":{"type":"object","required":["mode"],"additionalProperties":false,"properties":{"mode":{"$ref":"#/components/schemas/StorageMode"}}},"RequestStorage":{"type":"object","description":"Where the output files are kept (DESIGN.md §17).","properties":{"mode":{"$ref":"#/components/schemas/StorageMode"},"bytes":{"type":"integer","description":"Bytes of our copies of the output files."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the files are deleted (temporary); null when kept until you delete them."},"expired":{"type":"boolean","description":"true once the files were deleted."}}},"StorageSettings":{"type":"object","properties":{"object":{"type":"string","description":"\"storage_settings\" from PATCH /account/storage."},"mode":{"$ref":"#/components/schemas/StorageMode"},"price_credits_per_gb_month":{"type":"integer","description":"API credits per GB (1024^3 bytes) per month of permanent storage."},"price_usd_per_gb_month":{"type":"string"},"price_rub_per_gb_month":{"type":"string","description":"Only with currency=rub or on the RU hosts."},"temporary_retention_days":{"type":"integer"},"used_bytes":{"type":"integer","description":"Bytes kept permanently (billed)."},"used_gb":{"type":"string"},"expiring_bytes":{"type":"integer","description":"Bytes waiting to be deleted."},"monthly_estimate_credits":{"type":"integer"},"monthly_estimate_usd":{"type":"string"},"grace_started_at":{"type":["string","null"],"format":"date-time","description":"The API balance stopped covering storage at this time."},"grace_until":{"type":["string","null"],"format":"date-time","description":"Top up before this time, or the permanent files become temporary."}}},"Request":{"type":"object","required":["id","object","model","status"],"properties":{"id":{"type":"string"},"object":{"const":"request"},"model":{"type":"string"},"status":{"$ref":"#/components/schemas/RequestStatus"},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"queue_position":{"type":["integer","null"]},"cost":{"type":"object","description":"API credits (1000 = 1 USD).","properties":{"credits":{"type":"integer","description":"The quoted price (metered: the hold)."},"usd":{"type":"string","description":"The quoted price in USD."},"charged":{"type":"integer","description":"Debited from the API balance."},"refunded":{"type":"integer","description":"Given back (failure, cancel, or the unused part of a metered hold)."},"mode":{"const":"metered","description":"Only on metered requests."},"held":{"type":"integer","description":"metered only: the hold debited at the start."},"typical":{"type":"integer","description":"metered only: a typical run, API credits."},"settled":{"type":["object","null"],"description":"metered only, once the request succeeded: status settled (credits = what the usage cost = charged − refunded), pending, or no_usage (the model reported no usage: the hold stands).","properties":{"status":{"enum":["settled","pending","no_usage"]},"credits":{"type":"integer"},"usd":{"type":"string"},"quantity":{"type":"number","description":"Usage units billed."},"unit":{"type":"string","description":"e.g. 1000_tokens, audio_second, compute_second."},"unit_usd":{"type":"string"},"source":{"enum":["billed_usage","processing_time"]},"approximate":{"type":"boolean","description":"true when measured from the processing time."}}}}},"input":{"type":"object"},"output":{"type":["object","null"]},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/Output"}},"error":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}},{"type":"null"}]},"metrics":{"type":["object","null"]},"storage":{"$ref":"#/components/schemas/RequestStorage"},"logs":{"type":"array","items":{"type":"object"}},"urls":{"type":"object","properties":{"self":{"type":"string","format":"uri"},"cancel":{"type":"string","format":"uri"}}}}},"RequestList":{"type":"object","required":["object","data"],"properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"CancelResult":{"allOf":[{"$ref":"#/components/schemas/Request"},{"type":"object","properties":{"cancel_requested":{"type":"boolean"}}}]},"UploadRequest":{"type":"object","required":["filename"],"properties":{"filename":{"type":"string","description":"The extension decides the type (jpg, png, webp, mp4, mov, webm)."},"content_type":{"type":"string"},"size":{"type":"integer","minimum":1,"description":"Bytes."}}},"Upload":{"type":"object","properties":{"object":{"const":"upload"},"upload_url":{"type":"string","format":"uri"},"file_url":{"type":"string","format":"uri"},"method":{"const":"PUT"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"content_type":{"type":"string"},"expires_in":{"type":"integer"},"max_bytes":{"type":"integer"}}},"Account":{"type":"object","properties":{"object":{"const":"account"},"credits":{"type":"integer","description":"API balance in API credits (1000 = 1 USD). Separate from the Doitong app credits."},"balance":{"type":"object","properties":{"credits":{"type":"integer"},"usd":{"type":"string"},"rub":{"type":"string","description":"Only with currency=rub or on the RU hosts."}}},"top_up_url":{"type":"string","format":"uri"},"key":{"type":"object","properties":{"name":{"type":"string"},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"budget_remaining":{"type":["integer","null"],"description":"API credits; null: no cap on the key, the API balance is the limit."},"rate_limit":{"type":"integer"},"rate_limit_remaining":{"type":"integer"}}},"webhook_signing_secret":{"type":"string","description":"HMAC-SHA256 secret of the Doitong-Signature header."},"storage":{"$ref":"#/components/schemas/StorageSettings"}}},"JsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"const":"2.0"},"id":{"type":["string","integer","null"]},"method":{"type":"string"},"params":{"type":"object"}}},"JsonRpcResponse":{"type":"object","required":["jsonrpc"],"properties":{"jsonrpc":{"const":"2.0"},"id":{"type":["string","integer","null"]},"result":{"type":"object"},"error":{"type":"object"}}},"PixelcutProductPhotoInput":{"properties":{"background":{"description":"Background for the output: an image, transparency, or a solid color that defaults to white.","examples":[{"color":{"b":255,"g":255,"r":255},"image_fit":"Cover","mode":"Color"}],"properties":{"color":{"default":{"b":255,"g":255,"r":255},"description":"Solid background fill for 'Color' mode, white by default, specified through R/G/B components ranging from 0 to 255.","properties":{"b":{"maximum":255,"minimum":0,"title":"B","type":"integer"},"g":{"maximum":255,"minimum":0,"title":"G","type":"integer"},"r":{"maximum":255,"minimum":0,"title":"R","type":"integer"}},"required":["r","g","b"],"title":"RGBColor","type":"object","x-doitong-order":["r","g","b"]},"image_fit":{"default":"Cover","description":"Choose how to fit the background image to the canvas. 'Contain' preserves a fitted image with letterboxing over `color`, while 'Stretch' uses distortion to fit; 'Cover' fills the canvas by cropping.","enum":["Cover","Contain","Stretch"],"examples":["Cover"],"title":"Image Fit","type":"string"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"URL for the background image; mandatory in 'Image' mode.","title":"Image Url"},"mode":{"default":"Color","description":"Background mode: 'Color' uses `color`, defaulting to white; 'Transparent' produces transparency and always uses PNG; 'Image' composites the result over `image_url`.","enum":["Transparent","Color","Image"],"title":"Mode","type":"string"}},"title":"Background","type":"object","x-doitong-order":["mode","color","image_url","image_fit"]},"image_size":{"anyOf":[{"properties":{"height":{"default":512,"description":"The height of the generated image.","exclusiveMinimum":0,"maximum":14142,"title":"Height","type":"integer"},"width":{"default":512,"description":"The width of the generated image.","exclusiveMinimum":0,"maximum":14142,"title":"Width","type":"integer"}},"title":"ImageSize","type":"object","x-doitong-order":["width","height"]},{"enum":["square_hd","square","portrait_4_3","portrait_16_9","landscape_4_3","landscape_16_9"],"type":"string"},{"type":"null"}],"default":"square_hd","description":"Dimensions of the output canvas, specified as custom {width, height} or a preset: square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9. The default is square_hd (1024x1024).","title":"Image Size"},"image_url":{"description":"Product image URL for processing.","title":"Image Url","type":"string","x-doitong-alias":"image"},"margin":{"description":"Space between the product and canvas edges. Use `all` to set every margin, with optional overrides for individual sides; the default is 20% per side.","examples":[{"all":"20%"}],"properties":{"all":{"default":"20%","description":"Uniform margin on every side, specified as '%' of the canvas dimension, from 0 to 49%, or in 'px' with a minimum of 0px.","examples":["20%"],"title":"All","type":"string"},"bottom":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bottom margin replacing `all` on that side. Accepts '%' from 0 to 49%, or 'px' at 0px or above.","title":"Bottom"},"left":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Left margin replacing `all` on that side. Accepts '%' from 0 to 49%, or 'px' at 0px or above.","title":"Left"},"right":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Right margin replacing `all` on that side. Accepts '%' from 0 to 49%, or 'px' at 0px or above.","title":"Right"},"top":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Top margin replacing `all` on that side. Accepts '%' from 0 to 49%, or 'px' at 0px or above.","title":"Top"}},"title":"Margin","type":"object","x-doitong-order":["all","left","right","top","bottom"]},"output_format":{"anyOf":[{"enum":["png","jpeg"],"type":"string"},{"type":"null"}],"description":"Output image encoding, chosen from PNG or JPEG, with JPEG unavailable for transparent backgrounds. Omitting the selection preserves the input's format.","title":"Output Format"},"shadow":{"description":"Shadow configuration: select 'Generative' or 'Drop' and configure its settings. Leave unset to apply no shadow.","examples":[{"type":"Generative"}],"properties":{"drop":{"description":"Settings for the drop shadow, applied when the type is 'Drop'.","properties":{"blur":{"default":24,"description":"Shadow blur setting, with maximum softness at 100 corresponding to a radius of 5% of the shorter canvas dimension. The range starts at 0, which leaves the edges hard.","maximum":100,"minimum":0,"title":"Blur","type":"number"},"color":{"default":{"b":0,"g":0,"r":0},"description":"RGB color for the shadow; black is the default.","properties":{"b":{"maximum":255,"minimum":0,"title":"B","type":"integer"},"g":{"maximum":255,"minimum":0,"title":"G","type":"integer"},"r":{"maximum":255,"minimum":0,"title":"R","type":"integer"}},"required":["r","g","b"],"title":"RGBColor","type":"object","x-doitong-order":["r","g","b"]},"horizontal":{"default":50,"description":"Horizontal shadow displacement, where the maximum setting of 100 represents 10% of canvas width. Values range from -100 to 100, with negative settings shifting left and positive settings shifting right.","maximum":100,"minimum":-100,"title":"Horizontal","type":"number"},"opacity":{"default":0.25,"description":"Opacity of the shadow, from 0 to 1.","maximum":1,"minimum":0,"title":"Opacity","type":"number"},"vertical":{"default":8,"description":"Vertical shadow displacement, where the maximum setting of 100 represents 10% of canvas height. Values range from -100 to 100, with negative settings shifting up and positive settings shifting down.","maximum":100,"minimum":-100,"title":"Vertical","type":"number"}},"title":"DropShadow","type":"object","x-doitong-order":["color","horizontal","vertical","blur","opacity"]},"generative":{"description":"Settings for the AI-generated shadow, applied when the type is 'Generative'.","properties":{"light_source":{"anyOf":[{"properties":{"position":{"properties":{"x":{"anyOf":[{"maximum":1,"minimum":-1,"type":"number"},{"type":"null"}],"description":"Horizontal light position, normalized to image center (-1 to 1). Leave unset to auto-estimate the light from the image.","title":"X"},"y":{"anyOf":[{"maximum":1,"minimum":-1,"type":"number"},{"type":"null"}],"description":"Vertical light position, normalized to image center (-1 to 1). Leave unset to auto-estimate the light from the image.","title":"Y"},"z":{"anyOf":[{"maximum":2,"minimum":0,"type":"number"},{"type":"null"}],"description":"Height above subject (0 to 2). Leave unset to auto-estimate the light from the image.","title":"Z"}},"title":"ShadowLightSourcePosition","type":"object","x-doitong-order":["x","y","z"]},"size":{"anyOf":[{"maximum":1,"minimum":0,"type":"number"},{"type":"null"}],"description":"Apparent emitter size/softness. Higher = softer penumbra. Leave unset to auto-estimate the light from the image.","title":"Size"}},"title":"ShadowLightSource","type":"object","x-doitong-order":["size","position"]},{"type":"null"}],"description":"Explicit virtual light source for shadow synthesis, replacing the automatic estimate of light direction from the image when supplied."},"opacity":{"default":0.2,"description":"Opacity of the fully composited shadow, from 0 to 1.","maximum":1,"minimum":0,"title":"Opacity","type":"number"}},"title":"GenerativeShadow","type":"object","x-doitong-order":["opacity","light_source"]},"type":{"anyOf":[{"enum":["Generative","Drop"],"type":"string"},{"type":"null"}],"description":"Optional shadow style, with no shadow when unset. Choose 'Generative' for AI synthesis or 'Drop' for a deterministic drop shadow.","title":"Type"}},"title":"Shadow","type":"object","x-doitong-order":["type","generative","drop"]},"watermark":{"anyOf":[{"properties":{"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"URL for the logo or watermark image. An empty value leaves the output without a watermark.","title":"Image Url"},"margin":{"default":"3%","description":"Distance inward from the canvas edge, expressed as '%' of the canvas (0–49%) or in 'px'.","examples":["3%"],"title":"Margin","type":"string"},"opacity":{"default":1,"description":"Opacity of the watermark, from 0 to 1.","maximum":1,"minimum":0,"title":"Opacity","type":"number"},"position":{"default":"bottom_right","description":"Placement of the watermark.","enum":["top_left","top_right","bottom_left","bottom_right","center"],"examples":["bottom_right"],"title":"Position","type":"string"},"remove_background":{"default":false,"description":"Whether to strip the watermark's background using background removal so that the overlay excludes it.","title":"Remove Background","type":"boolean"},"scale":{"default":0.1,"description":"Width of the watermark, expressed as a fraction of canvas width.","examples":[0.1],"maximum":1,"minimum":0.01,"title":"Scale","type":"number"}},"title":"Watermark","type":"object","x-doitong-order":["image_url","remove_background","position","scale","opacity","margin"]},{"type":"null"}],"description":"Logo or watermark overlay enabled by supplying an image; omitting it leaves the output unwatermarked, as it is by default."}},"required":["image_url"],"title":"ProductPhotoInput","type":"object","x-doitong-order":["image_url","image_size","background","margin","shadow","watermark","output_format"]},"PixelcutProductPhotoOutput":{"properties":{"image":{"anyOf":[{"properties":{"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"MIME type identifying the file's content.","examples":["image/png"],"title":"Content Type"},"file_name":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"File name, generated automatically when omitted.","examples":["z9RV14K95DvU.png"],"title":"File Name"},"file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"File size measured in bytes.","examples":[4404019],"title":"File Size"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The height of the image in pixels.","examples":[1024],"title":"Height"},"url":{"description":"Download URL for the file.","title":"Url","type":"string"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The width of the image in pixels.","examples":[1024],"title":"Width"}},"required":["url"],"title":"Image","type":"object","x-doitong-order":["url","content_type","file_name","file_size","width","height"]},{"type":"null"}],"description":"Product photograph prepared for catalog use."}},"title":"ProductPhotoOutput","type":"object","x-doitong-order":["image"]}}}}