Docs API reference
Markdown Get an API key

API referenceChat and agents

Creative Workflows

Durable multi-step creative jobs with an explicit steps[] dependency graph. Use them when your application has already decided what to do: storyboards, image-to-video, batch generation. The API executes, persists state, streams SSE events, and supports cancel, resume, and reseed. User-facing Sogni apps call these cloud workflows.

#Start a workflow

POST /v1/creative-agent/workflows Auth required

Provide an inline input.steps plan, or invoke a saved template with workflow_id and inputs. The two are mutually exclusive. Requires an API key. Unknown fields return 400. Plans may contain up to 12 steps.

#Headers

NameTypeInDescription
Idempotency-KeystringheaderOptional. X-Idempotency-Key is also accepted. Header only. Keys longer than 192 characters are truncated. Reusing a key returns the original workflow with 200 and idempotent: true, even if the body differs.

#Body

NameTypeInDescription
inputobjectbodyInline workflow plan. Allowed fields: title and steps. Required when workflow_id is absent.
input.titlestringbodyOptional human-readable title for the run.
input.stepsrequiredarraybodyArray of step inputs. Each step has id, toolName, arguments, and an optional dependsOn array linking it to upstream artifacts.
workflow_idstringbodyOptional saved-template ID. Compiled server-side into a fresh steps[] before execution.
inputsobjectbodyTyped input values when invoking a template. Keys match WorkflowTemplate.inputs[].name.
token_typestringbodyspark, sogni, or auto (default). Picks which token pays when tokens are billed. It does not choose between an Unlimited plan and tokens; that is billing_mode.
billing_modestringbodyauto (default), subscription, or tokens. Under auto, an active Unlimited plan covers every step it can and no tokens are spent on them. subscription bills eligible steps against the plan only; a step the plan can't cover fails instead of billing tokens. tokens always bills your token balance, even with an active plan; send it to spend Premium Spark for fastest-priority queue access. Vendor models always bill Premium Spark. Other values return 400. See Plan or tokens.
app_sourcestringbodyOptional caller label.
max_estimated_capacity_unitsnumberbodyOptional ceiling on estimated capacity units. A plan above it is rejected with 400 before anything is saved; details.estimatedCapacity carries the estimate.
confirm_costbooleanbodySend false to get an estimate without starting: a plan with a positive estimate is rejected with 400, and details.estimatedCapacity and details.confirmationRequired: true hold the numbers. Resubmit with true (or omit the field) to start. Template runs still pause for approval.
media_referencesarraybodyOptional request media references available to $input_media bindings and negative media indices. Each must be an http(s) URL; inline data: URIs are rejected.
safe_content_filterbooleanbodyOptional Sensitive Content Filter setting for this workflow. Defaults to true. false requires an eligible account and is checked when each step renders. The setting is kept for retries, resume, and reseed.

#Request

curl https://api.sogni.ai/v1/creative-agent/workflows \
  -H "Authorization: Bearer $SOGNI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "title": "Robot sketch to video",
      "steps": [
        {
          "id": "keyframe",
          "toolName": "generate_image",
          "arguments": { "prompt": "A graphite robot sketch on a drafting table" }
        },
        {
          "id": "clip",
          "toolName": "animate_photo",
          "arguments": { "prompt": "Slow dolly-in on the keyframe.", "videoModel": "ltx25", "duration": 5 },
          "dependsOn": [{
            "sourceStepId": "keyframe",
            "sourceArtifactIndex": 0,
            "targetArgument": "sourceImageIndex",
            "transform": "image_index",
            "required": true
          }]
        }
      ]
    },
    "token_type": "auto",
    "max_estimated_capacity_units": 25,
    "confirm_cost": true
  }'

#Response

{
  "status": "success",
  "data": {
    "workflow": {
      "workflowId": "wf_durable_workflow_…",
      "status": "queued",
      "input": { "title": "Robot sketch to video", "steps": [ "…" ] },
      "events": []
    }
  }
}

Inline starts return 201 Created. Template starts (workflow_id) return 202 Accepted with waitingForCostApproval: true and a preview. An idempotent replay returns 200. A plan that names a vendor model on an account without Premium Spark is rejected with 402 before any step runs. If a GPU worker drops a step before producing media, the step is retried once automatically; the first attempt stays in the event log.

Active-workflow cap. Each account can have a limited number of workflows queued or running at once; paused (waiting_for_user) workflows don't count. Over the cap, a start returns 409 with details.activeWorkflowCount and details.activeWorkflowLimit; cancel or finish one first. A 409 does not use up your start allowance. When overall workflow capacity is full, or starts arrive too quickly, a start returns 429. A start-rate refusal carries the wait in the Retry-After header and, in seconds, in the body's retryAfter; wait at least that long, because a start sent sooner is refused again. When no wait is given, back off with jitter. Retry with the same Idempotency-Key, and follow running workflows with /stream or GET /:id rather than re-sending starts.

#List workflows

GET /v1/creative-agent/workflows Auth required

