Skip to content

HTTP API

The UI uses the same API as any client. The interactive OpenAPI page is at /docs on the API (http://localhost:8000/docs in development).

Services that only start workflows use the public API: see Public API and SDKs and the Public API reference (/openapi.public.json, /docs/public).

Envelope

Every REST response is an envelope:

// success
{"success": true, "data": <payload>, "error": null}
// error
{"success": false, "data": null, "error": {"code": "AUTH_INVALID_CREDENTIALS", "message": "Incorrect email or password", "details": null}}

code is stable UPPER_SNAKE and is the contract; message is English for humans and logs. Clients translate by code and fall back to message. The codes are listed in Error codes.

Workflow checks work the same way. POST /api/validate, saving a workflow (POST /api/workflows) and using a template return errors, a list of English messages, and issues, their codes in the same order: {"code", "params"}, or null for a message without one. A run's error event over WebSocket carries issues too when it reports these checks. The editor shows issues in the UI language.

Authentication

Client How
API client POST /api/auth/login → data.token; then Authorization: Bearer <token>
Browser The studio_session cookie, plus X-Requested-With: studio on writes
WebSocket The cookie, or ?token=<token>
Workflow trigger Authorization: Bearer wft_… on /api/hooks/* and /api/lg/* only

Running a workflow over WebSocket

WS /ws/run
→ {"workflow_id": "…", "input": {…}}             start a saved workflow
→ {"resume_run_id": "…", "response": "approved"}  answer a waiting Human node
→ {"workflow_id": "…", "workflow": {…}, …}       run the editor's unsaved graph
→ {"workflow_id": "…", "input": {…}, "steps": 1}  pause after one superstep
→ {"workflow_id": "…", "input": {…}, "until": "node_id"}  pause after that node
→ {"type": "cancel"}                              cancel the current run
← {"type": "run_started", …} {"type": "node_started", …} {"type": "node_token", …}
  {"type": "node_finished", …} … {"type": "run_finished", …}

Public Chat v1

All HTTP paths below are relative to /api/public/v1/chat/{slug} and appear under tag Chat in the public OpenAPI (/openapi.public.json, /docs/public on the server). The socket guide links AsyncAPI and the frame schemas. See Third-party auth and Compatibility.

Method Path Result (data inside the JSON envelope)
GET empty suffix Page settings, access modes, steps mode and attachment limits
GET /logo?v=<hash> Logo bytes, rather than an envelope
GET /sessions {sessions:[...]}, only the caller's sessions
POST /sessions New session; optional JSON {embed:true}
GET /sessions/{sid} Session with turns and steps_mode
GET /sessions/{sid}/turns?after=<turn_id> {turns:[...]} newer than this session's cursor; omit after for all
POST /sessions/{sid}/attachments Uploaded file metadata; multipart field file
GET /sessions/{sid}/attachments/{aid} Authenticated file download, bytes rather than an envelope
DELETE /sessions/{sid}/attachments/{aid} {ok:true}; unsent files only
PUT /sessions/{sid}/turns/{tid}/rating Rating; JSON {value:"up"} or {value:"down",comment?:"..."}
DELETE /sessions/{sid}/turns/{tid}/rating {ok:true}

Streaming: WS /ws/public/v1/chat/{slug} takes optional auth, then one typed message or answer; cancel stops the active run. It emits typed frames with v and seq. See Chat API for examples, Human answers, persistence and reconnect behavior.

App users send an HS256 user JWT in HTTP Bearer or socket auth.token. Anonymous same-origin clients use the chat cookie or X-Chat-Visitor (auth.visitor / ?visitor= on the socket). X-Chat-Visitor: new requests a new visitor token in data.visitor_token on session creation/listing. Studio access uses the studio identity and stays same-origin. Cross-origin clients need an app token and the key's allowed origin, without credentialed CORS.

The unversioned HTTP /api/public/chat/{slug}/... paths are legacy aliases. The old WS /ws/public/chat/{slug} remains same-origin with untyped frames. GET /api/public/chat-frame?path=/c/{slug} is the iframe CSP check used by nginx, not a session or streaming endpoint.

Endpoints

Auth and account
POST   /api/auth/register
POST   /api/auth/login
POST   /api/auth/logout
GET    /api/auth/options
POST   /api/auth/password-reset
POST   /api/auth/password-reset/confirm
GET    /api/me
POST   /api/me/password
Workflows, versions, sharing
GET    /api/workflows                       POST   /api/workflows
GET    /api/workflows/{wid}                 PATCH  /api/workflows/{wid}
DELETE /api/workflows/{wid}                 POST   /api/workflows/{wid}/duplicate
GET    /api/workflows/{wid}/dependents      POST   /api/validate
GET    /api/workflows/{wid}/versions        GET    /api/workflows/{wid}/versions/{n}
GET    /api/workflows/{wid}/versions/diff   POST   /api/workflows/{wid}/versions/{n}/restore
GET    /api/workflows/{wid}/shares          PUT    /api/workflows/{wid}/shares
DELETE /api/workflows/{wid}/shares/{target}
PUT    /api/workflows/{wid}/team-shares     DELETE /api/workflows/{wid}/team-shares/{tid}
GET    /api/workflows/{wid}/transfer        POST   /api/workflows/{wid}/transfer
GET    /api/workflows/{wid}/python          (the code, node lines; ?version=n)
GET    /api/workflows/{wid}/export/python   (the .py file to download)
GET    /api/workflows/{wid}/code            (?language=python|typescript; same data as /python)
GET    /api/workflows/{wid}/export/{language}  (python: the .py file, typescript: the LangGraph.js .ts file)
GET    /api/workflows/{wid}/export/{language}/project  (the runnable LangGraph project zip for langgraph dev)
Runs
GET    /api/workflows/{wid}/runs          (?tests=true: test runs)
GET    /api/runs/pending
GET    /api/runs/{run_id}                (one run with its events, as the history lists it; a workflow tool's child run)
GET    /api/runs/{run_id}/checkpoints   (time travel; fork: WS /ws/run {"fork": {...}})
POST   /api/runs/{run_id}/cancel
WS     /ws/run
API triggers and deliveries
GET    /api/workflows/{wid}/tokens          POST   /api/workflows/{wid}/tokens
DELETE /api/workflows/{wid}/tokens/{tid}    POST   /api/workflows/{wid}/tokens/{tid}/rotate-secret
POST   /api/hooks/workflows/{wid}/runs      GET    /api/hooks/workflows/{wid}/runs/{run_id}
GET    /api/workflows/{wid}/deliveries      POST   /api/workflows/{wid}/deliveries/{did}/redeliver
GET    /api/workflows/{wid}/mcp             PUT    /api/workflows/{wid}/mcp
POST   /mcp                                 (MCP Streamable HTTP, workflow token)
LangGraph Agent Server API (subset)

LangGraph-compatible API (guide), x-api-key: wft_… or a JWT.

GET    /api/lg/info                         POST   /api/lg/assistants/search
GET    /api/lg/assistants/{id}             GET    /api/lg/assistants/{id}/graph
GET    /api/lg/assistants/{id}/schemas     POST   /api/lg/threads
POST   /api/lg/threads/search               GET    /api/lg/threads/{tid}
DELETE /api/lg/threads/{tid}               GET    /api/lg/threads/{tid}/state
POST   /api/lg/threads/{tid}/history       POST   /api/lg/threads/{tid}/runs
POST   /api/lg/threads/{tid}/runs/wait     POST   /api/lg/threads/{tid}/runs/stream
GET    /api/lg/threads/{tid}/runs          GET    /api/lg/threads/{tid}/runs/{rid}
GET    /api/lg/threads/{tid}/runs/{rid}/join  POST /api/lg/threads/{tid}/runs/{rid}/cancel
POST   /api/lg/runs                         POST   /api/lg/runs/wait
POST   /api/lg/runs/stream
Schedules
GET    /api/workflows/{wid}/schedules       POST   /api/workflows/{wid}/schedules
PATCH  /api/workflows/{wid}/schedules/{sid} DELETE /api/workflows/{wid}/schedules/{sid}
POST   /api/schedules/preview
Chat triggers
GET    /api/workflows/{wid}/chat-triggers       POST   /api/workflows/{wid}/chat-triggers
PATCH  /api/workflows/{wid}/chat-triggers/{tid} DELETE /api/workflows/{wid}/chat-triggers/{tid}
(owner or admin; {channel_id, place: "dm" | channel or chat id, command, input_field, reply_field, enabled})
Chat and the public chat page
GET    /api/workflows/{wid}/chat                PUT    /api/workflows/{wid}/chat   (settings; PUT needs owner access)
GET    /api/workflows/{wid}/chat/sessions       POST   /api/workflows/{wid}/chat/sessions
GET    /api/chat/sessions/{sid}?view=builder|visitor   DELETE /api/chat/sessions/{sid}
GET    /api/workflows/{wid}/chat/visitors       GET    /api/workflows/{wid}/chat/visitors/{sid}   (read-only)
GET    /api/workflows/{wid}/chat/logo?v=      (logo: a data: URL in PUT sets it, "" removes it)
GET    /api/workflows/{wid}/chat/app-keys     POST /api/workflows/{wid}/chat/app-keys
DELETE /api/workflows/{wid}/chat/app-keys/{key_id}   (owner/admin; one-time secret on creation)
WS     /ws/run   {chat_session_id, message} | {chat_session_id, resume_run_id, response}

Legacy public HTTP aliases (authentication depends on the chat's access modes):
New clients use the complete Public Chat v1 section above.
GET    /api/public/chat/{slug}                  (title, intro, suggestions, access, steps_mode, signed_in, embed_origins, logo)
GET    /api/public/chat/{slug}/sessions         POST   /api/public/chat/{slug}/sessions   ({embed?})
GET    /api/public/chat/{slug}/sessions/{sid}
GET    /api/public/chat/{slug}/sessions/{sid}/turns?after=<turn_id>   (only the newer turns)
GET    /api/public/chat/{slug}/logo?v=<logo>
WS     /ws/public/chat/{slug}   {chat_session_id, message} | {chat_session_id, response}
WS     /ws/public/v1/chat/{slug}   the socket protocol v1: typed frames with v and seq (AsyncAPI: /asyncapi.public.yaml)
GET    /api/public/chat-frame?path=/c/{slug}    (its frame-ancestors, for nginx)

An anonymous visitor is an HttpOnly cookie, or the X-Chat-Visitor header (?visitor= on the socket) in an embed. Send X-Chat-Visitor: new to get a token back as visitor_token.

Workflow tests
GET    /api/workflows/{wid}/tests          POST   /api/workflows/{wid}/tests
PUT    /api/workflows/{wid}/tests/{tid}    DELETE /api/workflows/{wid}/tests/{tid}
POST   /api/workflows/{wid}/tests/run      ({test_ids?, mock?, version?}: version = a stored earlier version)
GET    /api/workflows/{wid}/tests/runs     (suite history)
GET    /api/workflows/{wid}/tests/runs/{sid}   (with the comparison to an earlier version)
POST   /api/workflows/{wid}/tests/runs/{sid}/cancel
POST   /api/workflows/{wid}/tests/runs/{sid}/langsmith
POST   /api/workflows/{wid}/tests/from-run/{run_id}   (a draft case from a run, not saved)
Templates
GET    /api/templates                       POST   /api/templates
POST   /api/templates/import                DELETE /api/templates/{tid}
GET    /api/templates/{tid}/export          POST   /api/templates/{tid}/use
Credentials and providers
GET    /api/providers                       POST   /api/providers/{pid}/test
GET    /api/credentials                     POST   /api/credentials
PUT    /api/credentials/{cid}               DELETE /api/credentials/{cid}
GET    /api/credentials/{cid}/models        POST   /api/credentials/{cid}/embeddings/test
Knowledge bases
GET    /api/knowledge-bases                 POST   /api/knowledge-bases
GET    /api/knowledge-bases/{kid}           PUT    /api/knowledge-bases/{kid}
DELETE /api/knowledge-bases/{kid}           POST   /api/knowledge-bases/{kid}/documents
DELETE /api/knowledge-bases/{kid}/documents/{did}
POST   /api/knowledge-bases/{kid}/reindex   POST   /api/knowledge-bases/{kid}/search
MCP servers
GET    /api/mcp/servers                     POST   /api/mcp/servers
PUT    /api/mcp/servers/{sid}               DELETE /api/mcp/servers/{sid}
POST   /api/mcp/servers/{sid}/discover
Approvals and identities
GET    /api/approvals/channels              POST   /api/approvals/channels
PUT    /api/approvals/channels/{cid}        DELETE /api/approvals/channels/{cid}
POST   /api/approvals/channels/{cid}/test   POST   /api/approvals/channels/{cid}/register-webhook
POST   /api/approvals/callback/{kind}       GET|POST /api/approvals/callback/{kind}/{cid}
POST   /api/channels/events/slack           (Slack Events API: chat triggers; Telegram messages use the callback URL)
GET    /api/approvals/identities            PUT    /api/approvals/identities
POST   /api/approvals/identities/{kind}/send-code
POST   /api/approvals/identities/{kind}/verify
GET    /api/approvals/link                  POST   /api/approvals/link
GET    /api/approvals/audit
GET    /api/approvals/inbox                 POST   /api/approvals/inbox/{run_id}
GET    /api/approvals/slack/oauth           POST   /api/approvals/slack/oauth/start
GET    /api/approvals/slack/oauth/callback
Notifications
GET    /api/notifications                   POST   /api/notifications/{nid}/read
POST   /api/notifications/read-all
GET    /api/notifications/preferences       PUT    /api/notifications/preferences
WS     /ws/notifications
Users, teams, administration
GET    /api/roles
GET    /api/admin/users                     PATCH  /api/admin/users/{target}
DELETE /api/admin/users/{target}            POST   /api/admin/users/{target}/password-reset
GET    /api/admin/policy                    PUT    /api/admin/policy
GET    /api/admin/langsmith                 PUT    /api/admin/langsmith
GET    /api/admin/audit
GET    /api/teams                           POST   /api/teams
PATCH  /api/teams/{tid}                     DELETE /api/teams/{tid}
POST   /api/teams/{tid}/members             DELETE /api/teams/{tid}/members/{member}
Import, code, meta
POST   /api/import                          GET    /api/import/{jid}
POST   /api/import/{jid}/finalize
POST   /api/code/test
GET    /api/health                          GET    /api/meta/runtime
GET    /api/tools