Monitor, cancel, and retry workflow runs
Follow a workflow run to terminal status, cancel active work, retry eligible failures, and reconcile final usage.
On this page
Use the public wrun_... identifier for every lifecycle request. Poll while a run is queued or running; stop automatic polling at succeeded, failed, cancelled, or manual_review.
Webhooks can replace frequent polling for state changes, but the run resource remains the current source of truth. Final usage and billing ledger entries show the settled or released amount for the run.
Read Errors and review before automating retry behavior.
Poll to a terminal state
Poll links.self while status is queued or running. Stop at succeeded, failed, cancelled, manual_review.
set -euo pipefail
API_URL="https://api.entirefeed.com/v1"
INPUTS='{"video_idea":"A slow product reveal with soft daylight"}'
STARTERS=$(curl -fsS "$API_URL/workflow-starters" \
-H "Authorization: Bearer $ENTIREFEED_API_KEY")
STARTER_VERSION=$(printf '%s' "$STARTERS" | jq -r '.data[] | select(.slug == "text-to-video-basic") | .version')
ESTIMATE=$(curl -fsS "$API_URL/workflow-starters/text-to-video-basic/estimate" \
-H "Authorization: Bearer $ENTIREFEED_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --argjson inputs "$INPUTS" --arg version "$STARTER_VERSION" '{inputs: $inputs, starter_version: $version}')")
if [ "$(printf '%s' "$ESTIMATE" | jq '.unknown_costs | length')" -ne 0 ]; then
printf '%s\n' "Estimate contains unknown costs; run creation stopped." >&2
exit 1
fi
ESTIMATE_VERSION=$(printf '%s' "$ESTIMATE" | jq -r '.estimate_version')
RUN=$(curl -fsS "$API_URL/workflow-starters/text-to-video-basic/runs" \
-H "Authorization: Bearer $ENTIREFEED_API_KEY" \
-H "Idempotency-Key: launch-video-042" \
-H "Content-Type: application/json" \
-d "$(jq -n --argjson inputs "$INPUTS" --arg starter "$STARTER_VERSION" --arg estimate "$ESTIMATE_VERSION" '{inputs: $inputs, starter_version: $starter, estimate_version: $estimate}')")
RUN_ID=$(printf '%s' "$RUN" | jq -r '.id')
while :; do
RUN=$(curl -fsS "$API_URL/workflow-runs/$RUN_ID" \
-H "Authorization: Bearer $ENTIREFEED_API_KEY")
STATUS=$(printf '%s' "$RUN" | jq -r '.status')
case "$STATUS" in succeeded|failed|cancelled|manual_review) break ;; esac
sleep 2
done
printf '%s' "$RUN" | jq '{status, output, usage}'{
"id": "wrun_0123456789abcdef0123456789abcdef",
"object": "workflow_run",
"status": "succeeded",
"starter_slug": "text-to-video-basic",
"starter_version": "st_0123456789abcdef01234567",
"created_at": "2026-07-14T08:30:00Z",
"started_at": "2026-07-14T08:30:03Z",
"completed_at": "2026-07-14T08:31:20Z",
"output": {
"video": {
"id": "asset_0123456789abcdef0123456789abcdef",
"type": "video",
"url": "https://cdn.entirefeed.com/examples/launch-video.mp4",
"mime_type": "video/mp4",
"expires_at": null
}
},
"usage": {
"amount_usd": "1.47",
"line_items": [
{
"label": "Video generation",
"amount_usd": "1.47",
"confidence": "exact",
"reason": "Final cost confirmed after completion."
}
],
"billing_status": "settled",
"billing_reason": "final_cost_confirmed"
},
"error": null,
"metadata": {
"customer_job_id": "launch-video-042"
},
"links": {
"self": "https://api.entirefeed.com/v1/workflow-runs/wrun_0123456789abcdef0123456789abcdef"
}
}Cancel active work
Cancel queued or running work. Read the returned run and continue polling if cancellation has not reached a terminal state.
curl https://api.entirefeed.com/v1/workflow-runs/wrun_0123456789abcdef0123456789abcdef/cancel \
-X POST \
-H "Authorization: Bearer $ENTIREFEED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Campaign was paused"
}'Retry eligible terminal work
Retry the latest failed or cancelled run only after work started and when its retry lineage has no active run. The retry is new work with a new public ID and its own Idempotency-Key.
curl https://api.entirefeed.com/v1/workflow-runs/wrun_0123456789abcdef0123456789abcdef/retry \
-X POST \
-H "Authorization: Bearer $ENTIREFEED_API_KEY" \
-H "Idempotency-Key: launch-video-042-retry-1"{
"id": "wrun_fedcba9876543210fedcba9876543210",
"object": "workflow_run",
"status": "queued",
"starter_slug": "text-to-video-basic",
"starter_version": "st_0123456789abcdef01234567",
"created_at": "2026-07-14T08:35:00Z",
"estimated_cost": {
"amount_usd": "1.53"
},
"metadata": {
"customer_job_id": "launch-video-042"
},
"links": {
"self": "https://api.entirefeed.com/v1/workflow-runs/wrun_fedcba9876543210fedcba9876543210"
}
}After an uncertain response, replay the same source run and key to recover the original retry. Reusing that key for another source returns idempotency_conflict. If a newer retry exists, operate on the latest run instead.
Receive signed run events
whsec_...curl https://api.entirefeed.com/v1/webhooks/endpoints \
-X POST \
-H "Authorization: Bearer $ENTIREFEED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/entirefeed",
"events": [
"workflow_run.succeeded",
"workflow_run.failed",
"workflow_run.cancelled",
"workflow_run.manual_review"
]
}'Supported run events are workflow_run.queued, workflow_run.running, workflow_run.succeeded, workflow_run.failed, workflow_run.cancelled, workflow_run.manual_review. Omitting events uses generation.succeeded, generation.failed, workflow_run.succeeded, workflow_run.failed.
{
"id": "f419d0cf-5d8e-4b4c-82bb-6042b17e68f8",
"url": "https://example.com/webhooks/entirefeed",
"events": [
"workflow_run.succeeded",
"workflow_run.failed",
"workflow_run.cancelled",
"workflow_run.manual_review"
],
"secret": "whsec_store_this_value_once"
}Verify EntireFeed-Signature against the exact raw request body before parsing. Store EntireFeed-Event-ID to make delivery handling idempotent.
import { createHmac, timingSafeEqual } from "node:crypto";
const parts = Object.fromEntries(
signatureHeader.split(",").map((part) => part.split("=", 2)),
);
const timestamp = Number(parts.t);
const received = Buffer.from(parts.v1 ?? "", "hex");
const expected = Buffer.from(
createHmac("sha256", process.env.ENTIREFEED_WEBHOOK_SECRET!)
.update(Buffer.concat([Buffer.from(String(timestamp) + "."), rawBody]))
.digest("hex"),
"hex",
);
const fresh = Math.abs(Date.now() / 1000 - timestamp) <= 300;
const valid =
fresh &&
received.length === expected.length &&
timingSafeEqual(received, expected);{
"id": "evt_0123456789abcdef0123456789abcdef",
"type": "workflow_run.succeeded",
"created_at": "2026-07-14T08:31:20Z",
"data": {
"object": {
"id": "wrun_0123456789abcdef0123456789abcdef",
"object": "workflow_run",
"status": "succeeded",
"starter_slug": "text-to-video-basic",
"starter_version": "st_0123456789abcdef01234567",
"created_at": "2026-07-14T08:30:00Z",
"started_at": "2026-07-14T08:30:03Z",
"completed_at": "2026-07-14T08:31:20Z",
"output": {
"video": {
"id": "asset_0123456789abcdef0123456789abcdef",
"type": "video",
"url": "https://cdn.entirefeed.com/examples/launch-video.mp4",
"mime_type": "video/mp4",
"expires_at": null
}
},
"usage": {
"amount_usd": "1.47",
"line_items": [
{
"label": "Video generation",
"amount_usd": "1.47",
"confidence": "exact",
"reason": "Final cost confirmed after completion."
}
],
"billing_status": "settled",
"billing_reason": "final_cost_confirmed"
},
"error": null,
"metadata": {
"customer_job_id": "launch-video-042"
},
"links": {
"self": "https://api.entirefeed.com/v1/workflow-runs/wrun_0123456789abcdef0123456789abcdef"
}
}
}
}Reconcile final usage
Terminal usage is the run-level billing outcome. Filter the ledger by workflow_run_id to reconcile reservation, settlement, and release entries.
curl https://api.entirefeed.com/v1/billing/ledger?workflow_run_id=wrun_0123456789abcdef0123456789abcdef \
-X GET \
-H "Authorization: Bearer $ENTIREFEED_API_KEY"{
"data": [
{
"id": "2f55ef4d-1f48-45db-9406-23754a3287ba",
"type": "RESERVE",
"amount_usd": "-1.53",
"available_after_usd": "8.47",
"reserved_after_usd": "1.53",
"workflow_run_id": "wrun_0123456789abcdef0123456789abcdef",
"description": "Reserved estimated operation cost.",
"created_at": "2026-07-14T08:30:00Z"
},
{
"id": "923fce22-42b1-4c74-8dc7-fafaf8fd64c4",
"type": "SETTLE",
"amount_usd": "-1.47",
"available_after_usd": "8.47",
"reserved_after_usd": "0.06",
"workflow_run_id": "wrun_0123456789abcdef0123456789abcdef",
"description": "Settled final operation cost.",
"created_at": "2026-07-14T08:31:20Z"
},
{
"id": "f0d251ef-a44f-41c3-b2f8-9d8db0ac9505",
"type": "RELEASE",
"amount_usd": "0.06",
"available_after_usd": "8.53",
"reserved_after_usd": "0.00",
"workflow_run_id": "wrun_0123456789abcdef0123456789abcdef",
"description": "Released unused reservation.",
"created_at": "2026-07-14T08:31:20Z"
}
],
"next_cursor": null
}