Align Disposition Test Run
curl --request POST \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"valueIds": [
{}
],
"instructions": "<string>"
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align"
payload = {
"valueIds": [{}],
"instructions": "<string>"
}
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({valueIds: [{}], instructions: '<string>'})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align', 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}/runs/{run_id}/align",
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([
'valueIds' => [
[
]
],
'instructions' => '<string>'
]),
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}/runs/{run_id}/align"
payload := strings.NewReader("{\n \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\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}/runs/{run_id}/align")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align")
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 \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"proposals": [
{
"valueId": "f4b706ec-43cc-4373-b4a5-a06130fddbbf",
"key": "booked",
"kind": "judge",
"changes": [
{
"field": "promptMd",
"before": "Decide whether the caller booked an appointment during this call.",
"after": "Decide whether the caller booked an appointment during this call. Treat a verbal agreement to a specific day and time as booked, even if the agent did not read back a confirmation number.",
"rationale": "Three corrections flipped the verdict from not booked to booked on calls where the caller agreed to a slot but no confirmation number was read back."
}
]
}
],
"skipped": [
{
"valueId": "d2dc9bf3-d842-44f9-8002-dea791ff0ad4",
"reason": "custom_code"
}
],
"truncatedCorrections": 0
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Aligning requires a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Correct at least one value on this run before aligning"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition align requests for this organization — please wait before requesting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition value not found in this run"
}
]
}
Test Runs
Align Disposition Test Run
Propose definition edits from a test run’s corrections.
POST
/
v2
/
agents
/
{agent_id}
/
dispositions
/
{disposition_id}
/
runs
/
{run_id}
/
align
Align Disposition Test Run
curl --request POST \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"valueIds": [
{}
],
"instructions": "<string>"
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align"
payload = {
"valueIds": [{}],
"instructions": "<string>"
}
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({valueIds: [{}], instructions: '<string>'})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align', 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}/runs/{run_id}/align",
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([
'valueIds' => [
[
]
],
'instructions' => '<string>'
]),
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}/runs/{run_id}/align"
payload := strings.NewReader("{\n \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\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}/runs/{run_id}/align")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/align")
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 \"valueIds\": [\n {}\n ],\n \"instructions\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"proposals": [
{
"valueId": "f4b706ec-43cc-4373-b4a5-a06130fddbbf",
"key": "booked",
"kind": "judge",
"changes": [
{
"field": "promptMd",
"before": "Decide whether the caller booked an appointment during this call.",
"after": "Decide whether the caller booked an appointment during this call. Treat a verbal agreement to a specific day and time as booked, even if the agent did not read back a confirmation number.",
"rationale": "Three corrections flipped the verdict from not booked to booked on calls where the caller agreed to a slot but no confirmation number was read back."
}
]
}
],
"skipped": [
{
"valueId": "d2dc9bf3-d842-44f9-8002-dea791ff0ad4",
"reason": "custom_code"
}
],
"truncatedCorrections": 0
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Aligning requires a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Correct at least one value on this run before aligning"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition align requests for this organization — please wait before requesting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition value not found in this run"
}
]
}
Overview
Dispositions are enabled per organization. If your organization does not have access, these endpoints return
404.complete, partial, or failed) and have at least one correction from Correct Test Run Value. Each corrected value costs one inference call; an organization may make at most 30 align requests per hour.
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.string
required
The test run’s unique identifier. Must be a UUID; otherwise returns
400 with the message runId must be a valid UUID. Returns 404 Test run not found if it does not belong to this disposition.Body Parameters
The body is optional; an empty object aligns every corrected value with no extra guidance. Unknown fields return400 BAD_REQUEST with the message Invalid request body.
array
Restrict alignment to these value ids: 1 to 50 UUIDs. Every id must exist in the run’s definition snapshot, otherwise
404 with the message Disposition value not found in this run. Values in the list that have no corrections are silently ignored.string
Free-text guidance added to every value’s proposal request, up to 2000 characters after trimming. Use it to steer tone or emphasis (for example, “keep prompts under 80 words”).
Response
array
One entry per corrected value that produced a usable proposal. A value whose corrections suggest no change appears with an empty
changes array.Show proposal object
Show proposal object
string
The definition value.
string
The value’s
key.string
structured_extraction, variable_extraction, or judge. custom_code values are never proposed against.array
Up to 12 field-level edits, each
{ "field", "before", "after", "rationale" }. field is promptMd or systemPromptMd (structured extraction and judge), description (variable extraction, the value schema’s description), or levels. followed by an existing judge level key and .promptMd (a judge level prompt). before is the current text, read by the server from the run’s frozen definition or the pinned judge version, never from the proposal. after is the full replacement text, up to 20,000 characters. rationale explains the change in up to 1000 characters. No-op edits and duplicate fields are dropped.array
Corrected values that received no proposal, each
{ "valueId", "reason" }. reason is custom_code (code values have no editable text), no_editable_fields (an unfrozen extraction source or a judge whose pinned version is gone), proposal_invalid (no usable proposal after two attempts), or brief_too_large (the value’s text and corrections exceed the per-request size budget even after trimming).number
How many corrections were dropped, oldest first, to fit the request within its size budget.
0 when every correction was considered.null | array
null on success, or a list of error objects if the request failed.{
"data": {
"proposals": [
{
"valueId": "f4b706ec-43cc-4373-b4a5-a06130fddbbf",
"key": "booked",
"kind": "judge",
"changes": [
{
"field": "promptMd",
"before": "Decide whether the caller booked an appointment during this call.",
"after": "Decide whether the caller booked an appointment during this call. Treat a verbal agreement to a specific day and time as booked, even if the agent did not read back a confirmation number.",
"rationale": "Three corrections flipped the verdict from not booked to booked on calls where the caller agreed to a slot but no confirmation number was read back."
}
]
}
],
"skipped": [
{
"valueId": "d2dc9bf3-d842-44f9-8002-dea791ff0ad4",
"reason": "custom_code"
}
],
"truncatedCorrections": 0
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Aligning requires a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "DISPOSITION_ALIGN_NOT_READY",
"message": "Correct at least one value on this run before aligning"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition align requests for this organization — please wait before requesting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Disposition value not found in this run"
}
]
}
Docs for agents: llms.txt
Was this page helpful?