Stream Pathway Migration
curl --request POST \
--url https://api.bland.ai/v2/agents/migrate/stream \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"pathway": {},
"name": "<string>",
"create": true
}
'import requests
url = "https://api.bland.ai/v2/agents/migrate/stream"
payload = {
"pathway": {},
"name": "<string>",
"create": True
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({pathway: {}, name: '<string>', create: true})
};
fetch('https://api.bland.ai/v2/agents/migrate/stream', 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://api.bland.ai/v2/agents/migrate/stream",
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([
'pathway' => [
],
'name' => '<string>',
'create' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <authorization>"
],
]);
$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://api.bland.ai/v2/agents/migrate/stream"
payload := strings.NewReader("{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<authorization>")
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://api.bland.ai/v2/agents/migrate/stream")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/migrate/stream")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}"
response = http.request(request)
puts response.read_bodydata: {"type":"start","pathway":"Front desk booking","nodes":2,"edges":1}
data: {"type":"read_reference","name":"inversion-rules"}
data: {"type":"read_nodes","ids":["73a855b4-7257-4c6e-bd7d-f151a763c9fa","ddc0765a-8086-4826-bfaf-77b889fb3022"]}
: ping
data: {"type":"iteration","iteration":1,"stopReason":"tool_use","outputTokens":1420,"toolCalls":["read_reference","read_nodes"]}
: ping
data: {"type":"plan_submitted","scenarios":1,"endCalls":0,"openQuestions":0}
data: {"type":"materializing"}
data: {"type":"iteration","iteration":2,"stopReason":"end_turn","outputTokens":4700,"toolCalls":["submit_migration_plan"]}
data: {"type":"done","status":200,"data":{"plan":{"displayName":"Front desk","hubPrompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","scenarios":[{"kind":"simple","name":"Book appointment","entry":{"mode":"llm","label":"Wants to book"},"ruleParts":[{"legacyPromptOf":"73a855b4-7257-4c6e-bd7d-f151a763c9fa"}]}],"endCalls":[],"report":{"architectureSummary":"A two-node booking pathway collapsed into one hub and one booking scenario.","dispositions":[{"nodeIds":["73a855b4-7257-4c6e-bd7d-f151a763c9fa"],"disposition":"Became scenario \"Book appointment\"","rationale":"Single dialogue step."},{"nodeIds":["ddc0765a-8086-4826-bfaf-77b889fb3022"],"disposition":"Merged into the hub prompt","rationale":"Greeting-only node."}],"droppedOrApproximated":[],"openQuestions":[]}},"snapshot":{"behavior":{"nodes":[{"id":"inbound","type":"inbound","position":{"x":360,"y":-180},"data":{"number":""}},{"id":"agent","type":"agent","position":{"x":192,"y":0},"data":{"prompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","loopWhile":"","variables":[]}},{"id":"545fe342-06be-4151-aae2-bd10bf128464","type":"scenario","position":{"x":0,"y":260},"data":{"name":"Book appointment","rule":"Ask which day and time works for the caller, then confirm the appointment back to them.","target":{"kind":"dialogue","label":"Book appointment"},"loopWhile":"","variables":[],"entry":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}}],"edges":[{"id":"e-inbound-agent","source":"inbound","target":"agent"},{"id":"e-agent-book","source":"agent","target":"545fe342-06be-4151-aae2-bd10bf128464","data":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}]},"settings":{"displayName":"Front desk","systemPrompt":"You are the front desk assistant for a dental office.","voice":"","languages":["english"],"enableMemory":false,"interruptionSensitivity":350,"backgroundNoise":"off"},"contact":{"inboundNumbers":[]}},"lint":{"errors":[],"warnings":[]},"usage":{"inputTokens":48211,"outputTokens":6120,"iterations":2},"created":false},"errors":null}
{
"data": null,
"errors": [
{
"error": "PATHWAY_TOO_LARGE",
"message": "pathway exceeds 500 nodes / 2000 edges"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many pathway migrations started for this organization — please wait before starting another."
}
]
}
Migration
Stream Pathway Migration
Run a pathway migration with live progress events.
POST
/
v2
/
agents
/
migrate
/
stream
Stream Pathway Migration
curl --request POST \
--url https://api.bland.ai/v2/agents/migrate/stream \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"pathway": {},
"name": "<string>",
"create": true
}
'import requests
url = "https://api.bland.ai/v2/agents/migrate/stream"
payload = {
"pathway": {},
"name": "<string>",
"create": True
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({pathway: {}, name: '<string>', create: true})
};
fetch('https://api.bland.ai/v2/agents/migrate/stream', 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://api.bland.ai/v2/agents/migrate/stream",
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([
'pathway' => [
],
'name' => '<string>',
'create' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <authorization>"
],
]);
$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://api.bland.ai/v2/agents/migrate/stream"
payload := strings.NewReader("{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<authorization>")
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://api.bland.ai/v2/agents/migrate/stream")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/migrate/stream")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"pathway\": {},\n \"name\": \"<string>\",\n \"create\": true\n}"
response = http.request(request)
puts response.read_bodydata: {"type":"start","pathway":"Front desk booking","nodes":2,"edges":1}
data: {"type":"read_reference","name":"inversion-rules"}
data: {"type":"read_nodes","ids":["73a855b4-7257-4c6e-bd7d-f151a763c9fa","ddc0765a-8086-4826-bfaf-77b889fb3022"]}
: ping
data: {"type":"iteration","iteration":1,"stopReason":"tool_use","outputTokens":1420,"toolCalls":["read_reference","read_nodes"]}
: ping
data: {"type":"plan_submitted","scenarios":1,"endCalls":0,"openQuestions":0}
data: {"type":"materializing"}
data: {"type":"iteration","iteration":2,"stopReason":"end_turn","outputTokens":4700,"toolCalls":["submit_migration_plan"]}
data: {"type":"done","status":200,"data":{"plan":{"displayName":"Front desk","hubPrompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","scenarios":[{"kind":"simple","name":"Book appointment","entry":{"mode":"llm","label":"Wants to book"},"ruleParts":[{"legacyPromptOf":"73a855b4-7257-4c6e-bd7d-f151a763c9fa"}]}],"endCalls":[],"report":{"architectureSummary":"A two-node booking pathway collapsed into one hub and one booking scenario.","dispositions":[{"nodeIds":["73a855b4-7257-4c6e-bd7d-f151a763c9fa"],"disposition":"Became scenario \"Book appointment\"","rationale":"Single dialogue step."},{"nodeIds":["ddc0765a-8086-4826-bfaf-77b889fb3022"],"disposition":"Merged into the hub prompt","rationale":"Greeting-only node."}],"droppedOrApproximated":[],"openQuestions":[]}},"snapshot":{"behavior":{"nodes":[{"id":"inbound","type":"inbound","position":{"x":360,"y":-180},"data":{"number":""}},{"id":"agent","type":"agent","position":{"x":192,"y":0},"data":{"prompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","loopWhile":"","variables":[]}},{"id":"545fe342-06be-4151-aae2-bd10bf128464","type":"scenario","position":{"x":0,"y":260},"data":{"name":"Book appointment","rule":"Ask which day and time works for the caller, then confirm the appointment back to them.","target":{"kind":"dialogue","label":"Book appointment"},"loopWhile":"","variables":[],"entry":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}}],"edges":[{"id":"e-inbound-agent","source":"inbound","target":"agent"},{"id":"e-agent-book","source":"agent","target":"545fe342-06be-4151-aae2-bd10bf128464","data":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}]},"settings":{"displayName":"Front desk","systemPrompt":"You are the front desk assistant for a dental office.","voice":"","languages":["english"],"enableMemory":false,"interruptionSensitivity":350,"backgroundNoise":"off"},"contact":{"inboundNumbers":[]}},"lint":{"errors":[],"warnings":[]},"usage":{"inputTokens":48211,"outputTokens":6120,"iterations":2},"created":false},"errors":null}
{
"data": null,
"errors": [
{
"error": "PATHWAY_TOO_LARGE",
"message": "pathway exceeds 500 nodes / 2000 edges"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many pathway migrations started for this organization — please wait before starting another."
}
]
}
Overview
Runs the same migration as Migrate Pathway with the same body and the same outcome, but delivers it as a Server-Sent Events stream so you can show progress during the multi-minute planner run. The finaldone event carries exactly the status, data, and errors the JSON endpoint would have returned. If you disconnect before the run finishes, the planner is aborted and nothing is created.
Limited to 10 migration starts per hour per organization, counted together with Migrate Pathway and Start Pathway Translation. Requires an admin, owner, operator, or prompter role.
Headers
string
required
Your API key for authentication.
Body Parameters
object
required
The legacy pathway graph, in the shape the pathway editor exports:
nodes (required, non-empty array), edges (required array, may be empty), and optional name and globalPrompt. Returns 400 INVALID_PATHWAY if nodes or edges is missing or nodes is empty, and 400 PATHWAY_TOO_LARGE beyond 500 nodes, 2,000 edges, or 2 MB serialized. See Migrate Pathway for field details.string
Display name for the new agent when
create is true. Defaults to <pathway.name> (migrated), or unnamed pathway (migrated) when the pathway has no name.boolean
default:"false"
When
true, the migrated snapshot is saved as a new agent with its first version. Any other value is treated as false (dry run).Response
Body validation and the rate limit are checked before the stream opens, so those failures arrive as ordinary JSON responses (400 or 429). Once accepted, the response is 200 with Content-Type: text/event-stream, Cache-Control: no-cache, no-transform, and Connection: keep-alive. Each event is a single data: line holding a JSON object whose type field identifies it; no event: names are used. A comment line : ping is sent every 10 seconds as a heartbeat and should be ignored. The stream closes after the done or error event.
string
Present on every event. One of
start, read_reference, read_nodes, iteration, plan_submitted, materializing, done, error.event
event
The planner consulted one of its internal reference documents.
name (string) identifies the document.event
The planner read the full content of specific legacy nodes.
ids (array of strings) lists their IDs.event
One planner turn finished. Turns can be one to three minutes apart.
event
The planner submitted a plan. Carries
scenarios, endCalls, and openQuestions (integers). A rejected plan is repaired and resubmitted within the same run, so this can fire more than once.event
The plan is being turned into an agent snapshot. No other fields.
event
The run finished. Emitted once, then the stream closes.
Show done payload
Show done payload
integer
The HTTP status Migrate Pathway would have returned:
200 (dry run), 201 (agent created), 422 (validation, lint, or create blocked), or 500.object
The same
data object as Migrate Pathway: plan, snapshot, lint, usage, created, and in create mode agent and version. Unlike the JSON endpoint, a 422 here still includes the partial data (at minimum plan, lint, and usage) so you can inspect what failed.null | array
null when status is 200 or 201, otherwise the error list.event
The planner itself failed.
message (string) is safe to show to users. The stream closes after it.null | array
null on success, or a list of error objects if the request failed.data: {"type":"start","pathway":"Front desk booking","nodes":2,"edges":1}
data: {"type":"read_reference","name":"inversion-rules"}
data: {"type":"read_nodes","ids":["73a855b4-7257-4c6e-bd7d-f151a763c9fa","ddc0765a-8086-4826-bfaf-77b889fb3022"]}
: ping
data: {"type":"iteration","iteration":1,"stopReason":"tool_use","outputTokens":1420,"toolCalls":["read_reference","read_nodes"]}
: ping
data: {"type":"plan_submitted","scenarios":1,"endCalls":0,"openQuestions":0}
data: {"type":"materializing"}
data: {"type":"iteration","iteration":2,"stopReason":"end_turn","outputTokens":4700,"toolCalls":["submit_migration_plan"]}
data: {"type":"done","status":200,"data":{"plan":{"displayName":"Front desk","hubPrompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","scenarios":[{"kind":"simple","name":"Book appointment","entry":{"mode":"llm","label":"Wants to book"},"ruleParts":[{"legacyPromptOf":"73a855b4-7257-4c6e-bd7d-f151a763c9fa"}]}],"endCalls":[],"report":{"architectureSummary":"A two-node booking pathway collapsed into one hub and one booking scenario.","dispositions":[{"nodeIds":["73a855b4-7257-4c6e-bd7d-f151a763c9fa"],"disposition":"Became scenario \"Book appointment\"","rationale":"Single dialogue step."},{"nodeIds":["ddc0765a-8086-4826-bfaf-77b889fb3022"],"disposition":"Merged into the hub prompt","rationale":"Greeting-only node."}],"droppedOrApproximated":[],"openQuestions":[]}},"snapshot":{"behavior":{"nodes":[{"id":"inbound","type":"inbound","position":{"x":360,"y":-180},"data":{"number":""}},{"id":"agent","type":"agent","position":{"x":192,"y":0},"data":{"prompt":"Greet the caller and find out what they need.\n\n## Routing\n\n- \"Book appointment\": the caller wants to schedule a visit","loopWhile":"","variables":[]}},{"id":"545fe342-06be-4151-aae2-bd10bf128464","type":"scenario","position":{"x":0,"y":260},"data":{"name":"Book appointment","rule":"Ask which day and time works for the caller, then confirm the appointment back to them.","target":{"kind":"dialogue","label":"Book appointment"},"loopWhile":"","variables":[],"entry":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}}],"edges":[{"id":"e-inbound-agent","source":"inbound","target":"agent"},{"id":"e-agent-book","source":"agent","target":"545fe342-06be-4151-aae2-bd10bf128464","data":{"mode":"llm","label":"Wants to book","description":"","alwaysPick":false,"conditions":[]}}]},"settings":{"displayName":"Front desk","systemPrompt":"You are the front desk assistant for a dental office.","voice":"","languages":["english"],"enableMemory":false,"interruptionSensitivity":350,"backgroundNoise":"off"},"contact":{"inboundNumbers":[]}},"lint":{"errors":[],"warnings":[]},"usage":{"inputTokens":48211,"outputTokens":6120,"iterations":2},"created":false},"errors":null}
{
"data": null,
"errors": [
{
"error": "PATHWAY_TOO_LARGE",
"message": "pathway exceeds 500 nodes / 2000 edges"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many pathway migrations started for this organization — please wait before starting another."
}
]
}
Docs for agents: llms.txt
Was this page helpful?