PricingAPI keys
  • Overview
  • Quickstart
  • Authentication
  • Overview
  • Format API
  • Create a run
  • Runs and results
  • Bulk runs
  • Editing a Format package
  • Structured output
  • Format catalog
  • Errors and spend
  • Cookbook
  • Embed a Format in your product
  • Waiting for runs and jobs
  • Agents
  • Agent Completions
  • Scheduled
  • Create a schedule
  • Advanced: run a schedule via API
  • Runs and results
  • Run webhooks
  • Safe automation
  • Best practices

Enterprise

Runs and results

Poll a schedule run, read its structured output and artifacts, and cancel it.

Each fire (cron, manual, or API) makes a run with a receipt that you can poll. Polls always work. On api.dev.sume.com and api.sume.com, run webhooks deliver the same receipt without a loop.

Run lifecycle

text
queued -> processing -> completed | failed | canceled | skipped
StatusMeaning
queuedAccepted, not started.
processingThe Agent works on the run.
completedFinished. output and artifacts are populated.
failedFinished with an error.
canceledA cancel request stopped it.
skippedNever ran, because another run was active.

The Action vocabulary spells it canceled with one l. The Action statuses map the internal statuses to new names: done shows as completed, error as failed, and cancelled as canceled. Do not assume that job-side status strings transfer.

The run receipt

GET /v1/action-runs/{run_id} returns the full receipt.

FieldNotes
id, objectobject is action.run.
action{ "id", "title", "trigger_type" }.
statusSee the table above.
trigger{ "source": "cron" | "manual" | "api", "idempotency_key" }.
created_at, started_at, finished_atstarted_at and finished_at are null until they occur.
output_schema{ "name", "strict", "source" }, where source is default, action_default, or request_override.
outputStructured result. null unless status is completed or failed.
output_error{ "code", "message", "details" } when projection failed. null unless status is completed or failed. Refer to When output cannot be produced.
primary_output_keynull unless status is completed.
primary_output_urlResolved URL for primary_output_key. null unless status is completed.
artifactsMedia harvested from the run. Empty until the run is terminal.
usage{ "debited_credits", "held_credits", "refunded_credits", "final", "cap": { "limit_credits", "counted_credits", "remaining_credits" } }, or null when Sume could not read the credits.
error{ "code", "message" }. code is output_error.code when one is set. If not, it is action_run_failed. Non-null only when status is failed.
skip_reasonprevious_run_active on a skipped run, otherwise null.
request_idLog this.
status_url, result_url, cancel_urlUse these URLs. Do not build URLs yourself.
events_urlAlways null. The API does not expose run lifecycle events.
cancelabletrue while queued or processing.
next_actionRecommended next step. Refer to the section below.
idempotency_hittrue when this receipt is an idempotency replay.

usage.cap.counted_credits is the generation credits of this run. It is the same total that Sume uses to enforce the cap of the run, usage.cap.limit_credits. This total includes both reserved and captured credits. It increases while the run is in flight, and it settles when the run terminates.

Know two limits of this value. First, it does not include the LLM turn of the agent. Thus, the value is not the total credits of the run: usage.debited_credits is. Second, it is a receipt figure, not an invoice. GET /v1/usage is still the authoritative billing record.

usage is null when Sume could not read the credits at all. That is different from 0, which means that the run truly used no credits yet.

Poll for completion

GET /v1/action-runs/{run_id}/status returns a trimmed payload for poll loops:

bash
curl -sS "https://api.sume.com/v1/action-runs/$RUN_ID/status" \
  -H "Authorization: Bearer $SUME_API_KEY"
json
{
  "data": {
    "id": "run_...",
    "status": "processing",
    "started_at": "2026-07-31T09:00:01.000Z",
    "finished_at": null,
    "next_action": "poll_status",
    "cancelable": true
  }
}

Branch on next_action:

next_actionWhenDo
poll_statusqueued or processingContinue to poll with backoff.
retry_laterskippedAnother run was active. Try again.
noneEvery terminal run — completed, failed, canceledThere is nothing more to fetch. On a failure, read error and output_error on this receipt.

These three values are the full set. events_url is always null, because there is no public run events route. Thus, no receipt tells you to inspect one.

Fetch the result

GET /v1/action-runs/{run_id}/result returns the full receipt, but only after the run is terminal. While the run is queued or processing, it returns 409 run_not_completed, with the current status in details.status.

bash
curl -sS "https://api.sume.com/v1/action-runs/$RUN_ID/result" \
  -H "Authorization: Bearer $SUME_API_KEY"

Structured output

Schedule runs use the same structured-output contract as Format runs. Structured output documents this contract one time. These items all apply here with no change: the supported schema subset, SumeMediaFile, the built-in sume/action-run-output/v1 schema, the URL gate, primary_output_key resolution, and the output_error failure modes.

Two items are specific to Scheduled:

  • A schedule binds its default schema in the dashboard, not at author time. The receipt shows this default as output_schema.source: "action_default".
  • A per-request output_schema on POST /v1/actions/{action_id}/runs overrides it for that run. The receipt shows it as request_override.

List runs

bash
curl -sS "https://api.sume.com/v1/actions/$ACTION_ID/runs?limit=20" \
  -H "Authorization: Bearer $SUME_API_KEY"

limit accepts 1–100, and the default is 50. The response is a page: { "data": [ ... ], "has_more": false, "next_cursor": null }. To read the full history, send next_cursor back as cursor until has_more is false. The cursor is opaque. If Sume did not create the cursor, the API rejects it with 400 invalid_request.

GET /v1/actions pages the same way: send next_cursor back as cursor until has_more is false.

You can also read a single run under its Action at GET /v1/actions/{action_id}/runs/{run_id}.

Cancel a run

bash
curl -sS -X POST "https://api.sume.com/v1/action-runs/$RUN_ID/cancel" \
  -H "Authorization: Bearer $SUME_API_KEY"

Cancel requires actions:write and is idempotent. If you cancel a run that is already terminal, the API returns that terminal receipt with 200.

End-to-end example

bash
export SUME_API_KEY="sume_live_..."
export ACTION_ID="aut_..."

RUN=$(curl -sS -X POST "https://api.sume.com/v1/actions/$ACTION_ID/runs" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"input":{"product_name":"Aurora Headphones"}}')

RUN_ID=$(echo "$RUN" | jq -r '.data.id')
STATUS=$(echo "$RUN" | jq -r '.data.status')

while [ "$STATUS" = "queued" ] || [ "$STATUS" = "processing" ]; do
  sleep 5
  STATUS=$(curl -sS "https://api.sume.com/v1/action-runs/$RUN_ID/status" \
    -H "Authorization: Bearer $SUME_API_KEY" | jq -r '.data.status')
done

if [ "$STATUS" = "completed" ]; then
  curl -sS "https://api.sume.com/v1/action-runs/$RUN_ID/result" \
    -H "Authorization: Bearer $SUME_API_KEY" \
    | jq -r '.data.primary_output_url'
else
  echo "run ended as $STATUS"
fi

In production, use exponential backoff, not a fixed five-second sleep.

Next

  • Advanced: run a schedule via API
  • Safe automation

On this page

  • Run lifecycle
  • The run receipt
  • Poll for completion
  • Fetch the result
  • Structured output
  • List runs
  • Cancel a run
  • End-to-end example
  • Next