The Speak AI API exposes 13 testing endpoints under the base URL https://api.speakai.co/v1. Every request needs the x-speakai-key and x-access-token headers described in Authentication.
Scripted test scenarios and run history for a voice agent. The run lifecycle (queue/pause/resume/cancel) is live; the execution engine that actually drives a simulated conversation is not wired up yet, so a run stays queued until that lands.
What can you do with the testing endpoints?
Speak AI groups these 13 endpoints under the testing resource. Each entry below links to the full reference for that endpoint further down this page.
Runs
Suite
Results
Runs
List Test Runs
/voice/testing/{agentId}/runsList Runs
Most recent first, capped at 100 regardless of the limit query parameter.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
limit |
query | integer | No | Defaults to 20. Values above 100 are capped at 100; non-numeric values fall back to the default. |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/runs' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.runs |
object[] |
data.runs – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Start Test Run
/voice/testing/{agentId}/runStart Test Run
Requires the OWNER or ADMIN role. The live execution engine is not wired up yet. These endpoints create and transition the run record, queued, running, paused, completed, cancelled, budget_exceeded, but nothing here drives a simulated conversation against the agent. A run created with POST /run stays queued until something else (not yet built) advances it; scenarioResults stays empty and overallScore stays 0.
Rejects with 409 if the agent has no test suite, the suite has no enabled scenarios, or an active run (queued/running/paused) already exists for this agent, only one run can be active per agent at a time.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/run' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'201 Created
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent, run, or recommendation not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent, run, or recommendation not found",
"hints": []
}409 Conflict, no test suite configured, no enabled scenarios, an active run already exists, or the transition is not valid from the run’s current status
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Get Test Run Detail
/voice/testing/{agentId}/runs/{runId}Get Run Detail
Full run record including scenarioResults and recommendations, scoped to your company. The agentId path segment is not used to filter this lookup, only runId and your company.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
runId |
path | string | Yes |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/runs/RUN_ID' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
404 Run not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Run not found",
"hints": []
}Cancel Test Run
/voice/testing/{agentId}/run/{runId}/cancelCancel Run
Requires the OWNER or ADMIN role. Valid from queued, running, or paused. Terminal, a cancelled run can never be resumed.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
runId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/run/RUN_ID/cancel' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent, run, or recommendation not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent, run, or recommendation not found",
"hints": []
}409 Conflict, no test suite configured, no enabled scenarios, an active run already exists, or the transition is not valid from the run’s current status
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Pause Test Run
/voice/testing/{agentId}/run/{runId}/pausePause Run
Requires the OWNER or ADMIN role. Valid only from queued or running. The live execution engine is not wired up yet. These endpoints create and transition the run record, queued, running, paused, completed, cancelled, budget_exceeded, but nothing here drives a simulated conversation against the agent. A run created with POST /run stays queued until something else (not yet built) advances it; scenarioResults stays empty and overallScore stays 0.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
runId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/run/RUN_ID/pause' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent, run, or recommendation not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent, run, or recommendation not found",
"hints": []
}409 Conflict, no test suite configured, no enabled scenarios, an active run already exists, or the transition is not valid from the run’s current status
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Resume Test Run
/voice/testing/{agentId}/run/{runId}/resumeResume Run
Requires the OWNER or ADMIN role. Valid only from paused, transitioning back to running.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
runId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/run/RUN_ID/resume' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent, run, or recommendation not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent, run, or recommendation not found",
"hints": []
}409 Conflict, no test suite configured, no enabled scenarios, an active run already exists, or the transition is not valid from the run’s current status
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Get Active Test Run
/voice/testing/{agentId}/run/activeGet Active Run
Returns the agent’s currently active run (queued, running, or paused), or null in data.run if none is active. Not a 404 when there is no active run.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/run/active' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.run |
object |
data.run – 22 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use runId to identify it. |
runId |
string | |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
status |
string | One of: queued, running, paused, completed, failed, cancelled, budget_exceeded . |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
currentScenarioIndex |
integer | |
totalScenarios |
integer | |
scenarioResults |
object[] | Populated as the execution engine appends results. Empty on a run that never left queued. |
overallScore |
number | |
passedCount |
integer | |
failedCount |
integer | |
totalCount |
integer | |
totalCost |
number | |
isRegression |
boolean | |
baselineScore |
number | |
scoreDelta |
number | |
recommendations |
object[] | |
startedAt |
string (date-time) | |
completedAt |
string (date-time) | |
failureReason |
string |
404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Apply Test Run Recommendation
/voice/testing/{agentId}/runs/{runId}/recommendations/{recId}/applyApply Recommendation
Requires the OWNER or ADMIN role. Applies a recommendation’s quick action to the agent:
patch_instructions/instructions, appends the recommendation’s suggested fix to the agent’s instructions.update_personality/personality, appends it to the agent’s personality.add_topic_to_avoid/topics_to_avoid, adds it tochatSettings.topicsToAvoid.add_lexicon_term/lexicon/add_to_kb/kb, marked applied but makes no change to the agent. These two categories are not wired up yet; the run record reflects the acknowledgement, the agent config does not.
Any other action type returns 400. A recommendation with no suggestedFix also returns 400.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
runId |
path | string | Yes | |
recId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/runs/RUN_ID/recommendations/REC_ID/apply' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.applied |
boolean | |
data.recommendation |
object | The recommendation as stored on the run, now with applied: true and appliedAt set. |
400 Invalid transition, or recommendation has no suggested fix
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent, run, or recommendation not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent, run, or recommendation not found",
"hints": []
}Suite
Get Test Suite
/voice/testing/{agentId}/suiteGet Test Suite
Returns the agent’s test suite, or null in data.suite if none has been created yet, this is not a 404.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/suite' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.suite |
object |
data.suite – 11 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use suiteId to identify it. |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
scenarios |
object[] | |
maxCostPerRun |
number | |
autoRunOnKbUpdate |
boolean | |
autoRunOnInstructionSave |
boolean | |
scheduledCron |
string | |
createdAt |
string (date-time) | |
updatedAt |
string (date-time) |
scenarios – 7 more fields
| Field | Type | Description |
|---|---|---|
scenarioId |
string | |
name |
string | |
description |
string | |
userMessages |
string[] | Required, at least one message. The scripted turns sent to the agent. |
criteria |
object[] | Defaults to an empty array. |
category |
string | One of: greeting, kb_retrieval, off_topic, edge_case, custom . |
isEnabled |
boolean |
criteria – 10 more fields
| Field | Type | Description |
|---|---|---|
criterionId |
string | |
name |
string | |
evaluationPrompt |
string | What the LLM judge is asked to evaluate. |
weight |
number | |
isCritical |
boolean | |
type |
string | Defaults to llm_judged when omitted. The other three route through a deterministic code check before the LLM judge runs. One of: llm_judged, response_length, regex_match, tool_called . |
maxWords |
integer | For type=response_length: fails if any agent response exceeds this word count. |
regexPattern |
string | For type=regex_match: JS regex source, no slashes. |
mustMatch |
boolean | For type=regex_match: when true (default), at least one response must match; when false, none may. |
expectedToolName |
string | For type=tool_called: the tool name to look for in the transcript’s tool calls. |
404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Create Or Update Test Suite
/voice/testing/{agentId}/suiteUpdate Test Suite
Requires the OWNER or ADMIN role. Upserts, creates the suite on first call, updates it on later calls. Send the full scenarios array you want to keep; it replaces the stored array rather than merging.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
Request body
Fields marked required are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.
| Field | Type |
|---|---|
scenarios |
object[] |
maxCostPerRun |
number |
autoRunOnKbUpdate |
boolean |
autoRunOnInstructionSave |
boolean |
scheduledCron |
string |
scenarios – 7 more fields
| Field | Type | Description |
|---|---|---|
scenarioId |
string | |
name |
string | |
description |
string | |
userMessages |
string[] | Required, at least one message. The scripted turns sent to the agent. |
criteria |
object[] | Defaults to an empty array. |
category |
string | One of: greeting, kb_retrieval, off_topic, edge_case, custom . |
isEnabled |
boolean |
criteria – 10 more fields
| Field | Type | Description |
|---|---|---|
criterionId |
string | |
name |
string | |
evaluationPrompt |
string | What the LLM judge is asked to evaluate. |
weight |
number | |
isCritical |
boolean | |
type |
string | Defaults to llm_judged when omitted. The other three route through a deterministic code check before the LLM judge runs. One of: llm_judged, response_length, regex_match, tool_called . |
maxWords |
integer | For type=response_length: fails if any agent response exceeds this word count. |
regexPattern |
string | For type=regex_match: JS regex source, no slashes. |
mustMatch |
boolean | For type=regex_match: when true (default), at least one response must match; when false, none may. |
expectedToolName |
string | For type=tool_called: the tool name to look for in the transcript’s tool calls. |
curl -X PUT 'https://api.speakai.co/v1/voice/testing/AGENT_ID/suite' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
-H 'Content-Type: application/json' \
-d '{}'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.suite |
object |
data.suite – 11 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use suiteId to identify it. |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
scenarios |
object[] | |
maxCostPerRun |
number | |
autoRunOnKbUpdate |
boolean | |
autoRunOnInstructionSave |
boolean | |
scheduledCron |
string | |
createdAt |
string (date-time) | |
updatedAt |
string (date-time) |
scenarios – 7 more fields
| Field | Type | Description |
|---|---|---|
scenarioId |
string | |
name |
string | |
description |
string | |
userMessages |
string[] | Required, at least one message. The scripted turns sent to the agent. |
criteria |
object[] | Defaults to an empty array. |
category |
string | One of: greeting, kb_retrieval, off_topic, edge_case, custom . |
isEnabled |
boolean |
criteria – 10 more fields
| Field | Type | Description |
|---|---|---|
criterionId |
string | |
name |
string | |
evaluationPrompt |
string | What the LLM judge is asked to evaluate. |
weight |
number | |
isCritical |
boolean | |
type |
string | Defaults to llm_judged when omitted. The other three route through a deterministic code check before the LLM judge runs. One of: llm_judged, response_length, regex_match, tool_called . |
maxWords |
integer | For type=response_length: fails if any agent response exceeds this word count. |
regexPattern |
string | For type=regex_match: JS regex source, no slashes. |
mustMatch |
boolean | For type=regex_match: when true (default), at least one response must match; when false, none may. |
expectedToolName |
string | For type=tool_called: the tool name to look for in the transcript’s tool calls. |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Generate Default Test Suite
/voice/testing/{agentId}/suite/generateAuto-Generate Test Suite
Requires the OWNER or ADMIN role. Uses the agent’s own instructions and knowledge base to generate a default set of scenarios via an LLM call, then overwrites the suite’s scenarios array with the result (upserting the suite if none exists). maxCostPerRun and the auto-run flags are left untouched.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
curl -X POST 'https://api.speakai.co/v1/voice/testing/AGENT_ID/suite/generate' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.suite |
object |
data.suite – 11 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use suiteId to identify it. |
suiteId |
string | |
agentId |
string | |
companyId |
string | |
scenarios |
object[] | |
maxCostPerRun |
number | |
autoRunOnKbUpdate |
boolean | |
autoRunOnInstructionSave |
boolean | |
scheduledCron |
string | |
createdAt |
string (date-time) | |
updatedAt |
string (date-time) |
scenarios – 7 more fields
| Field | Type | Description |
|---|---|---|
scenarioId |
string | |
name |
string | |
description |
string | |
userMessages |
string[] | Required, at least one message. The scripted turns sent to the agent. |
criteria |
object[] | Defaults to an empty array. |
category |
string | One of: greeting, kb_retrieval, off_topic, edge_case, custom . |
isEnabled |
boolean |
criteria – 10 more fields
| Field | Type | Description |
|---|---|---|
criterionId |
string | |
name |
string | |
evaluationPrompt |
string | What the LLM judge is asked to evaluate. |
weight |
number | |
isCritical |
boolean | |
type |
string | Defaults to llm_judged when omitted. The other three route through a deterministic code check before the LLM judge runs. One of: llm_judged, response_length, regex_match, tool_called . |
maxWords |
integer | For type=response_length: fails if any agent response exceeds this word count. |
regexPattern |
string | For type=regex_match: JS regex source, no slashes. |
mustMatch |
boolean | For type=regex_match: when true (default), at least one response must match; when false, none may. |
expectedToolName |
string | For type=tool_called: the tool name to look for in the transcript’s tool calls. |
403 Caller’s role is not OWNER or ADMIN
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Example response, application/json.
{
"status": "failed",
"message": "You do not have permission to manage agents"
}404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}503 Suite generation is unavailable, the underlying LLM provider is not configured
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
message |
string |
Results
Get Test Baseline
/voice/testing/{agentId}/baselineGet Baseline
The agent’s best-scoring completed run, used to detect regressions on later runs. null in data.baseline if no run has completed yet.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/baseline' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.baseline |
object |
data.baseline – 7 more fields
| Field | Type | Description |
|---|---|---|
_id |
string | MongoDB document id, included because every document has one; use suiteId to identify it. |
agentId |
string | |
suiteId |
string | |
bestScore |
number | |
bestRunId |
string | |
scenarioBaselines |
object | Map of scenarioId to that scenario’s best score. |
updatedAt |
string (date-time) |
404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Get Test Score History
/voice/testing/{agentId}/score-historyGet Score History
Completed-run score points for charting, most recent first, capped at 100 regardless of limit. Only status: completed runs are included, a queued, running, paused, failed, or cancelled run never appears here.
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
agentId |
path | string | Yes | |
limit |
query | integer | No |
curl -X GET 'https://api.speakai.co/v1/voice/testing/AGENT_ID/score-history' \
-H 'x-speakai-key: sk_test_speak_0000000000000000' \
-H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'200 OK
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: success . |
data |
object | |
data.history |
object[] |
data.history – 4 more fields
| Field | Type | Description |
|---|---|---|
runId |
string | |
score |
number | |
timestamp |
string (date-time) | |
trigger |
string | One of: manual, kb_update, instruction_save, scheduled . |
404 Agent not found
Response body, application/json.
| Field | Type | Description |
|---|---|---|
status |
string | One of: failed . |
requestId |
string | |
code |
integer | |
message |
string | |
hints |
string[] |
Example response, application/json.
{
"status": "failed",
"code": 404,
"message": "Agent not found",
"hints": []
}Related pages
- API reference for the base URL, authentication, and the error format.
- Authenticate with the Speak AI API using access tokens
- Upload audio and video to Speak AI and read insights
- Create and update live transcription sessions
- Analyze text notes with the Speak AI text endpoints
Get an API key on the Speak AI developer page.