Skip to content
API guide

Authentication

View as Markdown Updated

Every call that runs a model or reads your requests needs an API key. The catalog (GET /models, GET /categories), POST /quote and the OpenAPI document are public.

API keys

Create and revoke keys at https://doitong.com/developers/dashboard#keys. A key looks like doitong_ followed by 64 hex characters and is shown only once, when you create it. Send it in the Authorization header:

terminal
curl https://api.doitong.com/v1/account -H "Authorization: Bearer $DOITONG_API_KEY"

X-API-Key: <key> works as well.

A request without a key gets 401 with code missing_api_key; an unknown, revoked or expired key gets 401 as well.

Scopes

Each key carries scopes. The model API checks these:

Action Scope needed
Run a model, cancel a request, delete a request's files, change the storage setting models:run (keys with the older images:create or videos:create also work)
Create an upload URL models:run or media:upload
Read requests, account models:read (a key that may run models reads too)

New keys get models:read and models:run by default. A call without the right scope gets 403 with code insufficient_scope.

Credit budgets

A key can carry its own budget in API credits (1,000 API credits = $1), set by the account owner: a total budget, a daily budget (last 24 hours), or both. Before a run is charged, the cost is checked against what the key has already spent through this API (net of refunds). A run that would exceed it is refused with 402 budget_exceeded and nothing is charged.

A key without a budget can spend up to the API balance. Separately, a run that the API balance cannot cover gets 402 insufficient_credits with a top_up_url.

GET https://api.doitong.com/v1/account shows the API balance and the key's remaining budget (both in API credits):

200 OK · account
{
  "object": "account",
  "credits": 125000,
  "balance": { "credits": 125000, "usd": "125.00" },
  "top_up_url": "https://doitong.com/developers/dashboard#balance",
  "key": {
    "name": "Production server",
    "prefix": "doitong_3fa9c1e...",
    "scopes": ["models:read", "models:run"],
    "budget_remaining": 50000,
    "rate_limit": 3600,
    "rate_limit_remaining": 3571
  },
  "webhook_signing_secret": "whsec_..."
}

budget_remaining is null when the key has no budget of its own.

Rate limits

Each key may make 3600 requests per hour unless its limit was set differently. Every authenticated response carries the current state:

Header Meaning
X-RateLimit-Limit Requests allowed in the current window
X-RateLimit-Remaining Requests left in the current window
X-RateLimit-Reset Unix time when the window resets

Over the limit you get 429 with a Retry-After header (seconds). Long polling with ?wait= counts as one request per call, so waiting is cheaper than polling quickly.

There is also a limit of 10 requests in progress (queued or running) per account. Starting one more returns 429 too_many_inflight; start it again after one finishes.