API

Runs

Submit model runs, edits and batches.

Submit calls answer 202 Accepted with a request object; follow it by polling or a webhook. Add ?dry_run=true for a price estimate (Billing). Input is validated with the same schema as the AITOPIA app; see Requests & lifecycle for field details.

MethodPathSummary
POST/v1/models/{model_id}Submit a model run. The body is the model input (see GET /v1/models/{model_id}).
POST/v1/editEdit an asset from an instruction.
POST/v1/batchSubmit 1 to 12 generations as one request.

#POST /v1/models/{model_id}

Submit a model run. The body is the model input (see GET /v1/models/{model_id}).

Besides the model input, the body may carry webhook_url and asset_name.

Authentication: Authorization: Key <key>.

The body is the model input as described by input_schema (the example sends a prompt). webhook_url and asset_name are read by AITOPIA and not passed to the model.

#Path parameters

NameTypeRequiredDescription
model_idstringyesModel id, for example google/nano-banana-2. Send the "/" as it is or encoded as %2F (generated clients encode it); both reach the same model.

#Query parameters

NameTypeRequiredDescription
waitinteger (min 0, max 60)noLong-poll up to N seconds (integer 0-60) for a terminal status.
dry_runtrue | 1 | yes | false | 0 | nonotrue/1/yes returns a price estimate and runs nothing; false/0/no (or absent) runs. Anything else is a 400.

#Request body

Content type application/json. Additional fields are accepted (the model input).

FieldTypeRequiredDescription
webhook_urlstring (uri)noOptional https URL (public host only) that receives the final result as a signed POST.
asset_namestringno

#Responses

StatusDescriptionBody
200Dry run estimate (dry_run=true)DryRun
202AcceptedRequest
400INVALID_INPUT (with field), URL_NOT_ALLOWED, MODEL_REQUIRED, MODEL_KIND_MISMATCH, MODEL_NOT_ALLOWED, DUPLICATE_ITEM or INVALID_RUN_TOKENError
401UNAUTHENTICATED (missing/invalid/revoked key) or KEY_SESSION_EXPIRED (sign in to aitopia.ai to reactivate the key)Error
402INSUFFICIENT_CREDITS, KEY_CREDIT_CAP_REACHED or OVER_BUDGETError
404MODEL_NOT_FOUND or NOT_FOUNDError
409PRICE_CHANGED, PRICE_UNKNOWN or PLAN_EXPIREDError
422PLAN_INVALID, ASSET_UNREACHABLE or NOT_SUPPORTEDError
429RATE_LIMIT, RUN_LIMITED or QUEUE_LIMIT_EXCEEDED (see retry_after_seconds and the Retry-After header)Error
500INTERNAL_ERROR (an unexpected server error)Error
502UPSTREAM_5XX, or UPSTREAM_UNCERTAIN (the run may have started: check the request_id in the body and your balance before retrying)Error
503MODEL_UNAVAILABLE, SERVER_RESTARTING or SESSION_UNAVAILABLE (retryable)Error
504TIMEOUTError

#Example

Request
curl -X POST "https://api-live.aitopia.ai/v1/models/google/nano-banana-2" \
  -H "Authorization: Key $AITOPIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"a lighthouse at dusk, watercolor","webhook_url":"https://example.com/aitopia/webhook"}'
Response 200 (dry_run=true)
{
  "dry_run": true,
  "endpoint": "google/nano-banana-2",
  "credits_estimated": 4,
  "affordable": true,
  "credits_available": 100
}
Response 202
{
  "request_id": "0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "status": "queued",
  "endpoint": "google/nano-banana-2",
  "created_at": "2026-10-23T10:00:00.000Z",
  "completed_at": null,
  "credits_estimated": 4,
  "output": {
    "images": [],
    "videos": [],
    "audio": [],
    "files": []
  },
  "status_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "result_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "cancel_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10/cancel"
}

#POST /v1/edit

Edit an asset from an instruction.

Authentication: Authorization: Key <key>.

instruction: 1 to 1000 characters, any language. media_type: image, video or audio (omit to read it from the file). max_credits ≥ 0 refuses dearer plans (402 OVER_BUDGET). plan_token (from a dry run) runs exactly that priced plan, once, within 1 hour. Planning, dry runs included, is limited to 10 per minute and 100 per day.

#Query parameters

NameTypeRequiredDescription
waitinteger (min 0, max 60)noLong-poll up to N seconds (integer 0-60) for a terminal status.
dry_runtrue | 1 | yes | false | 0 | nonotrue/1/yes returns a price estimate and runs nothing; false/0/no (or absent) runs. Anything else is a 400.

#Request body

Content type application/json.

FieldTypeRequiredDescription
asset_urlstring (uri)yes
instructionstringyes
media_typestringno
max_creditsnumberno
plan_tokenstringnoFrom a dry run: run exactly that priced plan.
webhook_urlstring (uri)noOptional https URL (public host only) that receives the final result as a signed POST.

#Responses

