Orkestia
Blog
Reference

API & Tooling

The programmatic surfaces for driving Orkestia workflows — the REST API, the typed Node/TS SDK, and the two-token auth model

Orkestia exposes the same workflow engine through four drivers: the typed Node and Python SDKs, a plain HTTP API, and MCP for AI agents. They all wrap one loop — discover → check schema → run → stream → (retry) — over one event-sourced engine, so a run you start from the SDK is the same run you stream over REST or inspect from an agent. End-user login is a separate package: @orkestia/auth (PKCE / OAuth). For the model behind types, runs, and async transitions, see Workflows & runs and the hybrid execution model.

This page documents the programmatic surfaces and their auth. For the input/output schema of any specific workflow, the catalog is the source of truth — browse reference.orkestia.dev or call client.catalog.getSchema() / get_workflow_schema at runtime rather than hard-coding shapes.

The exact request/response shapes below are verified against the SDK contract and the workflow surface. Per-workflow inputs and outputs are not — they vary by type and evolve. Always resolve them from the live schema, not from examples.

The surfaces at a glance

SDKs

@ltinteg/workflows-sdk (Node / TypeScript) and ltinteg-workflows-sdk (Python) — typed clients generated from the same catalog. @orkestia/auth is the browser OAuth SDK for your app's end-users. Full install and examples: SDKs.

REST API

The HTTP surface the SDKs wrap, served at workflow-api.orkestia.dev — start, discover, status, history, and retry. Call it from any language.

MCP

The platform exposed to AI agents: list_workflow_types, get_workflow_schema, start_workflow, watch_workflow, and the rest, callable unattended.

Authentication — the two-token model

Every call carries a bearer token in the Authorization header. There are two kinds, and which one you hold decides what the run can touch.

Org-member tokenEnd-user token
Who holds itYour team operating the platformA user of an app you built on Orkestia
Issued byOrg login (Cognito)Sign in with Orkestia (PKCE, RS256 JWT)
Scope of a runThe whole organization's resourcesOnly that user's data within your app
Org resolutionResolved server-side from the tokenResolved server-side; user identity is injected immutably
Typical callerSDKs, CI, MCP agents, dashboardsWorkflows you've exposed to end-users

The critical invariant for both: org-scoping is automatic. Your organization_uuid is resolved from the token server-side and applied to every run — you never pass it in initial_data unless a workflow's schema explicitly declares it (and then it must match your authenticated org). For an end-user token, Orkestia additionally pins the user's identity to the run so it can never reach another user's data. The isolation is the platform's responsibility, not your app's. See Organizations & identity.

# Both tokens are sent the same way — only the issuer and scope differ.
# Introspect the token you hold via GET /api/auth/me.
curl -sS https://workflow-api.orkestia.dev/api/auth/me \
  -H "Authorization: Bearer $ORKESTIA_TOKEN"
# → { "user_id": "...", "organization_uuid": "org_...",
#     "username": "...", "token_type": "...", "principal_type": "..." }
End-user tokens are RS256 JWTs minted by Sign in with Orkestia; org-member tokens come from Cognito org login. Both are validated server-side and carry the same Authorization: Bearer shape — /api/auth/me reports which kind you're holding via token_type / principal_type.
Still stabilizing. Token issuance, end-user exposure (App Enablement), and rate limits may change between releases. Treat tokens as secrets — keep org-member tokens server-side, and never embed them in a browser app; for browser/end-user flows use Sign in with Orkestia so the app never holds a long-lived credential.

Start a run via REST

The full loop over HTTP. Discovery, schema, start, watch, status, history, and retry are all under /api/workflows.

BASE=https://workflow-api.orkestia.dev/api/workflows
AUTH="Authorization: Bearer $ORKESTIA_TOKEN"

# 1. (optional) discover what's available — the response also carries a
#    `namespaces` summary of the top-level domains (aws, dns, runner, …)
curl -sS "$BASE/types?prefix=aws." -H "$AUTH"

# 2. check the input schema before you run
curl -sS "$BASE/types/aws.s3.create_bucket/schema" -H "$AUTH"
# → { "input_schema": {...}, "output_schema": {...}, "has_prerequisites": true }

# 3. start a run — note: no organization_uuid in the body
curl -sS -X POST "$BASE/start" -H "$AUTH" -H "Content-Type: application/json" \
  -d '{
        "workflow_type": "aws.s3.create_bucket",
        "initial_data": { "bucket": "my-app-assets", "connection_uuid": "…", "region": "us-east-1" }
      }'
# → { "workflow_id": "wf_...", "state_name": "PENDING", "is_terminal": false }

Then track it:

