curl --request POST \
--url https://api.usetuner.ai/api/v1/public/call \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"call_id": "<string>",
"call_type": "<string>",
"transcript_with_tool_calls": [
{
"text": "<string>",
"words": [
{
"word": "<string>",
"start_ms": 123,
"end_ms": 123,
"confidence": 123
}
],
"start_ms": 123,
"end_ms": 123,
"duration_ms": 123,
"node": {
"to": "<string>",
"from": "<string>",
"reason": "<string>"
},
"tool": {
"name": "<string>",
"request_id": "<string>",
"params": {},
"result": {},
"is_error": true,
"error": "<string>",
"start_ms": 123,
"end_ms": 123
},
"metadata": {
"e2e_latency": 123,
"interrupted": true,
"llm_node_ttft": 123,
"tts_node_ttfb": 123,
"transcript_confidence": 123,
"stt_node_ttfb": 123,
"eou_delay": 123
}
}
],
"start_timestamp": 123,
"end_timestamp": 123,
"recording_url": "<string>",
"sip_call_id": "<string>",
"recipient": "<string>",
"agent_version": 1,
"transcript": "<string>",
"duration_ms": 123,
"call_status": "<string>",
"disconnection_reason": "<string>",
"caller_phone_number": "<string>",
"call_successful": true,
"user_sentiment": "<string>",
"in_voicemail": true,
"collected_dynamic_variables": {},
"call_cost": 123,
"call_analysis": {},
"metadata": {
"ai_models": {
"asr_model": "<string>",
"llm_model": "<string>",
"tts_model": "<string>"
},
"usage_token": {
"stt_duration_seconds": 123,
"llm_token": 123,
"tts_characters_count": 123
}
},
"general_meta_data_raw": {},
"recording_multi_channel_url": "<string>"
}
'import requests
url = "https://api.usetuner.ai/api/v1/public/call"
payload = {
"call_id": "<string>",
"call_type": "<string>",
"transcript_with_tool_calls": [
{
"text": "<string>",
"words": [
{
"word": "<string>",
"start_ms": 123,
"end_ms": 123,
"confidence": 123
}
],
"start_ms": 123,
"end_ms": 123,
"duration_ms": 123,
"node": {
"to": "<string>",
"from": "<string>",
"reason": "<string>"
},
"tool": {
"name": "<string>",
"request_id": "<string>",
"params": {},
"result": {},
"is_error": True,
"error": "<string>",
"start_ms": 123,
"end_ms": 123
},
"metadata": {
"e2e_latency": 123,
"interrupted": True,
"llm_node_ttft": 123,
"tts_node_ttfb": 123,
"transcript_confidence": 123,
"stt_node_ttfb": 123,
"eou_delay": 123
}
}
],
"start_timestamp": 123,
"end_timestamp": 123,
"recording_url": "<string>",
"sip_call_id": "<string>",
"recipient": "<string>",
"agent_version": 1,
"transcript": "<string>",
"duration_ms": 123,
"call_status": "<string>",
"disconnection_reason": "<string>",
"caller_phone_number": "<string>",
"call_successful": True,
"user_sentiment": "<string>",
"in_voicemail": True,
"collected_dynamic_variables": {},
"call_cost": 123,
"call_analysis": {},
"metadata": {
"ai_models": {
"asr_model": "<string>",
"llm_model": "<string>",
"tts_model": "<string>"
},
"usage_token": {
"stt_duration_seconds": 123,
"llm_token": 123,
"tts_characters_count": 123
}
},
"general_meta_data_raw": {},
"recording_multi_channel_url": "<string>"
}
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({
call_id: '<string>',
call_type: '<string>',
transcript_with_tool_calls: [
{
text: '<string>',
words: [{word: '<string>', start_ms: 123, end_ms: 123, confidence: 123}],
start_ms: 123,
end_ms: 123,
duration_ms: 123,
node: {to: '<string>', from: '<string>', reason: '<string>'},
tool: {
name: '<string>',
request_id: '<string>',
params: {},
result: {},
is_error: true,
error: '<string>',
start_ms: 123,
end_ms: 123
},
metadata: {
e2e_latency: 123,
interrupted: true,
llm_node_ttft: 123,
tts_node_ttfb: 123,
transcript_confidence: 123,
stt_node_ttfb: 123,
eou_delay: 123
}
}
],
start_timestamp: 123,
end_timestamp: 123,
recording_url: '<string>',
sip_call_id: '<string>',
recipient: '<string>',
agent_version: 1,
transcript: '<string>',
duration_ms: 123,
call_status: '<string>',
disconnection_reason: '<string>',
caller_phone_number: '<string>',
call_successful: true,
user_sentiment: '<string>',
in_voicemail: true,
collected_dynamic_variables: {},
call_cost: 123,
call_analysis: {},
metadata: {
ai_models: {asr_model: '<string>', llm_model: '<string>', tts_model: '<string>'},
usage_token: {stt_duration_seconds: 123, llm_token: 123, tts_characters_count: 123}
},
general_meta_data_raw: {},
recording_multi_channel_url: '<string>'
})
};
fetch('https://api.usetuner.ai/api/v1/public/call', 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.usetuner.ai/api/v1/public/call",
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([
'call_id' => '<string>',
'call_type' => '<string>',
'transcript_with_tool_calls' => [
[
'text' => '<string>',
'words' => [
[
'word' => '<string>',
'start_ms' => 123,
'end_ms' => 123,
'confidence' => 123
]
],
'start_ms' => 123,
'end_ms' => 123,
'duration_ms' => 123,
'node' => [
'to' => '<string>',
'from' => '<string>',
'reason' => '<string>'
],
'tool' => [
'name' => '<string>',
'request_id' => '<string>',
'params' => [
],
'result' => [
],
'is_error' => true,
'error' => '<string>',
'start_ms' => 123,
'end_ms' => 123
],
'metadata' => [
'e2e_latency' => 123,
'interrupted' => true,
'llm_node_ttft' => 123,
'tts_node_ttfb' => 123,
'transcript_confidence' => 123,
'stt_node_ttfb' => 123,
'eou_delay' => 123
]
]
],
'start_timestamp' => 123,
'end_timestamp' => 123,
'recording_url' => '<string>',
'sip_call_id' => '<string>',
'recipient' => '<string>',
'agent_version' => 1,
'transcript' => '<string>',
'duration_ms' => 123,
'call_status' => '<string>',
'disconnection_reason' => '<string>',
'caller_phone_number' => '<string>',
'call_successful' => true,
'user_sentiment' => '<string>',
'in_voicemail' => true,
'collected_dynamic_variables' => [
],
'call_cost' => 123,
'call_analysis' => [
],
'metadata' => [
'ai_models' => [
'asr_model' => '<string>',
'llm_model' => '<string>',
'tts_model' => '<string>'
],
'usage_token' => [
'stt_duration_seconds' => 123,
'llm_token' => 123,
'tts_characters_count' => 123
]
],
'general_meta_data_raw' => [
],
'recording_multi_channel_url' => '<string>'
]),
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://api.usetuner.ai/api/v1/public/call"
payload := strings.NewReader("{\n \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\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://api.usetuner.ai/api/v1/public/call")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usetuner.ai/api/v1/public/call")
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 \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"provider_call_id": "<string>",
"is_new": true
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Create a Call
Send call data from your voice AI platform to Tuner for analysis. This endpoint accepts call transcripts and metadata, then processes them through Tuner’s evaluation pipeline.
curl --request POST \
--url https://api.usetuner.ai/api/v1/public/call \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"call_id": "<string>",
"call_type": "<string>",
"transcript_with_tool_calls": [
{
"text": "<string>",
"words": [
{
"word": "<string>",
"start_ms": 123,
"end_ms": 123,
"confidence": 123
}
],
"start_ms": 123,
"end_ms": 123,
"duration_ms": 123,
"node": {
"to": "<string>",
"from": "<string>",
"reason": "<string>"
},
"tool": {
"name": "<string>",
"request_id": "<string>",
"params": {},
"result": {},
"is_error": true,
"error": "<string>",
"start_ms": 123,
"end_ms": 123
},
"metadata": {
"e2e_latency": 123,
"interrupted": true,
"llm_node_ttft": 123,
"tts_node_ttfb": 123,
"transcript_confidence": 123,
"stt_node_ttfb": 123,
"eou_delay": 123
}
}
],
"start_timestamp": 123,
"end_timestamp": 123,
"recording_url": "<string>",
"sip_call_id": "<string>",
"recipient": "<string>",
"agent_version": 1,
"transcript": "<string>",
"duration_ms": 123,
"call_status": "<string>",
"disconnection_reason": "<string>",
"caller_phone_number": "<string>",
"call_successful": true,
"user_sentiment": "<string>",
"in_voicemail": true,
"collected_dynamic_variables": {},
"call_cost": 123,
"call_analysis": {},
"metadata": {
"ai_models": {
"asr_model": "<string>",
"llm_model": "<string>",
"tts_model": "<string>"
},
"usage_token": {
"stt_duration_seconds": 123,
"llm_token": 123,
"tts_characters_count": 123
}
},
"general_meta_data_raw": {},
"recording_multi_channel_url": "<string>"
}
'import requests
url = "https://api.usetuner.ai/api/v1/public/call"
payload = {
"call_id": "<string>",
"call_type": "<string>",
"transcript_with_tool_calls": [
{
"text": "<string>",
"words": [
{
"word": "<string>",
"start_ms": 123,
"end_ms": 123,
"confidence": 123
}
],
"start_ms": 123,
"end_ms": 123,
"duration_ms": 123,
"node": {
"to": "<string>",
"from": "<string>",
"reason": "<string>"
},
"tool": {
"name": "<string>",
"request_id": "<string>",
"params": {},
"result": {},
"is_error": True,
"error": "<string>",
"start_ms": 123,
"end_ms": 123
},
"metadata": {
"e2e_latency": 123,
"interrupted": True,
"llm_node_ttft": 123,
"tts_node_ttfb": 123,
"transcript_confidence": 123,
"stt_node_ttfb": 123,
"eou_delay": 123
}
}
],
"start_timestamp": 123,
"end_timestamp": 123,
"recording_url": "<string>",
"sip_call_id": "<string>",
"recipient": "<string>",
"agent_version": 1,
"transcript": "<string>",
"duration_ms": 123,
"call_status": "<string>",
"disconnection_reason": "<string>",
"caller_phone_number": "<string>",
"call_successful": True,
"user_sentiment": "<string>",
"in_voicemail": True,
"collected_dynamic_variables": {},
"call_cost": 123,
"call_analysis": {},
"metadata": {
"ai_models": {
"asr_model": "<string>",
"llm_model": "<string>",
"tts_model": "<string>"
},
"usage_token": {
"stt_duration_seconds": 123,
"llm_token": 123,
"tts_characters_count": 123
}
},
"general_meta_data_raw": {},
"recording_multi_channel_url": "<string>"
}
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({
call_id: '<string>',
call_type: '<string>',
transcript_with_tool_calls: [
{
text: '<string>',
words: [{word: '<string>', start_ms: 123, end_ms: 123, confidence: 123}],
start_ms: 123,
end_ms: 123,
duration_ms: 123,
node: {to: '<string>', from: '<string>', reason: '<string>'},
tool: {
name: '<string>',
request_id: '<string>',
params: {},
result: {},
is_error: true,
error: '<string>',
start_ms: 123,
end_ms: 123
},
metadata: {
e2e_latency: 123,
interrupted: true,
llm_node_ttft: 123,
tts_node_ttfb: 123,
transcript_confidence: 123,
stt_node_ttfb: 123,
eou_delay: 123
}
}
],
start_timestamp: 123,
end_timestamp: 123,
recording_url: '<string>',
sip_call_id: '<string>',
recipient: '<string>',
agent_version: 1,
transcript: '<string>',
duration_ms: 123,
call_status: '<string>',
disconnection_reason: '<string>',
caller_phone_number: '<string>',
call_successful: true,
user_sentiment: '<string>',
in_voicemail: true,
collected_dynamic_variables: {},
call_cost: 123,
call_analysis: {},
metadata: {
ai_models: {asr_model: '<string>', llm_model: '<string>', tts_model: '<string>'},
usage_token: {stt_duration_seconds: 123, llm_token: 123, tts_characters_count: 123}
},
general_meta_data_raw: {},
recording_multi_channel_url: '<string>'
})
};
fetch('https://api.usetuner.ai/api/v1/public/call', 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.usetuner.ai/api/v1/public/call",
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([
'call_id' => '<string>',
'call_type' => '<string>',
'transcript_with_tool_calls' => [
[
'text' => '<string>',
'words' => [
[
'word' => '<string>',
'start_ms' => 123,
'end_ms' => 123,
'confidence' => 123
]
],
'start_ms' => 123,
'end_ms' => 123,
'duration_ms' => 123,
'node' => [
'to' => '<string>',
'from' => '<string>',
'reason' => '<string>'
],
'tool' => [
'name' => '<string>',
'request_id' => '<string>',
'params' => [
],
'result' => [
],
'is_error' => true,
'error' => '<string>',
'start_ms' => 123,
'end_ms' => 123
],
'metadata' => [
'e2e_latency' => 123,
'interrupted' => true,
'llm_node_ttft' => 123,
'tts_node_ttfb' => 123,
'transcript_confidence' => 123,
'stt_node_ttfb' => 123,
'eou_delay' => 123
]
]
],
'start_timestamp' => 123,
'end_timestamp' => 123,
'recording_url' => '<string>',
'sip_call_id' => '<string>',
'recipient' => '<string>',
'agent_version' => 1,
'transcript' => '<string>',
'duration_ms' => 123,
'call_status' => '<string>',
'disconnection_reason' => '<string>',
'caller_phone_number' => '<string>',
'call_successful' => true,
'user_sentiment' => '<string>',
'in_voicemail' => true,
'collected_dynamic_variables' => [
],
'call_cost' => 123,
'call_analysis' => [
],
'metadata' => [
'ai_models' => [
'asr_model' => '<string>',
'llm_model' => '<string>',
'tts_model' => '<string>'
],
'usage_token' => [
'stt_duration_seconds' => 123,
'llm_token' => 123,
'tts_characters_count' => 123
]
],
'general_meta_data_raw' => [
],
'recording_multi_channel_url' => '<string>'
]),
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://api.usetuner.ai/api/v1/public/call"
payload := strings.NewReader("{\n \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\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://api.usetuner.ai/api/v1/public/call")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usetuner.ai/api/v1/public/call")
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 \"call_id\": \"<string>\",\n \"call_type\": \"<string>\",\n \"transcript_with_tool_calls\": [\n {\n \"text\": \"<string>\",\n \"words\": [\n {\n \"word\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"confidence\": 123\n }\n ],\n \"start_ms\": 123,\n \"end_ms\": 123,\n \"duration_ms\": 123,\n \"node\": {\n \"to\": \"<string>\",\n \"from\": \"<string>\",\n \"reason\": \"<string>\"\n },\n \"tool\": {\n \"name\": \"<string>\",\n \"request_id\": \"<string>\",\n \"params\": {},\n \"result\": {},\n \"is_error\": true,\n \"error\": \"<string>\",\n \"start_ms\": 123,\n \"end_ms\": 123\n },\n \"metadata\": {\n \"e2e_latency\": 123,\n \"interrupted\": true,\n \"llm_node_ttft\": 123,\n \"tts_node_ttfb\": 123,\n \"transcript_confidence\": 123,\n \"stt_node_ttfb\": 123,\n \"eou_delay\": 123\n }\n }\n ],\n \"start_timestamp\": 123,\n \"end_timestamp\": 123,\n \"recording_url\": \"<string>\",\n \"sip_call_id\": \"<string>\",\n \"recipient\": \"<string>\",\n \"agent_version\": 1,\n \"transcript\": \"<string>\",\n \"duration_ms\": 123,\n \"call_status\": \"<string>\",\n \"disconnection_reason\": \"<string>\",\n \"caller_phone_number\": \"<string>\",\n \"call_successful\": true,\n \"user_sentiment\": \"<string>\",\n \"in_voicemail\": true,\n \"collected_dynamic_variables\": {},\n \"call_cost\": 123,\n \"call_analysis\": {},\n \"metadata\": {\n \"ai_models\": {\n \"asr_model\": \"<string>\",\n \"llm_model\": \"<string>\",\n \"tts_model\": \"<string>\"\n },\n \"usage_token\": {\n \"stt_duration_seconds\": 123,\n \"llm_token\": 123,\n \"tts_characters_count\": 123\n }\n },\n \"general_meta_data_raw\": {},\n \"recording_multi_channel_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": 123,
"provider_call_id": "<string>",
"is_new": true
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Send your API key in the
Authorization header as a Bearer token.Authorizations
Use Tuner API key (tr_api_...) or user session token. Find your API key in Workspace Settings > API Keys.
Query Parameters
Your Agent ID configured in Tuner. Get this value from Agent Settings > Agent Connection > Agent ID.
Body
Request schema for public call creation.
Unique call identifier from your provider (used for idempotency).
1 - 200Call channel/type from your provider (e.g., 'phone_call', 'web_call').
1 - 100Unified call timeline. Each item represents either a user message, agent message, node transition, or a tool event. Include timing either as word-level ("words") or segment-level ("start_ms + end_ms" or "duration_ms")
1Show child attributes
Show child attributes
Call start time as Unix epoch. Accepts either seconds or milliseconds.
Call end time as Unix epoch. Accepts either seconds or milliseconds. Must be greater than or equal to start_timestamp.
Publicly reachable recording URL (audio file or provider recording link).
1 - 1024Optional SIP call identifier. When provided, it is used as provider_call_id for persistence and idempotency.
1 - 200Recipient phone number (E.164) or SIP URL for outbound calls.
1 - 500The version of the agent that handled this call (e.g. 3).
x >= 0Diarized plain-text transcript (fallback for display/search). If omitted, we derive it from transcript_with_tool_calls when possible.
Call duration in milliseconds. If omitted, we compute it from start_timestamp and end_timestamp.
Provider call status at ingest time. Preferred values: 'call_ended'.
100Why the call ended (e.g. user_hangup, agent_hangup).
100Caller phone number in E.164 format when available (e.g., '+14155550123').
50Whether the call was successful
User sentiment label. Must be one of [positive, neutral, negative, unknown]
50Whether the call reached voicemail
Dynamic variables collected during the call (free-form JSON)
Total call cost in cents (e.g. 125 for $1.25). Client sends cents; frontend converts from dollars for UX.
Provider-native analysis payload (free-form JSON; stored as-is)
Call-level metadata (e.g. context, custom attributes). Supports structured ai_models and usage_token fields; extra keys are also accepted. Merged into general_meta_data_raw for storage. If both are sent, keys are merged; general_meta_data_raw keys win on collision.
Show child attributes
Show child attributes
Use to store any extra metadata payload as a JSON object
Multi-channel recording URL (separate speaker channels), if available.
1024Response
Successful Response