Create a bot flow
Creates a flow. name, bot_name, inbox_id and trigger_definition are all required — omitting any of them returns a 422 naming the missing ones.
graph is accepted here and seeds the first version. It is the only write endpoint other than publish that saves a graph. Administrator only.
curl --request POST \
--url https://app.tied.com/api/v1/accounts/{account_id}/bot_flows \
--header 'Content-Type: application/json' \
--header 'api_access_token: <api-key>' \
--data '
{
"bot_flow": {
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"inbox_id": 4,
"priority": 10,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"graph": {
"nodes": [
{
"id": "start",
"type": "message",
"data": {
"text": "Hi — what can we help with today?"
}
},
{
"id": "route",
"type": "choice",
"data": {
"options": [
{
"label": "Billing",
"next": "billing"
},
{
"label": "Technical",
"next": "tech"
}
]
}
}
],
"edges": [
{
"from": "start",
"to": "route"
}
]
}
}
}
'import requests
url = "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows"
payload = { "bot_flow": {
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"inbox_id": 4,
"priority": 10,
"trigger_definition": {
"op": "all",
"conditions": [{ "type": "new_conversation" }]
},
"graph": {
"nodes": [
{
"id": "start",
"type": "message",
"data": { "text": "Hi — what can we help with today?" }
},
{
"id": "route",
"type": "choice",
"data": { "options": [
{
"label": "Billing",
"next": "billing"
},
{
"label": "Technical",
"next": "tech"
}
] }
}
],
"edges": [
{
"from": "start",
"to": "route"
}
]
}
} }
headers = {
"api_access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_access_token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bot_flow: {
name: 'Docs example flow',
slug: 'docs-example-flow',
description: 'A two-step triage flow used in the API reference.',
bot_name: 'Tied Assistant',
inbox_id: 4,
priority: 10,
trigger_definition: {op: 'all', conditions: [{type: 'new_conversation'}]},
graph: {
nodes: [
{
id: 'start',
type: 'message',
data: {text: 'Hi — what can we help with today?'}
},
{
id: 'route',
type: 'choice',
data: {
options: [{label: 'Billing', next: 'billing'}, {label: 'Technical', next: 'tech'}]
}
}
],
edges: [{from: 'start', to: 'route'}]
}
}
})
};
fetch('https://app.tied.com/api/v1/accounts/{account_id}/bot_flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));require 'uri'
require 'net/http'
url = URI("https://app.tied.com/api/v1/accounts/{account_id}/bot_flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bot_flow\": {\n \"name\": \"Docs example flow\",\n \"slug\": \"docs-example-flow\",\n \"description\": \"A two-step triage flow used in the API reference.\",\n \"bot_name\": \"Tied Assistant\",\n \"inbox_id\": 4,\n \"priority\": 10,\n \"trigger_definition\": {\n \"op\": \"all\",\n \"conditions\": [\n {\n \"type\": \"new_conversation\"\n }\n ]\n },\n \"graph\": {\n \"nodes\": [\n {\n \"id\": \"start\",\n \"type\": \"message\",\n \"data\": {\n \"text\": \"Hi — what can we help with today?\"\n }\n },\n {\n \"id\": \"route\",\n \"type\": \"choice\",\n \"data\": {\n \"options\": [\n {\n \"label\": \"Billing\",\n \"next\": \"billing\"\n },\n {\n \"label\": \"Technical\",\n \"next\": \"tech\"\n }\n ]\n }\n }\n ],\n \"edges\": [\n {\n \"from\": \"start\",\n \"to\": \"route\"\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_bodypackage main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows"
payload := strings.NewReader("{\n \"bot_flow\": {\n \"name\": \"Docs example flow\",\n \"slug\": \"docs-example-flow\",\n \"description\": \"A two-step triage flow used in the API reference.\",\n \"bot_name\": \"Tied Assistant\",\n \"inbox_id\": 4,\n \"priority\": 10,\n \"trigger_definition\": {\n \"op\": \"all\",\n \"conditions\": [\n {\n \"type\": \"new_conversation\"\n }\n ]\n },\n \"graph\": {\n \"nodes\": [\n {\n \"id\": \"start\",\n \"type\": \"message\",\n \"data\": {\n \"text\": \"Hi — what can we help with today?\"\n }\n },\n {\n \"id\": \"route\",\n \"type\": \"choice\",\n \"data\": {\n \"options\": [\n {\n \"label\": \"Billing\",\n \"next\": \"billing\"\n },\n {\n \"label\": \"Technical\",\n \"next\": \"tech\"\n }\n ]\n }\n }\n ],\n \"edges\": [\n {\n \"from\": \"start\",\n \"to\": \"route\"\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": 2,
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"bot_avatar_url": null,
"bot_greeting": null,
"status": "draft",
"priority": 10,
"inbox_id": 4,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"published_version_id": null,
"created_at": "2026-09-21T04:18:24.928Z",
"updated_at": "2026-09-21T04:18:24.928Z",
"versions": [
{
"id": 4,
"version_number": 1,
"label": "Initial draft",
"graph": {
"edges": [
{
"to": "route",
"from": "start"
}
],
"nodes": [
{
"id": "start",
"data": {
"text": "Hi — what can we help with today?"
},
"type": "message"
},
{
"id": "route",
"data": {
"options": [
{
"next": "billing",
"label": "Billing"
},
{
"next": "tech",
"label": "Technical"
}
]
},
"type": "choice"
}
]
},
"created_by_id": 1,
"created_at": "2026-09-21T04:18:24.937Z"
}
],
"latest_version": {
"id": 4,
"version_number": 1,
"label": "Initial draft",
"graph": {
"edges": [
{
"to": "route",
"from": "start"
}
],
"nodes": [
{
"id": "start",
"data": {
"text": "Hi — what can we help with today?"
},
"type": "message"
},
{
"id": "route",
"data": {
"options": [
{
"next": "billing",
"label": "Billing"
},
{
"next": "tech",
"label": "Technical"
}
]
},
"type": "choice"
}
]
},
"created_by_id": 1,
"created_at": "2026-09-21T04:18:24.937Z"
}
}{
"error": "Resource could not be found"
}{
"message": "Url has already been taken",
"attributes": [
"url"
]
}Authorizations
This token can be obtained by visiting the profile page or via rails console. Provides access to endpoints based on the user permissions levels. This token can be saved by an external system when user is created via API, to perform activities on behalf of the user.
Path Parameters
The numeric ID of the account
Body
The flow to create or update.
Show child attributes
Show child attributes
Response
Success
The numeric ID of the flow.
The flow name.
Generated from the name when you do not send one. Unique within the account.
Internal description.
The name the bot uses when it speaks to a contact.
Avatar shown beside the bot's messages.
Opening line, if the flow uses one.
Only a published flow runs against live conversations.
draft, published, archived Higher wins when several flows match the same conversation.
The inbox the flow runs in.
When the flow fires, as {"op": "all", "conditions": [...]}. Required, and must be an object.
The version currently live. Null until the flow is published.
Present on the list response: the newest version, which is not necessarily the published one.
Present on single-flow responses: every version, newest first.
Show child attributes
Show child attributes
ISO-8601 timestamp.
ISO-8601 timestamp.
Was this page helpful?
curl --request POST \
--url https://app.tied.com/api/v1/accounts/{account_id}/bot_flows \
--header 'Content-Type: application/json' \
--header 'api_access_token: <api-key>' \
--data '
{
"bot_flow": {
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"inbox_id": 4,
"priority": 10,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"graph": {
"nodes": [
{
"id": "start",
"type": "message",
"data": {
"text": "Hi — what can we help with today?"
}
},
{
"id": "route",
"type": "choice",
"data": {
"options": [
{
"label": "Billing",
"next": "billing"
},
{
"label": "Technical",
"next": "tech"
}
]
}
}
],
"edges": [
{
"from": "start",
"to": "route"
}
]
}
}
}
'import requests
url = "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows"
payload = { "bot_flow": {
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"inbox_id": 4,
"priority": 10,
"trigger_definition": {
"op": "all",
"conditions": [{ "type": "new_conversation" }]
},
"graph": {
"nodes": [
{
"id": "start",
"type": "message",
"data": { "text": "Hi — what can we help with today?" }
},
{
"id": "route",
"type": "choice",
"data": { "options": [
{
"label": "Billing",
"next": "billing"
},
{
"label": "Technical",
"next": "tech"
}
] }
}
],
"edges": [
{
"from": "start",
"to": "route"
}
]
}
} }
headers = {
"api_access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {api_access_token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bot_flow: {
name: 'Docs example flow',
slug: 'docs-example-flow',
description: 'A two-step triage flow used in the API reference.',
bot_name: 'Tied Assistant',
inbox_id: 4,
priority: 10,
trigger_definition: {op: 'all', conditions: [{type: 'new_conversation'}]},
graph: {
nodes: [
{
id: 'start',
type: 'message',
data: {text: 'Hi — what can we help with today?'}
},
{
id: 'route',
type: 'choice',
data: {
options: [{label: 'Billing', next: 'billing'}, {label: 'Technical', next: 'tech'}]
}
}
],
edges: [{from: 'start', to: 'route'}]
}
}
})
};
fetch('https://app.tied.com/api/v1/accounts/{account_id}/bot_flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));require 'uri'
require 'net/http'
url = URI("https://app.tied.com/api/v1/accounts/{account_id}/bot_flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["api_access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bot_flow\": {\n \"name\": \"Docs example flow\",\n \"slug\": \"docs-example-flow\",\n \"description\": \"A two-step triage flow used in the API reference.\",\n \"bot_name\": \"Tied Assistant\",\n \"inbox_id\": 4,\n \"priority\": 10,\n \"trigger_definition\": {\n \"op\": \"all\",\n \"conditions\": [\n {\n \"type\": \"new_conversation\"\n }\n ]\n },\n \"graph\": {\n \"nodes\": [\n {\n \"id\": \"start\",\n \"type\": \"message\",\n \"data\": {\n \"text\": \"Hi — what can we help with today?\"\n }\n },\n {\n \"id\": \"route\",\n \"type\": \"choice\",\n \"data\": {\n \"options\": [\n {\n \"label\": \"Billing\",\n \"next\": \"billing\"\n },\n {\n \"label\": \"Technical\",\n \"next\": \"tech\"\n }\n ]\n }\n }\n ],\n \"edges\": [\n {\n \"from\": \"start\",\n \"to\": \"route\"\n }\n ]\n }\n }\n}"
response = http.request(request)
puts response.read_bodypackage main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows"
payload := strings.NewReader("{\n \"bot_flow\": {\n \"name\": \"Docs example flow\",\n \"slug\": \"docs-example-flow\",\n \"description\": \"A two-step triage flow used in the API reference.\",\n \"bot_name\": \"Tied Assistant\",\n \"inbox_id\": 4,\n \"priority\": 10,\n \"trigger_definition\": {\n \"op\": \"all\",\n \"conditions\": [\n {\n \"type\": \"new_conversation\"\n }\n ]\n },\n \"graph\": {\n \"nodes\": [\n {\n \"id\": \"start\",\n \"type\": \"message\",\n \"data\": {\n \"text\": \"Hi — what can we help with today?\"\n }\n },\n {\n \"id\": \"route\",\n \"type\": \"choice\",\n \"data\": {\n \"options\": [\n {\n \"label\": \"Billing\",\n \"next\": \"billing\"\n },\n {\n \"label\": \"Technical\",\n \"next\": \"tech\"\n }\n ]\n }\n }\n ],\n \"edges\": [\n {\n \"from\": \"start\",\n \"to\": \"route\"\n }\n ]\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("api_access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": 2,
"name": "Docs example flow",
"slug": "docs-example-flow",
"description": "A two-step triage flow used in the API reference.",
"bot_name": "Tied Assistant",
"bot_avatar_url": null,
"bot_greeting": null,
"status": "draft",
"priority": 10,
"inbox_id": 4,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"published_version_id": null,
"created_at": "2026-09-21T04:18:24.928Z",
"updated_at": "2026-09-21T04:18:24.928Z",
"versions": [
{
"id": 4,
"version_number": 1,
"label": "Initial draft",
"graph": {
"edges": [
{
"to": "route",
"from": "start"
}
],
"nodes": [
{
"id": "start",
"data": {
"text": "Hi — what can we help with today?"
},
"type": "message"
},
{
"id": "route",
"data": {
"options": [
{
"next": "billing",
"label": "Billing"
},
{
"next": "tech",
"label": "Technical"
}
]
},
"type": "choice"
}
]
},
"created_by_id": 1,
"created_at": "2026-09-21T04:18:24.937Z"
}
],
"latest_version": {
"id": 4,
"version_number": 1,
"label": "Initial draft",
"graph": {
"edges": [
{
"to": "route",
"from": "start"
}
],
"nodes": [
{
"id": "start",
"data": {
"text": "Hi — what can we help with today?"
},
"type": "message"
},
{
"id": "route",
"data": {
"options": [
{
"next": "billing",
"label": "Billing"
},
{
"next": "tech",
"label": "Technical"
}
]
},
"type": "choice"
}
]
},
"created_by_id": 1,
"created_at": "2026-09-21T04:18:24.937Z"
}
}{
"error": "Resource could not be found"
}{
"message": "Url has already been taken",
"attributes": [
"url"
]
}