# 4. stream transitions live (Server-Sent Events) until terminal
curl -sN "$BASE/wf_abc123/stream" -H "$AUTH"

# point-in-time run state / full event-sourced history
curl -sS "$BASE/wf_abc123"         -H "$AUTH"
curl -sS "$BASE/wf_abc123/history" -H "$AUTH"

# resume a FAILED run from its last good state
curl -sS -X POST "$BASE/wf_abc123/retry" -H "$AUTH"
EndpointMethodPurpose
/api/workflows/types?prefix=GETList workflow types (filterable by prefix); response includes a namespaces summary
/api/workflows/types/{type}/schemaGETInput/output schema + has_prerequisites
/api/workflows/types/{type}/prerequisitesGETSetup guide when has_prerequisites is true
/api/workflows/startPOSTStart a run → { workflow_id, state_name, is_terminal }
/api/workflows/{id}/streamGET (SSE)Stream transitions until terminal
/api/workflows/{id}GETCurrent run state
/api/workflows/{id}/historyGETFull transition log
/api/workflows/{id}/retryPOSTRe-drive a failed run from its last good state
If has_prerequisites is true (typical for cloud connections), fetch the setup guide first — it returns a step-by-step with Orkestia's platform identity already filled in. See AWS connections and runner management.

Start a run via SDK

The Node/TS SDK wraps the same endpoints. You construct one LtIntegWorkflowsClient, then drive runs either through the manager surface (client.workflows, client.catalog, …) or through the generated, per-workflow bindings — one autocompleted, type-checked binding per workflow, exported as a namespace per domain (aws, github, stripe, …). The flow mirrors REST exactly.

Node — @ltinteg/workflows-sdk
import { LtIntegWorkflowsClient, aws } from "@ltinteg/workflows-sdk"

const client = new LtIntegWorkflowsClient({
  baseUrl: "https://workflow-api.orkestia.dev",
  token: process.env.ORKESTIA_TOKEN,   // org-member or end-user token
})

// discover + inspect via the catalog manager (optional once you know the type)
await client.catalog.listTypes({ prefix: "aws." })
await client.catalog.getSchema("aws.s3.create_bucket")

// start via the generated binding — inputs are typed; organization_uuid is
// resolved from the token, never passed. Returns a WorkflowRunHandle.
const run = await aws.s3.startCreateBucket(client, {
  bucket: "my-app-assets",
  connection_uuid: "…",
  region: "us-east-1",
})
console.log(run.workflowId, run.stateName)

// stream typed events until terminal, or await the terminal output
for await (const evt of run.events()) {
  if (evt.type === "transition") console.log(evt.from, "->", evt.to)
  if (evt.type === "completed") break
  if (evt.type === "failed") throw new Error(evt.error.message)
}
const output = await run.wait()      // resolves to the terminal state_data

// lifecycle off the workflows manager, keyed by workflowId
await client.workflows.get(run.workflowId)
await client.workflows.history(run.workflowId)
await client.workflows.retry(run.workflowId)   // only meaningful for a FAILED run

The client accepts either token kind — pass an org-member token for platform automation, or an end-user token when acting on behalf of a signed-in app user. The surface is identical; the scope is enforced server-side.

The Python SDK (ltinteg-workflows-sdk) is generated from the same catalog and drives the same /api/workflows/* surface. The Node SDK remains the most complete runtime (SSE, run.wait(), typed errors). End-user JWTs come from @orkestia/auth. Browse bindings at reference.orkestia.dev.
Manager methods map one-to-one to the REST endpoints in the table above: client.workflows.get/history/retry/stream, client.catalog.listTypes/getSchema/getDefinition, plus client.plugins and client.projects. The generated bindings are thin wrappers over client.start(...) that add typed inputs/outputs and return a WorkflowRunHandle with .events(), .wait(), and .get().

Choosing a driver

Use…When
Node SDKTypeScript/Node — typed inputs, SSE, run.wait(). See Workflows SDK — Node
Python SDKPython ≥3.10 — same catalog, Pydantic start helpers. See Workflows SDK — Python
@orkestia/authBrowser PKCE / OAuth for your users. See Auth SDK
RESTAnother language, CI, or zero dependencies
MCPAn AI agent operating the catalog — MCP integration

Where to go next

Workflow types registry

The full catalog of workflow domains and types, with per-workflow inputs and outputs.

MCP integration

Drive the same engine from an AI agent — tools, discovery, and the agent loop.

SDKs

Node, Python, and @orkestia/auth — install and examples.

Identity & multi-tenancy

How org-member and end-user tokens scope every run, and how "Sign in with Orkestia" works.

Workflow reference

Every workflow, by domain — the authoritative source for input/output shapes.