curl --request POST \
--url https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/ \
--header 'Content-Type: application/json' \
--header 'X-CEKURA-API-KEY: <api-key>' \
--data '
{
"spec": "<unknown>",
"file": "<string>",
"agent_id": 123,
"name": "<string>",
"livekit_data": {},
"pipecat_data": {}
}
'import requests
url = "https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/"
payload = {
"spec": "<unknown>",
"file": "<string>",
"agent_id": 123,
"name": "<string>",
"livekit_data": {},
"pipecat_data": {}
}
headers = {
"X-CEKURA-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-CEKURA-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
spec: '<unknown>',
file: '<string>',
agent_id: 123,
name: '<string>',
livekit_data: {},
pipecat_data: {}
})
};
fetch('https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/', 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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/",
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([
'spec' => '<unknown>',
'file' => '<string>',
'agent_id' => 123,
'name' => '<string>',
'livekit_data' => [
],
'pipecat_data' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-CEKURA-API-KEY: <api-key>"
],
]);
$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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/"
payload := strings.NewReader("{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-CEKURA-API-KEY", "<api-key>")
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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/")
.header("X-CEKURA-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-CEKURA-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"agent": 123,
"status": "pending",
"run_as_text": false,
"runs": {
"id": 274,
"status": "pending",
"scenario": 1,
"number": null,
"inbound_number": "+11234567890",
"scenario_name": "Customer Support Call (Agent Inbound = True)",
"test_profile_data": null,
"outbound_dial_window_opens_at": null,
"outbound_dial_window_seconds": null,
"outbound_dial_window_closes_at": null
},
"created_at": "2025-02-25T21:00:01.990052Z"
}{
"field_name": [
"<string>"
]
}Run Scenarios V2 Voice
VOICE RUN: Execute evaluators against your agent using a real voice / phone / SIP call. This is the primary ‘run your evaluators’ endpoint for voice-mode testing. Requires telephony.phone_number configured on the agent (any provider).
curl --request POST \
--url https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/ \
--header 'Content-Type: application/json' \
--header 'X-CEKURA-API-KEY: <api-key>' \
--data '
{
"spec": "<unknown>",
"file": "<string>",
"agent_id": 123,
"name": "<string>",
"livekit_data": {},
"pipecat_data": {}
}
'import requests
url = "https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/"
payload = {
"spec": "<unknown>",
"file": "<string>",
"agent_id": 123,
"name": "<string>",
"livekit_data": {},
"pipecat_data": {}
}
headers = {
"X-CEKURA-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-CEKURA-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
spec: '<unknown>',
file: '<string>',
agent_id: 123,
name: '<string>',
livekit_data: {},
pipecat_data: {}
})
};
fetch('https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/', 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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/",
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([
'spec' => '<unknown>',
'file' => '<string>',
'agent_id' => 123,
'name' => '<string>',
'livekit_data' => [
],
'pipecat_data' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-CEKURA-API-KEY: <api-key>"
],
]);
$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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/"
payload := strings.NewReader("{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-CEKURA-API-KEY", "<api-key>")
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.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/")
.header("X-CEKURA-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cekura.ai/test_framework/v2/scenarios/run_scenarios_json/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-CEKURA-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"spec\": \"<unknown>\",\n \"file\": \"<string>\",\n \"agent_id\": 123,\n \"name\": \"<string>\",\n \"livekit_data\": {},\n \"pipecat_data\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"agent": 123,
"status": "pending",
"run_as_text": false,
"runs": {
"id": 274,
"status": "pending",
"scenario": 1,
"number": null,
"inbound_number": "+11234567890",
"scenario_name": "Customer Support Call (Agent Inbound = True)",
"test_profile_data": null,
"outbound_dial_window_opens_at": null,
"outbound_dial_window_seconds": null,
"outbound_dial_window_closes_at": null
},
"created_at": "2025-02-25T21:00:01.990052Z"
}{
"field_name": [
"<string>"
]
}Authorizations
API Key Authentication. It should be included in the header of each request.
Query Parameters
Validate and price the spec without running or charging anything.
Body
Accepts a spec as a JSON body or an uploaded file.
CI posts JSON directly; the dashboard uploads the same file the customer has
in their repo. Both land in spec.
The test-suite spec. Use this when posting JSON directly.
A .json spec file. Use this instead of 'spec' for uploads.
Agent to test. Overrides 'agent_id' in the spec, letting one spec file run against several environments.
Label for this run. Defaults to the spec's suite name.
255How to reach the agent: 'voice' for a phone call (the default), 'text' for chat, 'elevenlabs' for an ElevenLabs WebRTC session, or 'livekit_v2' or 'pipecat_v2' for their respective WebRTC sessions.
voice- voicetext- textelevenlabs- elevenlabslivekit_v2- livekit_v2pipecat_v2- pipecat_v2
voice, text, elevenlabs, livekit_v2, pipecat_v2 Optional LiveKit overrides. These apply only to this run and are not part of the portable test-suite spec.
Show child attributes
Show child attributes
Optional Pipecat Cloud overrides. These apply only to this run and are not part of the portable test-suite spec.
Show child attributes
Show child attributes
Response
ID of the result
ID of the agent
Status of the result
pending, running, completed, failed Whether the scenario ran as text or not
false
Show child attributes
Show child attributes
{
"id": 274,
"status": "pending",
"scenario": 1,
"number": null,
"inbound_number": "+11234567890",
"scenario_name": "Customer Support Call (Agent Inbound = True)",
"test_profile_data": null,
"outbound_dial_window_opens_at": null,
"outbound_dial_window_seconds": null,
"outbound_dial_window_closes_at": null
}
{
"id": 275,
"status": "pending",
"scenario": 2,
"number": "+11234567890",
"inbound_number": null,
"scenario_name": "Outbound Sales Call (Agent Inbound = False)",
"test_profile_data": null,
"outbound_dial_window_opens_at": "2026-06-24T10:47:30Z",
"outbound_dial_window_seconds": 300,
"outbound_dial_window_closes_at": "2026-06-24T10:52:30Z"
}
"2025-02-25T21:00:01.990052Z"