Create
POST /v1/tasks takes a model, an input checked against that model's schema, and optionally webhook_url, namespace and retention_seconds. It needs an Idempotency-Key header (Idempotency). The answer is 202 with the task, or 200 when you passed wait and the task finished inside it.
namespace is your own tag for one of your users, machines or services. It is 1 to 128 characters of letters, digits, ., _, = and -, and starts with a letter or a digit. It must not be personal data; send a hash. Tasks of one namespace share the running limits fairly.
GET /v1/tasks?namespace= and GET /v1/images?namespace= read only that namespace, newest first, so an app can show one user's or one machine's tasks and images. See Images.
Request
curl 'https://api.studio.dramatis.ai/v1/tasks' \
|
-X POST \
|
-H "Authorization: Bearer $OPSIS_API_KEY" \
|
-H "Content-Type: application/json" \
|
-H "Idempotency-Key: sample-$(date +%s)-$RANDOM" \
|
-d '{
|
"model": "google/gemini-3.1-flash-lite-image",
|
"input": {
|
"prompt": "A woman with silver hair stands on a pier at dusk, soft evening light.",
|
"aspect_ratio": "1:1"
|
}
|
}' |
What is checked at create and what is downloaded at dispatch
Inputs are checked inside the create call, before a task exists and before anything is charged. A check that fails refuses the request and charges nothing.
- An inline image (a
data:address) or an upload of the wrong type or size is refused at create as400 invalid_request, withparamnaming the field. - A linked image is confirmed to exist at create, but not downloaded. A link the server refuses (not HTTPS, another port, credentials in it, a private address) is
400 invalid_requesttoo. - A Civitai LoRA is checked by asking Civitai about it. If Civitai cannot be reached, create answers
503 dependency_unavailable; retry with the sameIdempotency-Key. - A linked image is downloaded once, at dispatch. Only a linked image can fail later, with
invalid_asset.
Status
One field, status, says where a task is in its life. A task is final when its status is SUCCEEDED or FAILED. Test for that, so a status added later does not break your client.
A task usually goes from SUBMITTED to RUNNABLE to STARTING to RUNNING to SUCCEEDED. PENDING is shown only while a task is held back, and a task may move from RUNNABLE back to PENDING when its account reaches its running limit after the task was ready. So do not rely on an order between the values.
There is no canceled or expired status. A cancel is FAILED with the error code canceled; a task that ran out of time is FAILED with timeout, or with backend_unavailable when it never started.
Why a task failed
status_reason is a sentence for a person, set only on FAILED and null otherwise. error holds code, message and param for a program: param names the input at fault when there is one. Errors lists the codes. A failed task is refunded, except where a model charges for its own refusal.
The list
GET /v1/tasks takes status, model, namespace, created_after, created_before, limit and cursor. status=FAILED includes your own cancels and tasks that never started; the error.code of each row tells them apart. The list has no filter on error.code in the first release.
Request
curl 'https://api.studio.dramatis.ai/v1/tasks?status=FAILED&limit=20' \
|
-H "Authorization: Bearer $OPSIS_API_KEY" |
Deadlines
deadline_at is set when the task is accepted. It covers waiting and running together and is the outer limit. A task that has not started when its queue allowance ends is FAILED with backend_unavailable. A task whose attempt has run for the model's run_seconds without finishing is FAILED with timeout. Both are refunded. Stop polling at deadline_at plus a few seconds: by then the task is final.
Polling
Read GET /v1/tasks/{id} no faster than every 2 seconds. Start at 2 to 3 seconds and back off to 10. Or pass wait, from 1 to 60 seconds, on the create call. A task that ended FAILED inside the wait answers 200 too.
For production, prefer a webhook to polling.
Cancel
POST /v1/tasks/{id}/cancel works while the status is SUBMITTED, PENDING or RUNNABLE. It moves the task to FAILED with the error code canceled and refunds it. From STARTING on, it answers 409 task_not_cancelable.
Request
curl 'https://api.studio.dramatis.ai/v1/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/cancel' \
|
-X POST \
|
-H "Authorization: Bearer $OPSIS_API_KEY" |
Delete the content
DELETE /v1/tasks/{id}/content removes the task's images, its copies of reference images and its prompt, once the status is final. Before that it answers 409 task_not_finished. The task itself stays, with what it was charged. See Retention.
Request
curl 'https://api.studio.dramatis.ai/v1/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/content' \
|
-X DELETE \
|
-H "Authorization: Bearer $OPSIS_API_KEY" |