Advanced: run a schedule via API

Most schedules should just run on a cadence — see Create a schedule. This page is the advanced path: it lets an external system, rather than a clock, decide when a run happens.

Start a run from your own service with the API-call trigger. This page covers the invoke contract only; see Runs and results for polling and result shapes. The wire namespace is /v1/actions — see the Scheduled overview for how that name maps to the product.

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

Every run request needs all three:

  1. The schedule's status is active.
  2. The schedule's api_trigger_enabled is true.
  3. Your API key carries actions:read and actions:write.

Scopes

ScopeNeeded for
actions:readList and read Actions, read and list runs.
actions:writeCreate a run, cancel a run.

Keys created before the API-call trigger shipped do not carry these scopes. An older key fails every run request with 403 insufficient_scope, and scopes cannot be added to an existing key. Create a new key at API Keys and rotate to it — see 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

An Action can also be invoked by its owner's handle and its own slug:

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. Renaming your handle or the Action's slug changes the vanity path; aut_… never changes. A renamed handle keeps resolving for 90 days, which is a migration window, not a guarantee.

PublicAction exposes both so you can choose:

FieldMeaning
invoke_urlOpaque path. Always present, always permanent.
slugThe Action's URL segment, or null on Actions created before slugs existed.
handleThe owner's current handle, when one is resolvable.
vanity_invoke_urlThe {handle}/{slug} path, or null when either half is unknown.

Slugs are lowercase alphanumerics separated by single hyphens, 2–64 characters, and unique within your account. runs is reserved.

An unknown handle, an unknown slug, and a handle you do not own all return the same 404 action_not_found.

Actions owned by a team workspace are not reachable over the public API yet, by either path.

Request body

The body accepts these properties and nothing else. Unknown properties are rejected with 400.

FieldTypeDefaultNotes
inputobject{}Caller data for this run. Max 64 properties, max 2097152 UTF-8 bytes (2 MiB).
on_active_runskip or rejectskipWhat to do when a run is already active. Format runs default to allow instead — see Calling a Format.
generation_spend_cap_usdnumber ≥ 0Action capClamped to min(request, Action cap). Cannot raise the cap.
primary_output_keystring ≤ 64Action defaultSelects which output key becomes primary_output_url.
output_schema{ name, strict, schema }Action defaultPer-request output schema override. See below.
response_format{ type: "json_schema", json_schema }Documented OpenAI-shaped alias for output_schema.
communication.modeasync or webhookasyncDescriptive. webhook_url is what arms delivery.
communication.webhook_urlHTTPS URI ≤ 2048Terminal delivery target. See Webhooks for current availability.

Overriding the output schema

output_schema overrides whatever the Action binds, for this run only. The receipt reports output_schema.source: "request_override".

output_schema.name is echoed back verbatim on the receipt. Sume only rewrites it internally when it calls the structuring model, which accepts a narrower character set; that rewrite is never visible in the API.

The schema must follow the strict subset described in Create a schedule. A schema outside it is rejected before any run starts:

If you already speak OpenAI Structured Outputs, response_format is accepted as an alias and normalized into output_schema:

Sending both output_schema and response_format is a 400 invalid_request.

output_schema is part of the idempotency payload: replaying a key with a different schema is an 409 idempotency_conflict, not a silent replay of the old receipt.

How input reaches the Agent

input is serialized into a fenced JSON block and handed to the Agent as data, not instructions. The Agent's behavior still comes from the Action's saved instructions.

Caller-supplied text is untrusted. Keep instructions authoritative and do not design an Action that lets input redirect what it does. See Safe automation.

Idempotency

Send an Idempotency-Key header (1–255 characters) on every run request.

  • Replaying the same key with the same payload returns 200 with the original receipt and idempotency_hit: true. No second run starts.
  • Reusing the same key with a different payload returns 409 idempotency_conflict.
  • Without a key, no replay protection is recorded and every request starts a new run.

Response codes

StatusMeaning
202Run accepted and started.
200Idempotency replay, or the run was skipped because another run was already active.

200 does not mean the work finished. Branch on the receipt's status field, not on the HTTP status.

Overlap behavior

Only one run of an Action is active at a time. on_active_run decides what happens to a second request:

ValueResult
skip (default)200 with a receipt whose status is skipped and skip_reason is previous_run_active. A run row is recorded.
reject409 action_run_in_progress. No run is recorded.

Use reject when a dropped trigger should surface as an error in your caller. Use skip when overlapping triggers are expected and harmless.

Errors

Statuserror.codeCauseFix
400output_schema_invalidoutput_schema.schema is outside the strict subset. details.violations[] names each rule.Fix the schema.
400invalid_requestinput is not an object, exceeds 64 properties or 2097152 bytes; generation_spend_cap_usd is not a finite number ≥ 0; webhook_url is not a public HTTPS URL; Action instructions are empty.Fix the request or the Action.
401unauthorizedMissing, malformed, or revoked key.Check the header; create a new key.
403insufficient_scopeKey lacks actions:write (details.required_scope), or is a service-account key (details.reason).Create a new dashboard key.
404action_not_foundUnknown or archived Action, or it belongs to another workspace.Check action_id.
409action_api_trigger_disabledapi_trigger_enabled is false.Enable the API call trigger.
409action_inactiveAction status is inactive.Set the Action Active.
409action_run_in_progressA run is active and on_active_run was reject.Retry later, or use skip.
409idempotency_conflictKey reused with a different payload.Use a new key.
429rate limitedPublic API rate limit.Back off; see Errors and rate limits.
503studio_agent_upstream_unavailableThe 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; contact support if it persists.

Errors use the standard Sume error envelope:

If you generate a client from the OpenAPI document, note that this route declares 200, 202, 400, 401, 404, 409, 429, and 500. The 403 and 503 responses above are raised by the auth and upstream layers and are not in the declared response set, so a generated client may not model them. Handle both.

Two envelope quirks worth knowing:

  • insufficient_scope classifies as category: "validation", not auth. Only 401 maps to the auth category.
  • studio_agent_upstream_unavailable reports retryable: false and next_action: "contact_support" even though it describes an upstream condition. A bounded retry is still reasonable; escalate if it persists.

Always log request_id — it is the fastest way to get a run investigated.

Webhooks

communication.webhook_url is a public HTTPS URL that receives one signed POST carrying the terminal receipt. callback_url is an accepted alias. The full contract — event names, envelope, signature, retry schedule — is on Run webhooks.

Delivery is live on api.dev.sume.com and api.sume.com. Polling remains a valid backup — see Runs and results.

Webhooks documents webhooks for generation jobs, 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}/events endpoint. The receipt's events_url is always null.

Next