Publish a bot flow
Saves the graph you send as a new version and makes that version live.
Note the direction: publish does not promote the latest saved version, it creates one from the request body — so graph is required. Add a label to make the version history readable. Administrator only.
curl --request POST \
--url https://app.tied.com/api/v1/accounts/{account_id}/bot_flows/{id}/publish \
--header 'Content-Type: application/json' \
--header 'api_access_token: <api-key>' \
--data '
{
"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"
}
]
},
"label": "First published version"
}
'import requests
url = "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows/{id}/publish"
payload = {
"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"
}
]
},
"label": "First published version"
}
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({
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'}]
},
label: 'First published version'
})
};
fetch('https://app.tied.com/api/v1/accounts/{account_id}/bot_flows/{id}/publish', 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/{id}/publish")
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 \"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 \"label\": \"First published version\"\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/{id}/publish"
payload := strings.NewReader("{\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 \"label\": \"First published version\"\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. Updating never publishes.",
"bot_name": "Tied Assistant",
"bot_avatar_url": null,
"bot_greeting": null,
"status": "published",
"priority": 10,
"inbox_id": 4,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"published_version_id": 5,
"created_at": "2026-09-21T04:18:24.928Z",
"updated_at": "2026-09-21T04:18:24.982Z",
"versions": [
{
"id": 5,
"version_number": 2,
"label": "First published version",
"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.976Z"
},
{
"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": 5,
"version_number": 2,
"label": "First published version",
"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.976Z"
}
}{
"error": "Resource could not be found"
}{
"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 bot flow.
1
Body
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/{id}/publish \
--header 'Content-Type: application/json' \
--header 'api_access_token: <api-key>' \
--data '
{
"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"
}
]
},
"label": "First published version"
}
'import requests
url = "https://app.tied.com/api/v1/accounts/{account_id}/bot_flows/{id}/publish"
payload = {
"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"
}
]
},
"label": "First published version"
}
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({
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'}]
},
label: 'First published version'
})
};
fetch('https://app.tied.com/api/v1/accounts/{account_id}/bot_flows/{id}/publish', 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/{id}/publish")
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 \"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 \"label\": \"First published version\"\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/{id}/publish"
payload := strings.NewReader("{\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 \"label\": \"First published version\"\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. Updating never publishes.",
"bot_name": "Tied Assistant",
"bot_avatar_url": null,
"bot_greeting": null,
"status": "published",
"priority": 10,
"inbox_id": 4,
"trigger_definition": {
"op": "all",
"conditions": [
{
"type": "new_conversation"
}
]
},
"published_version_id": 5,
"created_at": "2026-09-21T04:18:24.928Z",
"updated_at": "2026-09-21T04:18:24.982Z",
"versions": [
{
"id": 5,
"version_number": 2,
"label": "First published version",
"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.976Z"
},
{
"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": 5,
"version_number": 2,
"label": "First published version",
"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.976Z"
}
}{
"error": "Resource could not be found"
}{
"error": "Resource could not be found"
}{
"message": "Url has already been taken",
"attributes": [
"url"
]
}