Lists the caller's workflows, most recently updated first. next is the next offset, or null on the last page.

#Query parameters

NameTypeInDescription
offsetintegerqueryDefault 0.
limitintegerqueryDefault 20, max 100.

#Response

{
  "status": "success",
  "data": { "workflows": [ "…" ], "next": 20 }
}

#Read a workflow

GET /v1/creative-agent/workflows/:id Auth required

Returns a single workflow snapshot. Status is queued, running, waiting_for_user, completed, partial_failure, failed, or cancelled. Paused snapshots also carry waitingReason (for example cost_approval_required, safety_review_required, insufficient_credit, or other) and awaitingCostApproval. Offer confirm-cost only when awaitingCostApproval is true.

#Read the event log

GET /v1/creative-agent/workflows/:id/events Auth required

Returns the persisted event log for a workflow.

#Stream events

GET /v1/creative-agent/workflows/:id/events/stream Auth required

Server-Sent Events stream. Replays persisted events, then follows new ones. Pass ?after=<sequence> or send Last-Event-ID to skip events you already have. The stream also sends workflow_status frames ({ workflowId, status }, plus waitingReason and awaitingCostApproval while paused) and heartbeat comments. It stays open through waiting_for_user and closes on completed, failed, partial_failure, or cancelled. If the stream emits event: error, reconnect with Last-Event-ID.

#Event types

workflow_started, workflow_progress, workflow_waiting_for_user, workflow_completed, workflow_failed, workflow_cancelled, step_started, step_completed, step_failed, step_waiting_for_user, artifact_created, and custom. Ignore types you don't recognize.

#Resume a workflow

POST /v1/creative-agent/workflows/:id/resume Auth required

Resumes a paused or interrupted workflow from persisted state. Requires an API key. Returns 202 with { workflow, resumed: true }. Finished workflows and cost-approval pauses return 409; use confirm-cost for the latter.

#Body

NameTypeInDescription
token_typestringbodyOptional. Overrides which token pays for the rest of the run.
billing_modestringbodyOptional. auto, subscription, or tokens, as on start. A new value replaces the stored one for every step not yet dispatched.
app_sourcestringbodyOptional caller label.
safe_content_filterbooleanbodyOptional. Records a new Sensitive Content Filter setting before the run continues; it applies to every step not yet dispatched. Send false to release a safety_review_required pause. Account eligibility is still checked when each step renders.

#Confirm cost

POST /v1/creative-agent/workflows/:id/confirm-cost Auth required

Approves or rejects the cost preview for a workflow paused with cost_approval_required, such as a template run, which authorizes cost on start. resume does not release a cost-approval pause; use this endpoint. Rapid repeated calls return 429.

#Body

NameTypeInDescription
decisionrequiredstringbody"confirm" or "cancel".
acceptedCostPreviewrequiredobjectbodyRequired for decision: "confirm" (alias accepted_cost_preview). Echo the persisted preview { totalEstimatedCapacityUnits, tokenType, validityUntil }. A stale or mismatched value returns 409; a missing or malformed object returns 400.
Idempotency-KeystringheaderOptional. X-Idempotency-Key or a body idempotency_key also work. A replay returns { workflow, idempotent: true }; the same key with a different body returns 409.

#Response

{
  "status": "success",
  "data": { "workflow": { "…": "…" }, "decision": "confirm", "authorization": { "…": "…" } }
}

A confirm requires an API key and a preview no older than five minutes; re-read the workflow for a fresh preview. cancel returns { workflow, decision: "cancel" }. A 409 for the wrong state carries details: { retryable, workflowStatus, waitingReason, awaitingCostApproval }. An account with no available balance gets 402.

#Cancel a workflow

POST /v1/creative-agent/workflows/:id/cancel Auth required

Cooperative cancel. Flips the workflow to cancelled and emits a cancel event for SSE replay. Takes no body. Returns { workflow, transitioned, inFlight }; cancelling an already-finished workflow returns the snapshot with transitioned: false.

#Reseed a workflow

POST /v1/creative-agent/workflows/:id/reseed Auth required

Clones a completed or partial_failure workflow with fresh seeds and starts it as a new workflow, for alternate takes without retyping a plan. Requires an API key. Returns 201 with { workflow, reseed: { cloned_from_run_id, steps } }. The source's Sensitive Content Filter setting carries over, and the new run counts against the same active-workflow and start limits, with the same 409 and 429 responses as a start.

#Body

NameTypeInDescription
Idempotency-KeystringheaderOptional. X-Idempotency-Key is also accepted. A reseed mints new seeds, so a retried request without a key starts a second take. Reusing a key returns 200 with idempotent: true, the workflow the first request started, and the seeds it received. A key already used for a different request returns 409.
seed_overridesobjectbodyOptional per-step seed overrides. Omit to let the server generate fresh seeds for every step.
token_typestringbodyOptional. Which token pays when tokens are billed.
billing_modestringbodyOptional. auto, subscription, or tokens, as on start. Omit to keep the source run's setting.
app_sourcestringbodyOptional caller label.