spicyapiDocs
Main content

Task commitment and retry

Why an accepted generation task cannot be canceled, and how failed or expired tasks are retried safely.

Once createTask is accepted, the generation task is committed and cannot be canceled. This rule applies while it is queued as well as while it is running: generation cannot be reliably stopped once it has started, so SpicyAPI never exposes a local action that could report cancellation while the work — and its cost — carries on.

Accepted tasks are irreversible

Review the model, inputs and estimated charge before submitting. Closing the browser, leaving the page or deleting an API key does not stop an accepted task.

Retry a terminal task

A retry runs a finished, unsuccessful task again: it creates a new task with the same model, input and callback URL, so you do not have to send the original request body again. The new task is billed like any other: its estimated charge is held when it is accepted, and it is charged only if it succeeds.

POST /api/v1/jobs/retry
curl -X POST https://api.spicyapi.ai/api/v1/jobs/retry \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: retry-order-8814-1" \
  -d '{"taskId":"job_01k3m8x9q2z4v7n5p6r8s0t1w3"}'

Replace the example taskId with the ID of your failed task. Always send an Idempotency-Key with retry (for example retry-<sourceTaskId>-1): without one, a double click or a network retry creates two billed tasks.

Only failed and expired tasks should be retried. Historical canceled records remain readable and may also be retried for backward compatibility, but new tasks cannot enter that state through a user action. Success creates a new queued task and returns HTTP 200 (not 202 as createTask does), with code: 200:

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "job_01k3mnewtask",
    "sourceTaskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued",
    "estimatedCost": "0.08",
    "deadlineAt": "2026-08-28T10:12:04Z"
  },
  "request_id": "req_01k3mretry"
}

Poll or wait for the new taskId, not the source one; see Asynchronous tasks.

  • The source task remains terminal and unchanged.
  • The new task's sourceTaskId points to the source, preserving retry lineage.
  • Current schema, price, permission and balance checks run again. A retry is a new task: it is queued again and processed independently of the source.
  • The new task sends its callback to the same callBackUrl as the source task, and keeps the source task's retention period; an X-Spicy-Retention header on retry is ignored.
  • A retry reuses the source task's input exactly. Reference files uploaded to SpicyAPI — including small Base64 images, which are stored as uploads — last one day. After that, a retry returns 400: upload the file again and create a new task with createTask.
  • Idempotency-Key is scoped to the source task and retry action. Repeating the same key for the same source task returns the same new task instead of creating another.

When retry is refused

Nothing is held or charged when retry returns an error.

ResponseWhyWhat to do
404The source task does not exist, or was created with a different API keyRetry with the key that created it
409The source task succeeded (a new generation needs createTask), is still queued or running, or its billing is not final yetWait until it is failed or expired with settled: true; for another generation use createTask
409The source task's input is no longer stored — its prompt retention period passed, or you destroyed its contentSend the original request again with createTask
400A referenced upload has expired, or the callback URL saved on the source task no longer passes validationUpload the file again, or use a valid callBackUrl, and send the request with createTask
402Not enough balance, or a spend cap was reachedSee Billing

A network error is not a failed task

If a createTask connection breaks before the response arrives, replay createTask with its original Idempotency-Key. Use retry only when an existing task has a confirmed terminal state.

State and retry matrix

Current stateWhat you can do
queued / runningWait for the terminal result; the task cannot be canceled
succeededRead or download the result; create a new task for another generation
failed / expiredRetry to create a separately billed task
historical canceledRead the record or retry it; no new user cancellation is available

Before retrying, look at errorCode. rate_limited, upstream_unavailable and upstream_failed are worth a retry; timeout and generation_failed may fail the same way again. For invalid_request, unsupported_combination and content_rejected the same input will fail again, and for invalid_asset the reference file has to be uploaded again — change the input and use createTask instead. See Task failure codes.

On this page