Correct Test Run Value
curl --request PUT \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id} \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"state": "<string>",
"value": "<any>",
"explanation": "<string>"
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}"
payload = {
"state": "<string>",
"value": "<any>",
"explanation": "<string>"
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({state: '<string>', value: '<any>', explanation: '<string>'})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}', 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}/cases/{call_id}/annotations/{value_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'state' => '<string>',
'value' => '<any>',
'explanation' => '<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}/cases/{call_id}/annotations/{value_id}"
payload := strings.NewReader("{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "1104a27d-55ca-4598-81bf-816ff21370b1",
"testRunId": "9657e390-255f-4206-9bed-a05275cd0b94",
"testRunCaseId": "c6fcc42a-f731-4521-b489-c0fd7e3ddfc9",
"callId": "b9f0ebae-9698-4bd0-a86a-b4d031bf9e30",
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"revision": 1,
"originalResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": false,
"rationale": "No appointment time was agreed before the caller hung up.",
"executedVia": { "lane": "sync", "priceMultiplier": 1 }
},
"correctedResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": true
},
"explanation": "The caller agreed to the slot at the very end of the call, after the agent's recap.",
"createdBy": "0e9a481a-2920-4eef-b971-a36d9bbec695",
"createdAt": "2026-09-10T20:14:33.870Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Corrected value does not match the frozen boolean schema"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Corrections require a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition corrections submitted for this organization — please wait before submitting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Test run case not found"
}
]
}
Test Runs
Correct Test Run Value
Record a corrected value for one call in a test run.
PUT
/
v2
/
agents
/
{agent_id}
/
dispositions
/
{disposition_id}
/
runs
/
{run_id}
/
cases
/
{call_id}
/
annotations
/
{value_id}
Correct Test Run Value
curl --request PUT \
--url https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id} \
--header 'Content-Type: application/json' \
--header 'authorization: <authorization>' \
--data '
{
"state": "<string>",
"value": "<any>",
"explanation": "<string>"
}
'import requests
url = "https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}"
payload = {
"state": "<string>",
"value": "<any>",
"explanation": "<string>"
}
headers = {
"authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({state: '<string>', value: '<any>', explanation: '<string>'})
};
fetch('https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}', 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}/cases/{call_id}/annotations/{value_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'state' => '<string>',
'value' => '<any>',
'explanation' => '<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}/cases/{call_id}/annotations/{value_id}"
payload := strings.NewReader("{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}")
.header("authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bland.ai/v2/agents/{agent_id}/dispositions/{disposition_id}/runs/{run_id}/cases/{call_id}/annotations/{value_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"state\": \"<string>\",\n \"value\": \"<any>\",\n \"explanation\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "1104a27d-55ca-4598-81bf-816ff21370b1",
"testRunId": "9657e390-255f-4206-9bed-a05275cd0b94",
"testRunCaseId": "c6fcc42a-f731-4521-b489-c0fd7e3ddfc9",
"callId": "b9f0ebae-9698-4bd0-a86a-b4d031bf9e30",
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"revision": 1,
"originalResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": false,
"rationale": "No appointment time was agreed before the caller hung up.",
"executedVia": { "lane": "sync", "priceMultiplier": 1 }
},
"correctedResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": true
},
"explanation": "The caller agreed to the slot at the very end of the call, after the agent's recap.",
"createdBy": "0e9a481a-2920-4eef-b971-a36d9bbec695",
"createdAt": "2026-09-10T20:14:33.870Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Corrected value does not match the frozen boolean schema"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Corrections require a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition corrections submitted for this organization — please wait before submitting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Test run case not found"
}
]
}
Overview
Dispositions are enabled per organization. If your organization does not have access, these endpoints return
404.revision for that call and value. The run must be in a terminal status (complete, partial, or failed). Corrections show up on Get Test Run Rows, in the CSV export, and feed Align Disposition Test Run. An organization may submit at most 300 corrections 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, and 409 CONFLICT with the message Corrections require a terminal test run if the run is still queued or running, or was cancelled.string
required
The call whose result you are correcting. Must be a UUID; otherwise returns
400 with the message callId must be a valid UUID. Returns 404 with the message Test run case not found if the call is not part of this run.string
required
The definition value you are correcting. Must be a UUID; otherwise returns
400 with the message valueId must be a valid UUID. Returns 404 with the message Disposition value not found in this run if the run’s definition snapshot has no such value, or Run result not found for this value if the call produced no result for it.Body Parameters
Unknown fields are rejected with400 BAD_REQUEST and the message Invalid request body.
string
required
produced when you are supplying the right value, or no_value when the call genuinely offers no answer for this value.any
Required when
state is produced; must be omitted when state is no_value. Must match the value’s frozen schema exactly (a boolean for boolean, one of the option keys for enum, and so on), otherwise 400 with a message such as Corrected value does not match the frozen boolean schema. A string may be at most 4000 characters; an array or object may serialize to at most 16000 characters.string
required
Why the engine’s result was wrong, 40 to 4000 characters after trimming. Stored verbatim and used as training context by Align Disposition Test Run.
Response
Returns201 on success.
object
The new correction revision.
Show correction object
Show correction object
string
Unique identifier for this revision.
string
The test run.
string
Identifier of this call’s execution within the run. Matches the
run_id column of the CSV export.string
The call.
string
The definition value.
number
1 for the first correction of this call and value, incrementing with each further correction.object
The engine’s result as it stood when you corrected it:
valueId, state, and, when present, value, error, rationale, evidence, and executedVia, in the same shape as results[] on Get Test Run Rows.object
{ "valueId", "state" } plus value when state is produced.string
The trimmed explanation you supplied.
string | null
ID of the user who saved the correction, or
null when saved with an org-level key.string
ISO 8601 timestamp of the correction.
null | array
null on success, or a list of error objects if the request failed.{
"data": {
"id": "1104a27d-55ca-4598-81bf-816ff21370b1",
"testRunId": "9657e390-255f-4206-9bed-a05275cd0b94",
"testRunCaseId": "c6fcc42a-f731-4521-b489-c0fd7e3ddfc9",
"callId": "b9f0ebae-9698-4bd0-a86a-b4d031bf9e30",
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"revision": 1,
"originalResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": false,
"rationale": "No appointment time was agreed before the caller hung up.",
"executedVia": { "lane": "sync", "priceMultiplier": 1 }
},
"correctedResult": {
"valueId": "4a3d3d0e-4c73-4621-92a1-425676ccdb69",
"state": "produced",
"value": true
},
"explanation": "The caller agreed to the slot at the very end of the call, after the agent's recap.",
"createdBy": "0e9a481a-2920-4eef-b971-a36d9bbec695",
"createdAt": "2026-09-10T20:14:33.870Z"
},
"errors": null
}
{
"data": null,
"errors": [
{
"error": "BAD_REQUEST",
"message": "Corrected value does not match the frozen boolean schema"
}
]
}
{
"data": null,
"errors": [
{
"error": "CONFLICT",
"message": "Corrections require a terminal test run"
}
]
}
{
"data": null,
"errors": [
{
"error": "TOO_MANY_REQUESTS",
"message": "Too many disposition corrections submitted for this organization — please wait before submitting more."
}
]
}
{
"data": null,
"errors": [
{
"error": "NOT_FOUND",
"message": "Test run case not found"
}
]
}
Docs for agents: llms.txt
Was this page helpful?