Retry a failed run
Queues a failed run of a deployed workflow to execute again.
- Method
- POST
- Path
https://api.returning.ai / v1/ workflow-builder/ data-workflows/ runs/ {runId}/ retry - Permission
- workflowBuilder
- Retries
- This is the one call in the family whose whole point is a controlled repeat, so its own retry behaviour matters.
Authentication#
- Header
Authorization: Bearer <API_KEY>- Permission
- workflowBuilder
Authorization: Bearer <API_KEY> with workflowBuilder, and the run must belong to the key's community.
| Failure | Meaning | Recovery |
|---|---|---|
403 API_KEY_PERMISSION_DENIED | The key has no workflowBuilder permission | Grant the permission. |
404 RUN_NOT_FOUND | Unknown run id, or a run of another community | Use a run id from the list. |
409 RETRY_IN_PROGRESS | A retry of this run is already claimed, and this call carried no key or a different one | Wait for the queued retry to finish, then read the runs list. |
Behaviour#
A retry is not a resume: the whole workflow runs from the trigger again, including steps that already succeeded, paid rewards, or called an outside service.
There is no confirmation header and no separate retry permission to hold back a caller who should not retry: workflowBuilder covers it. What protects you is the per-run claim below, which stops two retries of one run from both queueing, and an Idempotency-Key, which turns a lost response into a replay.
Request#
Path parameters#
Rule^[0-9a-fA-F]{24}$
Eg65f1a2b3c4d5e6f708192a40
Headers#
Watch for
- A retry runs the whole workflow again. It does not continue from the failed step, so a step that already paid a reward runs again and may pay again.
- Only a failed run of a workflow that is currently deployed is queued. Anything else is skipped with
queued: 0and a reason inskipped, including a run that succeeded, a run that is still in progress, and a workflow that is no longer deployed. - A retry runs the workflow's current deployed steps with the failed run's recorded trigger output. It is the same event as far as the steps are concerned, against the configuration as it is now, so a step you changed after the failure runs in its new form.
- The response describes the request, not the result. Read the runs list for the outcome.
- There is no dry run of a retry: it is a real execution by definition, and the response says
sideEffects: "real"on every answer. If you want to know what the retry will do, dry-run the workflow (POST /{workflowId}/testwithmode: "dry-run") before queueing it.
More examples and details
curl --request POST \
--url "https://api.returning.ai/v1/workflow-builder/data-workflows/runs/65f1a2b3c4d5e6f708192a45/retry" \
--header "Authorization: Bearer <API_KEY>" \
--header "Idempotency-Key: retry-65f1a2b3c4d5e6f708192a45-1"
A first call queues the run:
{
"data": {
"requested": 1,
"queued": 1,
"skipped": [],
"sideEffects": "real",
"alreadyRequested": false,
"reExecution": "The whole workflow runs again from the trigger, including steps that already succeeded, paid rewards or called outside services."
}
}
A repeat with the same Idempotency-Key replays the recorded answer instead of queueing again:
{
"data": {
"requested": 1,
"queued": 1,
"skipped": [],
"sideEffects": "real",
"alreadyRequested": true,
"reExecution": "The whole workflow runs again from the trigger, including steps that already succeeded, paid rewards or called outside services."
}
}
A second call while the first retry is still in progress, with a different key or no key, is refused:
{
"meta": {
"status": "error",
"statusCode": 409,
"code": "RETRY_IN_PROGRESS",
"runId": "65f1a2b3c4d5e6f708192a45",
"requestId": "3f4d0e8b-7a6c-4f1e-9b2d-5a7c8e1f0a3b"
},
"message": "API request rejected error.",
"detail": "A retry for this run is already in progress. Wait for it to finish before retrying again.",
"solution": "Read error detail and try again."
}
curl --request POST \
--url 'https://api.returning.ai/v1/workflow-builder/data-workflows/runs/<runId>/retry' \
--header 'Authorization: Bearer <API_KEY>'
Response#
HTTP 200 with requested, queued, skipped, sideEffects, alreadyRequested and reExecution.
queued: 1withalreadyRequested: falsemeans a retry was accepted. Read back withGET /{workflowId}/runs: a new run appears with its own id, and the original run keeps its result.alreadyRequested: truemeans the platform replayed the answer it recorded for this run and thisIdempotency-Key. The body is the original answer, soqueued: 1describes the first call rather than this one. A replay is served for 24 hours, whether or not the ten-minute claim is still held.sideEffects: "real"is always present. A retry is a real execution.
Eg{ ... }
Eg1
Eg1
Eg[]
Eg"65f1a2b3c4d5e6f708192a40"
Eg"Only failed data workflow histories can be retried."
real: a retry runs the workflow again.Eg"real"
Idempotency-Key.Egfalse
Eg"The whole workflow runs again from the trigger, including steps that already succeeded, paid rewards or called outside services."
{
"data": {
"requested": 1,
"queued": 1,
"skipped": [],
"sideEffects": "real",
"alreadyRequested": false,
"reExecution": "The whole workflow runs again from the trigger, including steps that already succeeded, paid rewards or called outside services."
}
}
Errors#
Fix the request04
VALIDATION_FAILEDFix the requestmeta.errors names each field as path and message. The path says where the problem is: params. for a path parameter, query. for a query parameter, body. for a request field, and body itself for a body that is not valid JSON. An oversized body is 413 with the same code.AUTHENTICATION_REQUIREDFix the requestAPI_KEY_REQUIREDFix the requestAPI_KEY_PERMISSION_DENIEDFix the requestworkflowBuilder permission. Grant the permission.Fix the data02
RUN_NOT_FOUNDFix the dataRETRY_IN_PROGRESSFix the dataRetry with backoff02
RATE_LIMITEDRetry with backoffINTERNAL_ERRORRetry with backoffRetries
This is the one call in the family whose whole point is a controlled repeat, so its own retry behaviour matters. Two guards run in this order: A recorded answer for your key is checked first. If this run already accepted a retry under your Idempotency-Key, the platform returns that answer with alreadyRequested: true and queues nothing. The record lasts 24 hours, so a client that retries after a timeout still cannot queue a second re-run, even long after the first claim expired. Otherwise a claim is taken on the run and its current state. While that claim is held, a call with no key or a different key is refused with 409 RETRY_IN_PROGRESS and queues nothing. Two retries of one failed run can therefore never both queue. The claim lasts ten minutes. After it expires, a call with a new key or no key takes a new claim and queues a new re-run: the workflow really executes again, so a reward step can pay twice. Only the same key is protected, and only by the 24-hour record. If queueing itself fails, the claim is released, so a failed attempt does not block a legitimate retry. Use an Idempotency-Key on every retry: it is what turns a lost response into a replay instead of a refusal.
{
"meta": {
"status": "error",
"statusCode": 400,
"code": "VALIDATION_FAILED",
"errors": [
{
"path": "params.workflowId",
"message": "Id must be a 24 character hex string"
}
],
"requestId": "3f4d0e8b-7a6c-4f1e-9b2d-5a7c8e1f0a3b"
},
"message": "API request rejected error.",
"detail": "The request body is not valid.",
"solution": "Read error detail and try again."
}