Create flow
Creates a flow. With no spec/nodes it starts a draft with one default start node. Supply spec (flow-spec DSL, see GET /v1/schemas/flow-spec) or a raw nodes/edges graph to seed the draft in the same call — node position/measured, node ids, and edge ids/handles are all generated server-side (a raw node’s id is only a request-scoped token for wiring edges; the response’s nodeIds maps each authored id to its persisted id). Add publish: true to validate the graph exactly like flows.publish and create the flow’s first version immediately. Use flows.list to inspect existing flows first.
curl --request POST \
--url https://app.chatbotx.io/api/v1/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"folderId": "<string>",
"name": "<string>",
"nodes": [
{
"id": "<string>"
}
],
"edges": [
{
"source": "<string>",
"target": "<string>",
"id": "<string>",
"sourceHandle": "<string>",
"targetHandle": "<string>"
}
],
"publish": true
}
'import requests
url = "https://app.chatbotx.io/api/v1/flows"
payload = {
"folderId": "<string>",
"name": "<string>",
"nodes": [{ "id": "<string>" }],
"edges": [
{
"source": "<string>",
"target": "<string>",
"id": "<string>",
"sourceHandle": "<string>",
"targetHandle": "<string>"
}
],
"publish": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
folderId: '<string>',
name: '<string>',
nodes: [{id: '<string>'}],
edges: [
{
source: '<string>',
target: '<string>',
id: '<string>',
sourceHandle: '<string>',
targetHandle: '<string>'
}
],
publish: true
})
};
fetch('https://app.chatbotx.io/api/v1/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.chatbotx.io/api/v1/flows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'folderId' => '<string>',
'name' => '<string>',
'nodes' => [
[
'id' => '<string>'
]
],
'edges' => [
[
'source' => '<string>',
'target' => '<string>',
'id' => '<string>',
'sourceHandle' => '<string>',
'targetHandle' => '<string>'
]
],
'publish' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.chatbotx.io/api/v1/flows"
payload := strings.NewReader("{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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))
}HttpResponse<String> response = Unirest.post("https://app.chatbotx.io/api/v1/flows")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.chatbotx.io/api/v1/flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"nodeIds": {}
}{
"defined": true,
"code": "businessError",
"status": 400,
"message": "An error occurred while processing your request",
"data": "<unknown>"
}{
"defined": true,
"code": "UNAUTHORIZED",
"status": 401,
"message": "Authentication required",
"data": "<unknown>"
}{
"defined": true,
"code": "FORBIDDEN",
"status": 403,
"message": "You do not have permission to perform this action",
"data": "<unknown>"
}{
"defined": true,
"code": "invalidRequestData",
"status": 422,
"message": "Input validation failed",
"data": {
"issues": [
{
"message": "<string>",
"path": [
"<string>"
]
}
]
}
}{
"defined": true,
"code": "tooManyRequests",
"status": 429,
"message": "Too many requests",
"data": "<unknown>"
}{
"defined": true,
"code": "INTERNAL_SERVER_ERROR",
"status": 500,
"message": "An unexpected error occurred",
"data": "<unknown>"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Folder id (numeric string) to create the flow in, or null for no folder.
^\d+$Flow name.
1 - 255Flow-spec DSL document compiled server-side into the draft's nodes/edges (see GET /v1/schemas/flow-spec). Mutually exclusive with nodes/edges.
Show child attributes
Show child attributes
Raw node graph. position/measured are optional — omitted positions are laid out automatically — and each node's id is a request-scoped token for wiring edges, remapped to a real persisted id server-side. Mutually exclusive with spec.
1Show child attributes
Show child attributes
Edges between nodes. Requires nodes.
Show child attributes
Show child attributes
Validate the supplied graph exactly like flows.publish and create the flow's first version immediately. Requires spec or nodes.
Was this page helpful?
curl --request POST \
--url https://app.chatbotx.io/api/v1/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"folderId": "<string>",
"name": "<string>",
"nodes": [
{
"id": "<string>"
}
],
"edges": [
{
"source": "<string>",
"target": "<string>",
"id": "<string>",
"sourceHandle": "<string>",
"targetHandle": "<string>"
}
],
"publish": true
}
'import requests
url = "https://app.chatbotx.io/api/v1/flows"
payload = {
"folderId": "<string>",
"name": "<string>",
"nodes": [{ "id": "<string>" }],
"edges": [
{
"source": "<string>",
"target": "<string>",
"id": "<string>",
"sourceHandle": "<string>",
"targetHandle": "<string>"
}
],
"publish": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
folderId: '<string>',
name: '<string>',
nodes: [{id: '<string>'}],
edges: [
{
source: '<string>',
target: '<string>',
id: '<string>',
sourceHandle: '<string>',
targetHandle: '<string>'
}
],
publish: true
})
};
fetch('https://app.chatbotx.io/api/v1/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.chatbotx.io/api/v1/flows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'folderId' => '<string>',
'name' => '<string>',
'nodes' => [
[
'id' => '<string>'
]
],
'edges' => [
[
'source' => '<string>',
'target' => '<string>',
'id' => '<string>',
'sourceHandle' => '<string>',
'targetHandle' => '<string>'
]
],
'publish' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.chatbotx.io/api/v1/flows"
payload := strings.NewReader("{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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))
}HttpResponse<String> response = Unirest.post("https://app.chatbotx.io/api/v1/flows")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.chatbotx.io/api/v1/flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"folderId\": \"<string>\",\n \"name\": \"<string>\",\n \"nodes\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"edges\": [\n {\n \"source\": \"<string>\",\n \"target\": \"<string>\",\n \"id\": \"<string>\",\n \"sourceHandle\": \"<string>\",\n \"targetHandle\": \"<string>\"\n }\n ],\n \"publish\": true\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"nodeIds": {}
}{
"defined": true,
"code": "businessError",
"status": 400,
"message": "An error occurred while processing your request",
"data": "<unknown>"
}{
"defined": true,
"code": "UNAUTHORIZED",
"status": 401,
"message": "Authentication required",
"data": "<unknown>"
}{
"defined": true,
"code": "FORBIDDEN",
"status": 403,
"message": "You do not have permission to perform this action",
"data": "<unknown>"
}{
"defined": true,
"code": "invalidRequestData",
"status": 422,
"message": "Input validation failed",
"data": {
"issues": [
{
"message": "<string>",
"path": [
"<string>"
]
}
]
}
}{
"defined": true,
"code": "tooManyRequests",
"status": 429,
"message": "Too many requests",
"data": "<unknown>"
}{
"defined": true,
"code": "INTERNAL_SERVER_ERROR",
"status": 500,
"message": "An unexpected error occurred",
"data": "<unknown>"
}