Skip to main content
Test calls let you programmatically validate an agent against canned scenarios. Each run produces a real call log (billed at a test-call multiplier, typically 2×). Use runs for one-shot tests and batches to execute the same scenario several times concurrently.

Endpoints

MethodPathDescription
GET/v1/test-callsList test-call runs
POST/v1/test-callsStart a single test-call run
GET/v1/test-call-batchesList batches
POST/v1/test-call-batchesStart a batch
GET/v1/test-call-batches/{batch_id}Retrieve batch status and child runs

Test call run object

{
  "id": 7110,
  "target_type": "agent",
  "target_id": 12,
  "direction": "outbound",
  "target_number": "+14155550199",
  "scenario_prompt": "Roleplay as a customer asking about refunds.",
  "mode": "bot",
  "status": "completed",
  "charge_multiplier": 2,
  "estimated_cost_cents": 16,
  "call_id": 987654321,
  "sip_call_id": null,
  "error_message": "",
  "started_at": "2026-04-20T18:24:10.113Z",
  "completed_at": "2026-04-20T18:25:04.822Z",
  "batch_id": null,
  "created_at": "2026-04-20T18:24:09.011Z",
  "updated_at": "2026-04-20T18:25:04.822Z"
}
FieldTypeDescription
idintegerTest-call run id
target_typestringagent or phone_number — what the bot is calling
target_idintegerId of the target agent / phone number
directionstringoutbound (bot places the call) or inbound (bot answers)
target_numberstringOptional E.164 — override for the bot’s perceived caller id
scenario_promptstringFree-form role-play prompt driving the test bot
modestringbot (bot-to-bot) or sip (SIP loopback)
statusstringqueued, in_progress, completed, failed
charge_multiplierintegerMultiplier applied to normal call billing (default 2)
estimated_cost_centsintegerPre-call estimate in USD cents
call_idinteger | nullThe real call log the test produced
sip_call_idinteger | nullFor mode=sip: the inbound call log the webhook created
error_messagestringPopulated on status=failed
batch_idinteger | nullParent batch id if this run is part of a batch

List runs

curl 'https://api.thunderphone.com/v1/test-calls?limit=50' \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"

Query parameters

ParamTypeDescription
limitintegerDefault 50, max 200
offsetinteger
target_typestringFilter by agent or phone_number
statusstringFilter by status
agent_idintegerFilter by target agent
Returns an array of Test call run objects.

Start a single run

curl -X POST https://api.thunderphone.com/v1/test-calls \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_type": "agent",
    "target_id":   12,
    "direction":   "outbound",
    "scenario_prompt": "Roleplay as a customer asking about refunds.",
    "consent_to_charge": true
  }'

Request fields

FieldTypeRequiredDescription
target_typestringyesagent or phone_number
target_idintegeryesId of the target in this org
directionstringyesoutbound or inbound
target_numberstringnoE.164 — defaults to a demo number if omitted
scenario_promptstringnoDrives the test bot
modestringnobot (default) or sip
consent_to_chargebooleanyesMust be true — required to prevent accidental charges
Returns 201 Created with the run. Status starts at queued and advances to completed or failed; poll the list endpoint or GET /v1/calls/{call_id} once call_id is set. Errors:
StatusCondition
400consent_to_charge missing / false
402Insufficient balance
404Target agent or phone number not found
429Max concurrent test-call runs per org reached

Start a batch

A batch executes the same scenario N times in parallel. The response returns immediately with a batch in in_progress; poll the detail endpoint for per-run results.
curl -X POST https://api.thunderphone.com/v1/test-call-batches \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_type":  "agent",
    "target_id":    12,
    "direction":    "outbound",
    "run_count":    5,
    "stagger_seconds": 2,
    "scenario_prompts": [
      "Ask about refunds.",
      "Ask for hours of operation.",
      "Complain about a delayed shipment.",
      "Ask to speak with a human.",
      "Ask an unrelated trivia question."
    ],
    "consent_to_charge": true
  }'

Request fields

FieldTypeRequiredDescription
target_typestringyesagent or phone_number
target_idintegeryes
directionstringyes
run_countintegeryes1–20
stagger_secondsintegernoDelay between spawning successive runs (0–60)
scenario_promptsarray of stringnoRotates through prompts per run (modulo)
scenario_promptstringnoSame prompt for all runs (alternative to array)
target_numberstringno
modestringno
consent_to_chargebooleanyes
Returns 201 Created with the batch row:
{
  "id": 201,
  "name": "",
  "target_type": "agent",
  "target_id": 12,
  "direction": "outbound",
  "target_number": "",
  "scenario_prompts": ["Ask about refunds.", "…"],
  "run_count": 5,
  "stagger_seconds": 2,
  "status": "in_progress",
  "total_runs": 5,
  "completed_runs": 0,
  "failed_runs": 0,
  "error_message": "",
  "requested_by_id": 1,
  "started_at": "2026-04-20T18:24:09.011Z",
  "completed_at": null,
  "created_at": "2026-04-20T18:24:09.011Z",
  "updated_at": "2026-04-20T18:24:09.011Z",
  "run_ids": [7110, 7111, 7112, 7113, 7114]
}

Get batch detail

curl https://api.thunderphone.com/v1/test-call-batches/201 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
Returns the same batch shape as the create response — note run_ids is a list of child-run ids, not nested run objects. Fetch each run via GET /v1/test-calls?limit=... or by following the call_id on each run to GET /v1/calls/{call_id}.

Agents

Build the agent being tested.

Calls

Inspect the resulting call logs and transcripts.