Errors
Every endpoint fails the same way: an HTTP status and one JSON envelope.
{
"error": {
"type": "invalid_request",
"code": "invalid_input",
"message": "duration must be one of 5, 10.",
"param": "duration",
"details": [ { "param": "duration", "message": "duration must be one of 5, 10." } ],
"request_id": null,
"doc_url": "https://doitong.com/developers/docs/errors#invalid_input"
}
}
| Field | Meaning |
|---|---|
type |
Broad class of the error. Decide what to do from this. |
code |
Exact reason, stable and machine-readable. Every code has a section below; doc_url links to it. |
message |
Human-readable explanation, safe to log or show to a developer. |
param |
The input parameter or header at fault, when there is one. |
details |
For input errors, every problem found: [{ "param", "message" }]. |
request_id |
The request it concerns, when one exists. |
Nothing is charged for a call that returns an error. A request that fails after it was accepted keeps status
failed, carries error: { "type", "code", "message" } on the request object, and is refunded automatically.
Types
| Type | HTTP status | What to do |
|---|---|---|
invalid_request |
400, 413 or 422 | Fix the request. Retrying the same call fails again. |
authentication_error |
401 | Send a valid key in Authorization: Bearer <key>. |
permission_error |
403 | Use a key with the needed scope. |
not_found |
404 | Check the model id or request id. |
insufficient_credits |
402 | Top up the API balance (top_up_url in the error). |
budget_exceeded |
402 | The key's own budget is used up. Final: ask the key owner to raise it. |
conflict |
409 | The resource is not in a state that allows this call. |
rate_limited |
429 | Wait Retry-After seconds, then retry. |
upstream_error |
502 | The model backend failed. Safe to retry with the same Idempotency-Key: it runs again; you were not charged. |
service_unavailable |
503 | The API is paused or a dependency is down. Retry later. |
internal_error |
500 | Our bug. Retry; if it persists, contact support with the time and request_id. |
Codes
invalid_request
Generic malformed request (400).
invalid_json
The body is not valid JSON (400).
invalid_body
The body is valid JSON but not an object; model input must be a JSON object (400).
body_too_large
The body is larger than 16 MB (413). Upload large files and pass their URL instead (see Files).
invalid_parameter
A query parameter has a wrong value, for example limit outside 1 to 100, wait not a number, an unknown
status or category, or storage other than permanent / temporary (400). param names it.
invalid_category
GET /openapi.json?category= names a category that does not exist (400). GET https://api.doitong.com/v1/categories lists them.
invalid_cursor
The cursor of a list call does not belong to this list (400). Start again without a cursor.
invalid_idempotency_key
The Idempotency-Key header is empty or longer than 255 characters (400).
invalid_arguments
An MCP tool call has a missing or malformed argument (MCP only). param names the argument.
invalid_input
The model input does not pass validation (422): an unknown parameter (the message suggests the closest valid name),
a missing required parameter, a wrong type, a value outside the allowed list or range, or both the canonical and the
native name given with different values. param is the first offending parameter and details lists all of them.
Nothing is charged.
unsupported_file
A file has a type we do not accept (422), for example an upload with an unsupported extension, or a content_type
that does not match the extension.
invalid_webhook_url
webhook_url is not a public https:// URL (422). Private, local and plain http:// addresses are refused.
missing_api_key
The endpoint needs an API key and none was sent (401).
invalid_api_key
The key is unknown, revoked or expired (401).
insufficient_scope
The key lacks the scope this call needs (403), for example models:run for a run, or models:read to read
requests and the balance. See Authentication.
account_disabled
The account is closed or suspended (403). Its keys no longer work.
not_found
The path does not exist (404).
model_not_found
No public model has this id (404). List models with GET https://api.doitong.com/v1/models.
request_not_found
No request with this id exists in your account (404). Requests of other accounts are never visible.
insufficient_credits
The account's API balance (API credits, 1,000 API credits = $1 — not the credits of the Doitong apps) does not cover the
price of this call (402). The response is sent before anything is charged. The error carries top_up_url; add money
at https://doitong.com/developers/dashboard#balance and retry.
{ "error": { "type": "insufficient_credits", "code": "insufficient_credits",
"message": "This request costs 560 API credits ($0.56); the API balance is 120 API credits ($0.12). Top up at https://doitong.com/developers/dashboard#balance",
"top_up_url": "https://doitong.com/developers/dashboard#balance", "doc_url": "https://doitong.com/developers/docs/errors#insufficient_credits" } }
budget_exceeded
The call would exceed the API key's own budget in API credits (402). The budget is set by the key's owner; retrying does not help until they raise it.
conflict
The call conflicts with the current state of the resource (409).
idempotency_mismatch
The Idempotency-Key was already used with a different body (409). Use a new key for a new operation.
idempotency_in_progress
A request with the same Idempotency-Key is being created right now (409). Retry in a moment to get it.
request_active
The request is still queued or running, so it has no files to delete yet (409). Delete them once it has finished.
not_cancelable
The request is already succeeded or failed and cannot be canceled (409).
rate_limited
The key made too many requests in the current window (429). See the X-RateLimit-* and Retry-After headers.
too_many_inflight
The account already has 10 requests queued or running (429). Start the next one when one of them finishes.
upstream_error
The model backend refused or failed the request (502 on run, or failed with this code on the request). The API credits are
refunded. If the backend rejected the input itself, the call returns 422 invalid_input with its message instead.
upstream_lost
The model backend no longer knows the request, so no result will ever arrive. It ends as failed with this code
(type upstream_error) and is refunded. Run it again.
timeout
The request ran longer than its limit (15 minutes for images, 60 for video, 30 otherwise) and was stopped. It ends as
failed with this code and is refunded.
service_unavailable
The API is temporarily paused, or a dependency such as file uploads is down (503). Retry later.
internal_error
Something broke on our side (500). Retry; if it persists, contact support.
charge_failed
The account could not be charged because of an internal problem (500). The request is marked failed; nothing was
taken. Retry.
pricing_unavailable
The model's price is not configured, so it cannot be quoted or run right now (500).