curl --request POST \
--url https://{subdomain}.mihu.ai/api/v1/simulations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "booking-flow-voice",
"agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_cases": [
{
"title": "Reserves a seat with a valid ticket",
"criteria": [
"<string>"
],
"scenario": "<string>",
"expected": "<string>"
}
],
"description": "<string>",
"personas": [
{
"name": "Mehmet Yılmaz",
"role": "Concert ticket owner who wants a front seat",
"traits": [
"<string>"
]
}
],
"runs_per_case": 3,
"max_turns": 8,
"pass_threshold": 80,
"call_mode": "simulated",
"caller_agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"with_intents": false,
"run": false
}
'import requests
url = "https://{subdomain}.mihu.ai/api/v1/simulations"
payload = {
"name": "booking-flow-voice",
"agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_cases": [
{
"title": "Reserves a seat with a valid ticket",
"criteria": ["<string>"],
"scenario": "<string>",
"expected": "<string>"
}
],
"description": "<string>",
"personas": [
{
"name": "Mehmet Yılmaz",
"role": "Concert ticket owner who wants a front seat",
"traits": ["<string>"]
}
],
"runs_per_case": 3,
"max_turns": 8,
"pass_threshold": 80,
"call_mode": "simulated",
"caller_agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"with_intents": False,
"run": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'booking-flow-voice',
agent_uuid: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
test_cases: [
{
title: 'Reserves a seat with a valid ticket',
criteria: ['<string>'],
scenario: '<string>',
expected: '<string>'
}
],
description: '<string>',
personas: [
{
name: 'Mehmet Yılmaz',
role: 'Concert ticket owner who wants a front seat',
traits: ['<string>']
}
],
runs_per_case: 3,
max_turns: 8,
pass_threshold: 80,
call_mode: 'simulated',
caller_agent_uuid: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
with_intents: false,
run: false
})
};
fetch('https://{subdomain}.mihu.ai/api/v1/simulations', 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://{subdomain}.mihu.ai/api/v1/simulations",
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([
'name' => 'booking-flow-voice',
'agent_uuid' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'test_cases' => [
[
'title' => 'Reserves a seat with a valid ticket',
'criteria' => [
'<string>'
],
'scenario' => '<string>',
'expected' => '<string>'
]
],
'description' => '<string>',
'personas' => [
[
'name' => 'Mehmet Yılmaz',
'role' => 'Concert ticket owner who wants a front seat',
'traits' => [
'<string>'
]
]
],
'runs_per_case' => 3,
'max_turns' => 8,
'pass_threshold' => 80,
'call_mode' => 'simulated',
'caller_agent_uuid' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'with_intents' => false,
'run' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://{subdomain}.mihu.ai/api/v1/simulations"
payload := strings.NewReader("{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://{subdomain}.mihu.ai/api/v1/simulations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{subdomain}.mihu.ai/api/v1/simulations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}"
response = http.request(request)
puts response.read_bodyCreate a simulation
Creates a draft. Personas may be omitted — they are generated from the test cases when the simulation first runs. Set run=true to queue it immediately.
curl --request POST \
--url https://{subdomain}.mihu.ai/api/v1/simulations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "booking-flow-voice",
"agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_cases": [
{
"title": "Reserves a seat with a valid ticket",
"criteria": [
"<string>"
],
"scenario": "<string>",
"expected": "<string>"
}
],
"description": "<string>",
"personas": [
{
"name": "Mehmet Yılmaz",
"role": "Concert ticket owner who wants a front seat",
"traits": [
"<string>"
]
}
],
"runs_per_case": 3,
"max_turns": 8,
"pass_threshold": 80,
"call_mode": "simulated",
"caller_agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"with_intents": false,
"run": false
}
'import requests
url = "https://{subdomain}.mihu.ai/api/v1/simulations"
payload = {
"name": "booking-flow-voice",
"agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_cases": [
{
"title": "Reserves a seat with a valid ticket",
"criteria": ["<string>"],
"scenario": "<string>",
"expected": "<string>"
}
],
"description": "<string>",
"personas": [
{
"name": "Mehmet Yılmaz",
"role": "Concert ticket owner who wants a front seat",
"traits": ["<string>"]
}
],
"runs_per_case": 3,
"max_turns": 8,
"pass_threshold": 80,
"call_mode": "simulated",
"caller_agent_uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"with_intents": False,
"run": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'booking-flow-voice',
agent_uuid: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
test_cases: [
{
title: 'Reserves a seat with a valid ticket',
criteria: ['<string>'],
scenario: '<string>',
expected: '<string>'
}
],
description: '<string>',
personas: [
{
name: 'Mehmet Yılmaz',
role: 'Concert ticket owner who wants a front seat',
traits: ['<string>']
}
],
runs_per_case: 3,
max_turns: 8,
pass_threshold: 80,
call_mode: 'simulated',
caller_agent_uuid: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
with_intents: false,
run: false
})
};
fetch('https://{subdomain}.mihu.ai/api/v1/simulations', 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://{subdomain}.mihu.ai/api/v1/simulations",
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([
'name' => 'booking-flow-voice',
'agent_uuid' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'test_cases' => [
[
'title' => 'Reserves a seat with a valid ticket',
'criteria' => [
'<string>'
],
'scenario' => '<string>',
'expected' => '<string>'
]
],
'description' => '<string>',
'personas' => [
[
'name' => 'Mehmet Yılmaz',
'role' => 'Concert ticket owner who wants a front seat',
'traits' => [
'<string>'
]
]
],
'runs_per_case' => 3,
'max_turns' => 8,
'pass_threshold' => 80,
'call_mode' => 'simulated',
'caller_agent_uuid' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'with_intents' => false,
'run' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://{subdomain}.mihu.ai/api/v1/simulations"
payload := strings.NewReader("{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://{subdomain}.mihu.ai/api/v1/simulations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{subdomain}.mihu.ai/api/v1/simulations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"booking-flow-voice\",\n \"agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"test_cases\": [\n {\n \"title\": \"Reserves a seat with a valid ticket\",\n \"criteria\": [\n \"<string>\"\n ],\n \"scenario\": \"<string>\",\n \"expected\": \"<string>\"\n }\n ],\n \"description\": \"<string>\",\n \"personas\": [\n {\n \"name\": \"Mehmet Yılmaz\",\n \"role\": \"Concert ticket owner who wants a front seat\",\n \"traits\": [\n \"<string>\"\n ]\n }\n ],\n \"runs_per_case\": 3,\n \"max_turns\": 8,\n \"pass_threshold\": 80,\n \"call_mode\": \"simulated\",\n \"caller_agent_uuid\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"with_intents\": false,\n \"run\": false\n}"
response = http.request(request)
puts response.read_bodyAuthorizations
Use a Bearer token to access these API endpoints. Example: "Bearer {your-token}"
Body
Required. A label for this simulation; shown in the list and on the report.
"booking-flow-voice"
Required. The channel the assistant is tested on; the agent must have it connected (see /options).
voice, sms, whatsapp, whatsapp_call, email, instagram, messenger Required. The agent being tested; must have the chosen channel connected (422 otherwise).
Required, at least one. Each is one scenario the assistant is scored against.
1Show child attributes
Show child attributes
Optional. Free-text note about what this simulation verifies.
Optional. The simulated customers. Omit to auto-generate them from the test cases at run time.
Show child attributes
Show child attributes
Optional. How many conversations to run per test case; criteria resolve by majority across them. Default 3.
1 <= x <= 20Optional. Max customer turns per conversation. Use 3-4 for smoke tests, 6-10 for discovery/booking flows. Default 8.
2 <= x <= 30Optional. Average score (0-100) at or above which the simulation is 'passed'. Default 80.
50 <= x <= 100Voice only. real = the caller line dials the assistant's number with the persona taking over the call
simulated, real Required for call_mode=real: the agent whose line plays the customer (must differ from agent_uuid and have a phone line)
The assistant uses its real intent tools; detected intents EXECUTE their events for real
Queue the simulation immediately after creating it
Response
Created. With run=true check data.state: queued = started; draft = it could not start and message states why (fix, then POST /{uuid}/run)