Advanced: run a schedule via API
For most schedules, a cadence is the correct choice. Refer to Create a schedule. This page is the advanced path. With this path, an external system decides when a run starts, not a clock.
Use the API-call trigger to start a run from your own service. This page covers
only the invoke contract. For status polls and result shapes, refer to
Runs and results. The wire namespace is /v1/actions.
For how that name maps to the product, refer to the
Scheduled overview.
Exact request and response schemas come from live OpenAPI
(https://api.sume.com/reference/json). The tables here are a readable summary,
not a second schema.
Prerequisites
Each run request needs all three of these conditions:
- The schedule's
statusisactive. - The schedule's
api_trigger_enabledistrue. - Your API key has
actions:readandactions:write.
Scopes
| Scope | Needed for |
|---|---|
actions:read | List and read Actions, read and list runs. |
actions:write | Create a run, cancel a run. |
Keys created before the API-call trigger shipped do not have these scopes.
An older key fails each run request with 403 insufficient_scope. You cannot
add scopes to a key that already exists. Create a new key at
API Keys, and rotate to it. Refer to
Authentication.
Service-account keys cannot create Action runs. They fail with
403 insufficient_scope and details.reason of
service_account_action_runs_unsupported.
Invoke
An accepted run returns 202 with a run receipt:
Vanity URLs
You can also invoke an Action by the handle of its owner and its own slug:
The request body, headers, scopes, idempotency, spend caps, and the run receipt
are identical to the opaque form. The vanity path resolves to the same Action
and runs the same pipeline. action.id in the receipt is always the opaque
aut_… id.
GET /v1/actions/{handle}/{slug} and GET /v1/actions/{handle}/{slug}/runs
work the same way.
Store the opaque id, not the vanity URL. If you rename your handle or the
slug of the Action, the vanity path changes. aut_… never changes. A renamed
handle continues to resolve for 90 days. This is a migration window, not a
guarantee.
PublicAction exposes both, so that you can choose:
| Field | Meaning |
|---|---|
invoke_url | Opaque path. Always present, always permanent. |
slug | The URL segment of the Action, or null on Actions created before slugs existed. |
handle | The current handle of the owner, when one is resolvable. |
vanity_invoke_url | The {handle}/{slug} path, or null when one of the two parts is unknown. |
Slugs are lowercase alphanumerics, with single hyphens as separators. A slug has
2–64 characters and is unique in your account. runs is reserved.
An unknown handle, an unknown slug, and a handle that you do not own all return
the same 404 action_not_found.
Actions that a team workspace owns are not available over the public API yet, on either path.
Request body
The body accepts only these properties. The API silently drops unknown top-level properties and does not reject them. Thus, make sure that the field names are correct.
| Field | Type | Default | Notes |
|---|---|---|---|
input | object | {} | Caller data for this run. Max 64 properties, max 2097152 UTF-8 bytes (2 MiB). |
on_active_run | skip or reject | skip | The action to take when a run is already active. Format runs use allow as the default instead. Refer to Call a Format. |
generation_spend_cap_usd | number > 0, or null | Action cap | The API clamps a number to min(request, Action cap). A number cannot raise the cap. null runs with no automation ceiling. Wallet balance, generation admission, and org limits still apply. The API rejects 0 with 400. |
primary_output_key | string ≤ 64 | Action default | Selects which output key becomes primary_output_url. |
output_schema | { name, strict, schema } | Action default | An override of the output schema for this request. Refer to the section below. |
response_format | { type: "json_schema", json_schema } | — | Documented OpenAI-shaped alias for output_schema. |
communication.mode | async or webhook | async | Descriptive only. webhook_url arms delivery. |
communication.webhook_url | HTTPS URI ≤ 2048 | — | Terminal delivery target. For current availability, refer to Webhooks. |
Overriding the output schema
output_schema overrides the schema that the Action binds, for this run only.
The receipt reports output_schema.source: "request_override".
The receipt returns output_schema.name verbatim. Sume rewrites the name
internally only when it calls the structuring model. That model accepts a
narrower character set. The API never shows that rewrite.
The schema must obey the strict subset that Create a schedule describes. The API rejects a schema outside this subset before a run starts:
If you already use OpenAI Structured Outputs, you can send response_format.
The API accepts it as an alias and normalizes it into output_schema:
If you send both output_schema and response_format, the API returns
400 invalid_request.
output_schema is part of the idempotency payload. If you replay a key with a
different schema, you get 409 idempotency_conflict. You do not get a silent
replay of the old receipt.
How input reaches the Agent
Sume serializes input into a fenced JSON block and gives it to the Agent as
data, not instructions. The behavior of the Agent still comes from the saved
instructions of the Action.
Text from the caller is untrusted. Keep the instructions authoritative. Do not
design an Action that lets input change what the Action does. Refer to
Safe automation.
Idempotency
Send an Idempotency-Key header (1–255 characters) on each run request.
- If you replay the same key with the same payload, the API returns
200with the original receipt andidempotency_hit: true. No second run starts. - If you use the same key again with a different payload, the API returns
409 idempotency_conflict. - Without a key, the API records no replay protection, and each request starts a new run.
Response codes
| Status | Meaning |
|---|---|
202 | Run accepted and started. |
200 | Idempotency replay, or the API skipped the run because another run was already active. |
200 does not mean that the work finished. Branch on the status field of the
receipt, not on the HTTP status.
Overlap behavior
Only one run of an Action is active at a time. on_active_run controls what
occurs to a second request:
| Value | Result |
|---|---|
skip (default) | 200 with a receipt whose status is skipped and skip_reason is previous_run_active. The API records a run row. |
reject | 409 action_run_in_progress. The API records no run. |
Use reject when a dropped trigger must show as an error in your caller. Use
skip when you expect triggers to overlap and the overlap is harmless.
Errors
| Status | error.code | Cause | Fix |
|---|---|---|---|
400 | output_schema_invalid | output_schema.schema is outside the strict subset. details.violations[] names each rule. | Fix the schema. |
400 | invalid_request | input is not an object, or has more than 64 properties or 2097152 bytes. Or generation_spend_cap_usd is not a finite number > 0 or null. Or webhook_url is not a public HTTPS URL. Or the Action instructions are empty. | Fix the request or the Action. |
401 | unauthorized | Missing, malformed, or revoked key. | Examine the header. Create a new key. |
403 | insufficient_scope | The key does not have actions:write (details.required_scope), or it is a service-account key (details.reason). | Create a new dashboard key. |
404 | action_not_found | Unknown or archived Action, or it belongs to another workspace. | Examine action_id. |
409 | action_api_trigger_disabled | api_trigger_enabled is false. | Enable the API call trigger. |
409 | action_inactive | Action status is inactive. | Set the Action Active. |
409 | action_run_in_progress | A run is active and on_active_run was reject. | Retry later, or use skip. |
409 | idempotency_conflict | You used the key again with a different payload. | Use a new key. |
429 | rate limited | Public API rate limit. | Use backoff. Refer to Errors and rate limits. |
503 | studio_agent_upstream_unavailable | The Agents control plane is unconfigured, unreachable, or returned a non-JSON response. details.missing reports action_control_plane when it is a configuration gap. | Retry. If the error continues, contact support. |
Errors use the standard Sume error envelope:
If you generate a client from the OpenAPI document, know that this route
declares 200, 202, 400, 401, 403, 404, 409, 413, 429, and
500. The upstream layer raises the 503 response above. This response is not
in the declared response set. Thus, it is possible that a generated client does
not model it. Handle it.
Know these two envelope details:
- The API classifies
insufficient_scopeascategory: "auth"withnext_action: "authenticate". The fix is a key with the correct scope, not a different request body. studio_agent_upstream_unavailablereportsretryable: falseandnext_action: "contact_support", but it describes an upstream condition. A bounded retry is still reasonable. If the error continues, escalate it.
Always log request_id. It is the fastest way to get an investigation of a run.
Webhooks
communication.webhook_url is a public HTTPS URL. It receives one signed POST
with the terminal receipt. callback_url is an accepted alias.
Run webhooks gives the full contract: event names,
envelope, signature, and retry schedule.
Delivery is live on api.dev.sume.com and api.sume.com. Status polls are
still a valid backup. Refer to Runs and results.
Webhooks documents webhooks for generation jobs. That
is a separate surface with its own job.* event set. The signature scheme is
the same, so one verifier covers both.
Not available
- No MCP tool and no CLI command for Actions.
- No public endpoint to create, edit, or delete an Action. Use the dashboard.
- No
/v1/action-runs/{run_id}/eventsendpoint. Theevents_urlof the receipt is alwaysnull.