Skip to content

Actions API

Build the assistant’s actions from code, or let an AI tool build them through the MCP server. Everything is written to the draft: visitors get it when the project is next published in the dashboard. Publishing stays a dashboard step.

Method Path Scope What it does
GET /api/v1/projects/{projectId}/actions actions:read List the actions, with whether each can be edited through the API.
POST /api/v1/projects/{projectId}/actions actions:write Create an action.
GET /api/v1/projects/{projectId}/actions/{actionId} actions:read Read one, ready to change and send back.
PUT /api/v1/projects/{projectId}/actions/{actionId} actions:write Replace one whole.
DELETE /api/v1/projects/{projectId}/actions/{actionId} actions:write Delete one, unless another action runs it.

actions:write is its own scope rather than part of assistant:write: an action can call other systems and post to your page, which changing the instructions cannot.

An action is a list of steps (nodes) joined by edges. It’s the format the dashboard’s “Create with AI” writes, so it’s compact and easy for an AI to produce.

{
"title": "Request a callback",
"enabled": false,
"nodes": [
{ "key": "start", "type": "start", "name": "Start", "trigger": "ai",
"aiDescription": "When the visitor asks to be called back." },
{ "key": "ask", "type": "message", "name": "Ask for a number",
"botMessage": "Which number should we call?", "responseType": "form",
"formFields": [{ "key": "phone", "label": "Phone", "type": "phone", "required": true }] },
{ "key": "done", "type": "end", "name": "Done" }
],
"edges": [
{ "from": "start", "to": "ask" },
{ "from": "ask", "to": "done" }
]
}
Step type What it holds
start trigger (when it runs: ai, chat_start, after_greeting, session_end_detected, session_ended, or none), aiDescription, inputs.
message botMessage, responseType (single_select, multi_select, form, message_only), options {key, label}, formFields {key, label, type, required, placeholder}.
condition rules {key, sourceNodeKey, sourceField, operator, value}: true when any rule passes.
http_request method, url (with {name} placeholders), values.
page_event eventName, values.
run_action targetFlowId (another action’s id), params.
end onComplete (continue, end_session), returnToAi.

Branch a single_select step with edge.branch set to an option’s key, and a condition with "true" or "false". See Steps and Start inputs and values for what each step does.

GET returns the action’s definition in exactly the shape PUT takes: change it and send it back whole. The keys in a read are the stored ids, so steps, options and fields you keep keep their ids, and answers, analytics and other actions’ references keep pointing at them.

  • HTTP steps show their URL as (kept as it is), and their headers are never shown, because they may hold credentials. Send (kept as it is) back to keep them. Set headers in the dashboard.
  • Not editable here. An action that uses settings this format can’t express says editable: false, with the reasons in notEditableBecause; PUT refuses it with 409, and you edit it in the dashboard instead. Nothing is silently dropped. These settings are:
    • AND-ed rule groups;
    • rules on Start inputs or HTTP results;
    • comparing two answers;
    • fields hidden from the AI;
    • LMS completion reporting;
    • an end step that starts an action;
    • hand-over steps.

A write is held to more than a dashboard save, because there is no editor to show the problems in. Nothing is saved until all of these pass:

  • The whole action must be valid: one start, at least one end, every step but end connected, options for a choice step, fields for a form.
  • It must fit the size limits.
  • It must not run itself through other actions.
  • Its title must be unique in the project (409).
  • run_action steps must run actions of the same project.

Every problem is reported at once, in details.problems (422), so you can fix them in one go. New actions are disabled unless you send "enabled": true. Each change is written to the audit log with the key’s id.