200 from an Action run call: replay or skipped? Read the receipt
A 200 on POST /v1/actions/:id/runs means an idempotency replay or a skipped run. Branch on status, idempotency_hit and skip_reason, not on the HTTP code.

A 200 from POST /v1/actions/:id/runs is not a success signal by itself. The API docs say it covers two cases: an idempotency replay, and a run the API skipped because another run was already active. A fresh run is 202. So read the receipt: status, idempotency_hit and skip_reason tell you which case you are in, and the docs say to branch on the status field, not on the HTTP status. A 200 also does not mean the work finished.
The three outcomes
The API-trigger page gives these responses. A render that takes a while makes overlap likely, because only one run of an Action is active at a time.
| HTTP | Receipt shows | Meaning | Your code does |
|---|---|---|---|
202 | status: queued, poll status_url | New run accepted and started | Poll until next_action stops saying poll_status |
200 | idempotency_hit: true | Same key and payload seen before | Use the original run; do not count a new one |
200 | status: skipped, skip_reason: previous_run_active | Another run was active and on_active_run is skip | Decide whether to try later; the API records a run row |
409 | action_run_in_progress | Active run and on_active_run was reject | Retry later; no run recorded |
Telling them apart in code
Check status first. If it is skipped, log skip_reason and stop: no work is running for this trigger, and nothing will be sent to a webhook for it. If idempotency_hit is true, take the run id from the receipt and keep polling the original. Otherwise it is a new run on a 202.
202plusstatus_url: new run, poll it.200plusidempotency_hit: true: the earlier run is the one to track.200plusstatus: skipped: no run was started for this request.409 action_run_in_progress: you asked forreject, so your caller must handle the error.
Choosing skip or reject
skip is the default. Use it when overlapping triggers are harmless, such as a nightly job where one missed night is fine. Use reject when a dropped trigger has to appear as an error in your caller, for example when an order system must know that a render was not started. With reject, no run row is written.
One more caution on the replay case: if you reuse a key with a different body, you do not get a 200; you get 409 idempotency_conflict. And without any key there is no replay protection at all, so each request starts a new run. Pair a stable key with the on_active_run choice, and the receipt will always tell you which of the paths happened.
A receipt handler
Write one function that takes the parsed receipt and returns one of four labels: started, replay, skipped or error. Call it right after the HTTP response, whatever the status. Everything after that point branches on the label, never on the HTTP code. This avoids the common mistake of treating every 200 as a replay and every 202 as the only success.
Log the label with the key you sent. When someone asks why a week's run did not happen, the log shows skipped with previous_run_active, or replay with the earlier run id, and the question is answered.
A skipped run does not send a webhook, so do not wait for one.
- Return a label from the receipt.
- Log label plus key.
- No webhook for a skipped run.
Sources
Related posts
More in Agents
- 402 automation_generation_spend_cap_exceeded in a scheduled run
The per-run generation cap rejected one job before it reserved credits. Only that job fails; the run is not canceled. Raise the cap or trim the plan.
- Agent Completion or three API calls for a render-trim-caption chain
If the steps are fixed, call the endpoints. If the task changes on every call, an Agent Completion with a required spend cap fits. How the two compare.
- Agent Completions input: JSON data the agent reads from a file
Send caller data in input, not in instruction. Sume writes it to /workspace/inputs/sume-action-input.json and tells the agent to read it as data. curl sample.
- Agent Completions request limits: 100,000 characters, 50 messages
The Sume Agent Completions schema caps instruction at 100,000 characters, messages at 50, and images at 30. Know where each limit is enforced before you send.
Written by Sume