Publish Disposition
curl --request POST \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"expectedDraftRevision": 123,
"estimateId": "<string>",
"acknowledgeEstimate": true
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish"
payload = {
"expectedDraftRevision": 123,
"estimateId": "<string>",
"acknowledgeEstimate": 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({expectedDraftRevision: 123, estimateId: '<string>', acknowledgeEstimate: true})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish', 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/{agent_id}/dispositions/{disposition_id}/publish",
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([
'expectedDraftRevision' => 123,
'estimateId' => '<string>',
'acknowledgeEstimate' => 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/{agent_id}/dispositions/{disposition_id}/publish"
payload := strings.NewReader("{\n \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": 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/{agent_id}/dispositions/{disposition_id}/publish")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish")
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 \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "6168a24b-1863-422b-bbec-ed6d38395c41",
"dispositionId": "1b179d4d-8830-43bd-b095-632f23bc4c57",
"versionNumber": 2,
"definition": {
"name": "Appointment outcome",
"description": "Did the caller book an appointment?",
"timing": "immediate",
"values": [
{
"id": "03bcc986-0183-4449-b9a6-a98b914edb72",
"key": "booked",
"label": "Appointment booked",
"schema": { "kind": "boolean" },
"source": {
"kind": "judge",
"judgeId": "dee902eb-e05c-46d3-8a33-0347c3871c07",
"judgeVersionId": "c2781909-2c00-46d5-a2dd-db020a0f1b1f",
"execution": { "reasoningEffort": "auto", "inputSourceIds": ["transcript"] }
}
}
],
"transformation": {
"version": 1,
"root": {
"kind": "object",
"fields": {
"booked": { "kind": "value", "valueId": "03bcc986-0183-4449-b9a6-a98b914edb72" }
}
}
},
"postCallWebhook": { "mode": "emit_followup" }
},
"publishedAt": "2026-09-10T18:40:03.512Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Definition failed validation",
"ext": "{\"problems\":[{\"valueId\":null,\"message\":\"Publish requires at least one value\"}]}"
}
]
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Acknowledge the estimated recurring cost before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Pricing estimate changed — review the latest estimate before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Draft revision moved (expected 3) — re-estimate and publish again"
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition not found"
}
]
}
Dispositions
Publish Disposition
Publish a disposition draft as an immutable version.
POST
/
v2
/
agents
/
{agent_id}
/
dispositions
/
{disposition_id}
/
publish
Publish Disposition
curl --request POST \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"expectedDraftRevision": 123,
"estimateId": "<string>",
"acknowledgeEstimate": true
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish"
payload = {
"expectedDraftRevision": 123,
"estimateId": "<string>",
"acknowledgeEstimate": 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({expectedDraftRevision: 123, estimateId: '<string>', acknowledgeEstimate: true})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish', 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/{agent_id}/dispositions/{disposition_id}/publish",
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([
'expectedDraftRevision' => 123,
'estimateId' => '<string>',
'acknowledgeEstimate' => 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/{agent_id}/dispositions/{disposition_id}/publish"
payload := strings.NewReader("{\n \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": 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/{agent_id}/dispositions/{disposition_id}/publish")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/publish")
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 \"expectedDraftRevision\": 123,\n \"estimateId\": \"<string>\",\n \"acknowledgeEstimate\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "6168a24b-1863-422b-bbec-ed6d38395c41",
"dispositionId": "1b179d4d-8830-43bd-b095-632f23bc4c57",
"versionNumber": 2,
"definition": {
"name": "Appointment outcome",
"description": "Did the caller book an appointment?",
"timing": "immediate",
"values": [
{
"id": "03bcc986-0183-4449-b9a6-a98b914edb72",
"key": "booked",
"label": "Appointment booked",
"schema": { "kind": "boolean" },
"source": {
"kind": "judge",
"judgeId": "dee902eb-e05c-46d3-8a33-0347c3871c07",
"judgeVersionId": "c2781909-2c00-46d5-a2dd-db020a0f1b1f",
"execution": { "reasoningEffort": "auto", "inputSourceIds": ["transcript"] }
}
}
],
"transformation": {
"version": 1,
"root": {
"kind": "object",
"fields": {
"booked": { "kind": "value", "valueId": "03bcc986-0183-4449-b9a6-a98b914edb72" }
}
}
},
"postCallWebhook": { "mode": "emit_followup" }
},
"publishedAt": "2026-09-10T18:40:03.512Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Definition failed validation",
"ext": "{\"problems\":[{\"valueId\":null,\"message\":\"Publish requires at least one value\"}]}"
}
]
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Acknowledge the estimated recurring cost before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Pricing estimate changed — review the latest estimate before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Draft revision moved (expected 3) — re-estimate and publish again"
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition not found"
}
]
}
Overview
Dispositions are enabled per organization. If your organization does not have access, these endpoints return
404.publishedVersionId at it, and sets state to enabled so the disposition runs on every new completed call. Publishing validates strictly: every value must pin a published judge or extractor version, and the definition must have at least one value. Call Estimate Disposition Cost first and pass its id; publish recomputes the estimate and refuses if anything moved. Undo with Disable Disposition.
Requires an admin, owner, operator, or prompter role.
Headers
string
required
Your API key for authentication.
Path Parameters
string
required
The agent’s unique identifier. Must be a UUID; otherwise returns
400 with the message agentId must be a valid UUID. Returns 404 Agent not found if the agent is not in your organization.string
required
The disposition’s unique identifier. Must be a UUID; otherwise returns
400 with the message dispositionId must be a valid UUID. Returns 404 Disposition not found if it does not belong to this agent.Body Parameters
Unknown fields are rejected.integer
required
The draft revision you estimated, at least
1. Returns 409 CONFLICT if the live revision differs. On success the draft revision becomes expectedDraftRevision + 1 and the draft is kept in sync with the published snapshot, so hasUnpublishedChanges reads false.string
required
The
id returned by Estimate Disposition Cost for this exact draft revision. Publish recomputes the estimate against fresh dependency reads and returns 409 CONFLICT if the id no longer matches.boolean
Must be exactly
true when the estimate’s totalUsdPerCall.expected is greater than 0.0000; omitting it in that case returns 400 BAD_REQUEST with the message Acknowledge the estimated recurring cost before publishing. Any value other than true is rejected as an invalid body. Optional when the expected cost is zero.Response
object
The newly created version.
Show version object
Show version object
string
Unique identifier for the version. It is now the disposition’s
publishedVersionId.string
The disposition this version belongs to.
number
Sequential number, one higher than the previous version, or
1 for a first publish.object
The frozen definition this version executes.
structured_extraction sources carry the server-written frozen copy of the extractor prompt, output schema, and inference configuration.string
ISO 8601 timestamp of publication.
null | array
null on success, or a list of error objects if the request failed.{
"data": {
"id": "6168a24b-1863-422b-bbec-ed6d38395c41",
"dispositionId": "1b179d4d-8830-43bd-b095-632f23bc4c57",
"versionNumber": 2,
"definition": {
"name": "Appointment outcome",
"description": "Did the caller book an appointment?",
"timing": "immediate",
"values": [
{
"id": "03bcc986-0183-4449-b9a6-a98b914edb72",
"key": "booked",
"label": "Appointment booked",
"schema": { "kind": "boolean" },
"source": {
"kind": "judge",
"judgeId": "dee902eb-e05c-46d3-8a33-0347c3871c07",
"judgeVersionId": "c2781909-2c00-46d5-a2dd-db020a0f1b1f",
"execution": { "reasoningEffort": "auto", "inputSourceIds": ["transcript"] }
}
}
],
"transformation": {
"version": 1,
"root": {
"kind": "object",
"fields": {
"booked": { "kind": "value", "valueId": "03bcc986-0183-4449-b9a6-a98b914edb72" }
}
}
},
"postCallWebhook": { "mode": "emit_followup" }
},
"publishedAt": "2026-09-10T18:40:03.512Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Definition failed validation",
"ext": "{\"problems\":[{\"valueId\":null,\"message\":\"Publish requires at least one value\"}]}"
}
]
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Acknowledge the estimated recurring cost before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Pricing estimate changed — review the latest estimate before publishing"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Draft revision moved (expected 3) — re-estimate and publish again"
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition not found"
}
]
}
Docs for agents: llms.txt
Was this page helpful?