Run an AI operation

POST https://api.iconscout.com/v3/ai/{operation}

Submits work and returns one or more tasks to poll at GET /v3/ai/tasks/{task}.

Two body shapes

Which body you send depends on the operation, and GET /v3/ai/operations tells you which is which.

Generative — text-to-image, image-to-image, text-to-3d, image-to-3d. Send form fields or JSON: a model from GET /v3/ai/models, and normally a prompt.

Upload — vectorize, remove-background, smart-group. Send multipart/form-data with a single file. These take no model and no prompt.

Reference images

Each operation declares an image_input of none, optional or required. Passing image_url to an operation declaring none (text-to-3d) is rejected with a 422 rather than silently ignored, so you are never charged for input that was not used. image_url must be publicly reachable over http(s); private, loopback, link-local and cloud-metadata addresses are refused.

Credits

Credits are reserved before dispatch and released if the provider refuses, so failed work does not bill. The response carries credits_charged for this call alongside the remaining balance. Costs are per operation for uploads and per operation/model pair for generation — read them from GET /v3/ai/operations and GET /v3/ai/models rather than hard-coding them. For plans and pricing, see iconscout.com/api.

Entitlements

AI availability follows your plan, and the app must have AI switched on in the API dashboard. Every operation is listed by the catalogue whatever your tier, annotated with available_on_your_plan; calling one your plan does not include, or with AI switched off for the app, returns 403.

Check the catalogue first. The request is validated before entitlement is, so calling an operation your plan excludes with an incomplete body answers 422 The model field is required — the validation error, not the wall behind it. You only see the 403 once the request is otherwise valid. Reading available_on_your_plan from GET /v3/ai/operations tells you in one call what two round trips would otherwise.

Rate limit

Every v3 endpoint is rate limited per client, with reads and writes counted separately — this endpoint is a write. The limit depends on your plan and on the product family (ai, converter, assets), and support can raise it for an individual client, so read it rather than assume it. Exceeding it returns 429 with data.reason of rate_limit_exceeded; back off on Retry-After.

X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset are returned on every response the limiter admits — successes and the errors this endpoint raises alike — so the remaining budget is readable between calls rather than only once you have hit the wall. They are absent only on a 401, which is refused before the limiter runs.

The request limit and the credit allowance are different ceilings and refuse differently: rate_limit_exceeded is transient and clears within the minute, while quota_exhausted means the period's credits are spent and waiting will not clear it before the period rolls over.

Parameters

NameInTypeNotes
operationpathstringrequired; one of text-to-image, image-to-image, text-to-3d, image-to-3d, vectorize, remove-background, smart-group
One of the operations returned by /v3/ai/operations
Idempotency-Keyheaderstringoptional
Replay guard, 16-128 URL-safe characters. A key whose original run already completed is rejected rather than re-dispatched.
X-Project-Referenceheaderstringoptional
Your own identifier for the project, environment or end customer this call belongs to. Recorded against the usage event so spend can be attributed in reporting. Opaque to us; 1-128 printable ASCII.

Responses

StatusMeaning
202 Accepted. Poll each returned task_id at GET /v3/ai/tasks/{task} until its status is COMPLETED or FAILED. Location points at the first task and Retry-After gives the interval to poll at. A call that returned several tasks has one URL per task and Location names only the first — read tasks[].task_id for the rest. Generation typically takes tens of seconds; polling faster than Retry-After will not make it finish sooner.
401 Missing or invalid client credentials. data.reason is invalid_credentials.
403 Your plan does not include this operation, or the app has AI switched off in the API dashboard (data.reason is entitlement_required for both; the message says which), or the client has no owning account to attribute generations to (client_without_owner). Check available_on_your_plan on GET /v3/ai/operations before calling to avoid this round trip — it accounts for the plan and the app setting alike.
404 Unknown operation. data.reason is unknown_operation.
409 This Idempotency-Key has already been used. data.reason is idempotency_in_progress, idempotency_already_completed or idempotency_already_failed. Neither a completed nor an in-flight key is re-dispatched, but the run it names is recoverable in both cases: data.tasks carries the task_ids it produced, so poll those rather than re-sending. It is absent only when the original request has not dispatched yet. Retrying with a new key dispatches new work and is charged again.
413 Uploaded file exceeds max_upload_kb for your plan. data.reason is invalid_request.
422 Validation failure — an unsupported model for the asset, an image_url on a text-only operation, or a prompt rejected under the acceptable use policy (data.reason is invalid_request); or this client holds no active API subscription (subscription_required). Nothing is charged either way.
429 Two different conditions, told apart by data.reason. rate_limit_exceeded — too many requests this minute. Transient; Retry-After says when to retry, and the X-RateLimit-* headers are returned alongside it. quota_exhausted — the API credit allowance for the billing period is spent. Not transient: retrying will not succeed until the period rolls over or the plan is upgraded. The X-RateLimit-* headers are still returned, because the request was admitted by the limiter and counted against your budget before the wallet refused it; only Retry-After is absent, since there is no window to wait out.
Try it in the interactive reference →