StatusDescriptionBody
200Dry run estimate (dry_run=true)DryRun
202AcceptedRequest
400INVALID_INPUT (with field), URL_NOT_ALLOWED, MODEL_REQUIRED, MODEL_KIND_MISMATCH, MODEL_NOT_ALLOWED, DUPLICATE_ITEM or INVALID_RUN_TOKENError
401UNAUTHENTICATED (missing/invalid/revoked key) or KEY_SESSION_EXPIRED (sign in to aitopia.ai to reactivate the key)Error
402INSUFFICIENT_CREDITS, KEY_CREDIT_CAP_REACHED or OVER_BUDGETError
409PRICE_CHANGED, PRICE_UNKNOWN or PLAN_EXPIREDError
422PLAN_INVALID, ASSET_UNREACHABLE or NOT_SUPPORTEDError
429RATE_LIMIT, RUN_LIMITED or QUEUE_LIMIT_EXCEEDED (see retry_after_seconds and the Retry-After header)Error
500INTERNAL_ERROR (an unexpected server error)Error
502UPSTREAM_5XX, or UPSTREAM_UNCERTAIN (the run may have started: check the request_id in the body and your balance before retrying)Error
503MODEL_UNAVAILABLE, SERVER_RESTARTING or SESSION_UNAVAILABLE (retryable)Error
504TIMEOUTError

#Example

Request
curl -X POST "https://api-live.aitopia.ai/v1/edit" \
  -H "Authorization: Key $AITOPIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"asset_url":"https://cdn.aitopia.ai/...","instruction":"remove the background, make it 9:16","max_credits":50}'
Response 200 (dry_run=true)
{
  "dry_run": true,
  "endpoint": "edit_media",
  "credits_estimated": 30,
  "affordable": true,
  "credits_available": 100,
  "plan_token": "<plan token>",
  "plan_token_expires_in_sec": 3600
}
Response 202
{
  "request_id": "0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "status": "queued",
  "endpoint": "edit_media",
  "created_at": "2026-10-23T10:00:00.000Z",
  "completed_at": null,
  "credits_estimated": 30,
  "output": {
    "images": [],
    "videos": [],
    "audio": [],
    "files": []
  },
  "status_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "result_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "cancel_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10/cancel"
}

#POST /v1/batch

Submit 1 to 12 generations as one request.

Authentication: Authorization: Key <key>.

kind is image, audio or video. Each item is priced and billed like a single run of its model. Identical items need a model that takes a seed, otherwise DUPLICATE_ITEM.

#Query parameters

NameTypeRequiredDescription
waitinteger (min 0, max 60)noLong-poll up to N seconds (integer 0-60) for a terminal status.
dry_runtrue | 1 | yes | false | 0 | nonotrue/1/yes returns a price estimate and runs nothing; false/0/no (or absent) runs. Anything else is a 400.

#Request body

Content type application/json.

FieldTypeRequiredDescription
itemsarray of BatchItem (min 1 items, max 12 items)yes
items[].kindstringyes
items[].promptstringyes
items[].model_idstringyes
items[].inputobjectno
items[].asset_namestringno
webhook_urlstring (uri)noOptional https URL (public host only) that receives the final result as a signed POST.

#Responses

StatusDescriptionBody
200Dry run estimate (dry_run=true)DryRun
202AcceptedRequest
400INVALID_INPUT (with field), URL_NOT_ALLOWED, MODEL_REQUIRED, MODEL_KIND_MISMATCH, MODEL_NOT_ALLOWED, DUPLICATE_ITEM or INVALID_RUN_TOKENError
401UNAUTHENTICATED (missing/invalid/revoked key) or KEY_SESSION_EXPIRED (sign in to aitopia.ai to reactivate the key)Error
402INSUFFICIENT_CREDITS, KEY_CREDIT_CAP_REACHED or OVER_BUDGETError
409PRICE_CHANGED, PRICE_UNKNOWN or PLAN_EXPIREDError
422PLAN_INVALID, ASSET_UNREACHABLE or NOT_SUPPORTEDError
429RATE_LIMIT, RUN_LIMITED or QUEUE_LIMIT_EXCEEDED (see retry_after_seconds and the Retry-After header)Error
500INTERNAL_ERROR (an unexpected server error)Error
502UPSTREAM_5XX, or UPSTREAM_UNCERTAIN (the run may have started: check the request_id in the body and your balance before retrying)Error
503MODEL_UNAVAILABLE, SERVER_RESTARTING or SESSION_UNAVAILABLE (retryable)Error
504TIMEOUTError

#Example

Request
curl -X POST "https://api-live.aitopia.ai/v1/batch" \
  -H "Authorization: Key $AITOPIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"kind":"image","prompt":"a red fox, studio light","model_id":"google/nano-banana-2"},{"kind":"image","prompt":"a red fox, forest at dawn","model_id":"google/nano-banana-2"}]}'
Response 200 (dry_run=true)
{
  "dry_run": true,
  "endpoint": "generate_batch",
  "credits_estimated": 8,
  "affordable": true,
  "credits_available": 100,
  "items": [
    {
      "index": 0,
      "kind": "image",
      "model_id": "google/nano-banana-2",
      "credits_estimated": 4
    },
    {
      "index": 1,
      "kind": "image",
      "model_id": "google/nano-banana-2",
      "credits_estimated": 4
    }
  ]
}
Response 202
{
  "request_id": "0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "status": "queued",
  "endpoint": "generate_batch",
  "created_at": "2026-10-23T10:00:00.000Z",
  "completed_at": null,
  "credits_estimated": 8,
  "output": {
    "images": [],
    "videos": [],
    "audio": [],
    "files": []
  },
  "status_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "result_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10",
  "cancel_url": "https://api-live.aitopia.ai/v1/requests/0d6f3c1e-5b7a-4c2e-9d1f-2a8b6e4c9f10/cancel"
}
AITOPIA REST API · Live https://api-live.aitopia.ai/v1 · Sandbox https://api-sandbox.aitopia.ai/v1