Developer section: these pages cover the S6S workflow engine for self-hosted installs and developers. On s6s.ai, API keys and MCP access are issued by S6S on request (contact us); on a self-hosted install, an admin creates them on the API Keys page. For the AI Visibility product, start at the AI Visibility docs.
Workflow Quick Start
Deploy and run your first workflow with the REST API. This is the developer-playground path — if you're here for brand monitoring and the AI Visibility Report, start at /docs/ai-visibility instead.
What this is
The S6S workflow engine runs persistent, multi-step workflows for AI agents and humans. You define workflows as JSON recipes, and S6S handles validation, compilation, credential binding, scheduling, and execution. Deploy via the REST API, MCP server, TypeScript SDK, or the chat UI. The API, MCP server and SDK all need an API key (Step 1).
The same engine powers AI Visibility fixes, discovery, and scheduled monitoring underneath the product surface — but you don't need to know any of that to use AI Visibility. It only matters when you want to build agents on top of S6S.
Choose your path
AI Agent (MCP)
Connect your AI agent via MCP server.
Learn moreAPI / SDK
Deploy workflows programmatically. Continue reading below.
You are hereChat UI
Build workflows with Ali, the AI copilot.
Open chatStep 1: Get an API Key
- On s6s.ai: API keys are issued by S6S on request. Contact us to get one.
- On a self-hosted install: an admin opens API Keys (
/keys) in the app, clicks Create Key, and gives it a name.
The key starts with s6s_ and is shown only once, so copy it right away. Send it as Authorization: Bearer s6s_…. Keep it secure: store it in an environment variable rather than in code. See API Keys for best practices.
The examples below use https://s6s.ai. On a self-hosted install, use your install's URL instead.
Step 2: Deploy Your First Workflow
Deploy a workflow by sending a Recipe to the deploy endpoint. A Recipe is a JSON object that describes your workflow's trigger, steps, and execution flow.
Here is a minimal example — a manual-trigger workflow with a single transform step:
curl -X POST https://s6s.ai/api/v1/workflows/deploy \
-H "Authorization: Bearer s6s_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Hello World",
"trigger": { "type": "manual" },
"steps": [
{
"ref": "greet",
"action": "transform",
"config": {
"template": {
"message": "Hello from S6S!",
"run_id": "{{run.id}}"
}
}
}
],
"flow": ["greet"]
}'Recipe fields explained
| Field | Purpose |
|---|---|
| name | A human-readable name for the workflow. The workflow's slug is derived from it. |
| trigger | How the workflow starts. A manual trigger runs once right after deploy. |
| steps | An array of actions. Each step has a ref (unique name), action (what to do), and config (action-specific settings). |
| flow | Execution order as an array of step refs. Every step must be listed. Refs in a nested array run in parallel. |
Success response
{
"ok": true,
"workflowId": "6c33d112-7297-4f02-9092-2a22135ba56b",
"versionId": "7680dc16-9169-48ad-a08d-c474b625c39f",
"version": 1,
"hash": "2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881",
"runId": "7ed60fcc-f5ac-4306-a455-24bee407186c",
"connectedProviders": [],
"monitorUrl": "https://s6s.ai/runs/7ed60fcc-f5ac-4306-a455-24bee407186c",
"refToId": {
"greet": "4bdbdac7-7204-40bd-ac2e-8571bc6d4f74",
"__trigger__": "76447542-e948-4916-9778-1c8ac50e5da6"
}
}The monitorUrl opens the run in the S6S app (when no run started, it opens the workflow). refToId maps each step ref to the node ID used in run results. If the recipe is invalid, the deploy returns 422 with a list of errors; if the account doesn't have enough credits for the run, it returns 402 and the workflow is saved without a run. See Recipe Format for the deploy options (autoRun, waitForCompletion, callback_url, slug).
Step 3: Check the Run
Poll the run status with your API key, or open the monitorUrl in the app:
curl https://s6s.ai/api/v1/runs/7ed60fcc-f5ac-4306-a455-24bee407186c \ -H "Authorization: Bearer s6s_your_api_key"
Response fields
| Field | Meaning |
|---|---|
| runId, workflowId | IDs of the run and its workflow |
| status | Run status (see below) |
| startedAt, finishedAt, durationMs | Timing |
| errorCode, failureReason | Why a failed run failed |
| steps | One entry per step that has started or been skipped, including the trigger: nodeId, nodeType, status, durationMs, errorCode, output. Match nodeId to a ref with refToId. |
{
"nodeId": "4bdbdac7-7204-40bd-ac2e-8571bc6d4f74",
"nodeType": "action.transform",
"status": "succeeded",
"durationMs": 4,
"errorCode": null,
"output": {
"message": "Hello from S6S!",
"run_id": "7ed60fcc-f5ac-4306-a455-24bee407186c"
}
}Run statuses
| Status | Meaning |
|---|---|
| running | The workflow is currently executing. |
| succeeded | The run finished. Steps skipped by run_if or a branch don't fail it. |
| failed | A step failed. Check errorCode and failureReason. |
| cancelled | The run was cancelled by the user or via API. |
To follow a run live instead of polling, open the server-sent event stream GET /api/runs/{runId}/stream (API key or app session). It sends status and step events as the run progresses, then done when it finishes (or error), and closes after at most 5 minutes.
Step 4: Deploy a Real Workflow
Now let's deploy something more realistic: a webhook-triggered workflow that fetches data from an API, reshapes it, and sends a Slack notification — with a retry policy for the API call.
curl -X POST https://s6s.ai/api/v1/workflows/deploy \
-H "Authorization: Bearer s6s_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Order Processor",
"trigger": {
"type": "webhook",
"path": "/orders/new",
"method": "POST"
},
"steps": [
{
"ref": "fetch_order",
"action": "http",
"config": {
"method": "GET",
"url": "https://api.example.com/orders/{{trigger.output.body.order_id}}"
}
},
{
"ref": "enrich",
"action": "transform",
"config": {
"template": {
"summary": "New order #{{fetch_order.output.body.id}} — ${{fetch_order.output.body.total}}",
"customer": "{{fetch_order.output.body.customer_name}}"
}
}
},
{
"ref": "notify_slack",
"action": "slack",
"config": {
"channel": "#orders",
"textTemplate": "{{enrich.output.summary}}"
},
"credential": "default"
}
],
"flow": ["fetch_order", "enrich", "notify_slack"],
"on_error": {
"fetch_order": { "action": "retry", "retry": { "max_attempts": 3 } }
}
}'Key concepts in this example
- Webhook trigger — Deploying it doesn't start a run. The response's
webhookTriggerobject holds the invoke URL (https://s6s.ai/api/webhooks/orders/new) and, on the first deploy only, thesecret. Each request must carry that secret, for example in anX-Webhook-Tokenheader; the request body is available as{{trigger.output.body.*}}. See Triggers for all authentication options. - Expressions — Double-brace expressions like
{{fetch_order.output.body.id}}reference outputs from previous steps by theirrefname. Anhttpstep's response data is under.body. - Error handling —
on_erroris a top-level map keyed by step ref. Herefetch_ordergets up to 3 attempts when the API returns a temporary error (5xx, 429 or a timeout). Steps without an entry usestop, the default: a failure ends the run.continuemoves on to the next flow item instead. - Parallel flow — Refs in a nested array run in parallel, e.g.
["fetch_order", ["notify_slack", "log_order"]]. A step can only use outputs of steps from earlier flow items, soenrichandnotify_slackcan't run in parallel here:notify_slackreadsenrich's output.
curl -X POST https://s6s.ai/api/webhooks/orders/new \
-H "X-Webhook-Token: $WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
-d '{ "order_id": "1042" }'The webhook replies at once with the new runId; check it as in Step 3.
Missing credentials
If your workflow uses an integration (like Slack) that you haven't connected yet, the workflow is saved but no run starts. The deploy response has "runId": null and a missing_credentials array with a connect_url for each provider:
{
"ok": true,
"workflowId": "6c33d112-7297-4f02-9092-2a22135ba56b",
"versionId": "7680dc16-9169-48ad-a08d-c474b625c39f",
"version": 1,
"hash": "2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881",
"runId": null,
"connectedProviders": [],
"monitorUrl": "https://s6s.ai/workflows/6c33d112-7297-4f02-9092-2a22135ba56b",
"dashboard_url": "https://s6s.ai/credentials",
"missing_credentials": [
{
"provider": "slack",
"ref": "default",
"node_name": "Slack: notify slack",
"connect_url": "https://s6s.ai/credentials/connect/slack"
}
],
"message": "Workflow saved but cannot run — missing credentials for: slack. Connect them at https://s6s.ai/credentials then re-deploy or trigger the workflow.",
"refToId": {
"fetch_order": "4bdbdac7-7204-40bd-ac2e-8571bc6d4f74",
"enrich": "0e4a7c52-1d3b-4f6e-9a8c-2b5d7e9f1a3c",
"notify_slack": "9b1f3e6d-5c2a-4d8b-8e7f-3a6c9d2e5b14",
"__trigger__": "76447542-e948-4916-9778-1c8ac50e5da6"
}
}Visit the connect_url to authorize S6S with the provider, then deploy again. For a webhook-triggered workflow like this one, that next deploy is also the one that returns the webhook secret. Steps with "credential": "default" use any connected account for that provider.
Next Steps
Recipe Format
Full reference for the Recipe JSON schema and deploy options.
Triggers
Webhook, schedule, manual and Telegram triggers.
Node Types
Every trigger, action and logic node with its config and output.
Expressions
Reference data between steps with template expressions.
API Keys
How API keys work and how to keep them secure.
MCP Server
Connect AI agents via the Model Context Protocol.
Ready to build?
Run S6S on your own infrastructure, or ask us for API access on s6s.ai.