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": "end_timestamp must be after start_timestamp"
}{
"detail": "Not authenticated"
}{
"detail": "Workspace has insufficient credits"
}{
"detail": "User does not have access to workspace 42"
}{
"detail": "Agent with remote identifier agent_abc123 not found"
}{
"detail": "Call with ID call_abc123 already exists for provider 4"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"detail": "Rate limit exceeded: 60 requests per minute allowed for this workspace."
}{
"detail": "Failed to create call"
}Create Call
Ingest a completed call for analysis.
Accepts the transcript and metadata for a call that has already finished on your platform. Tuner queues it for evaluation; scores, outcomes, and red flags appear on the call record shortly after.
call_id must be unique. Re-sending a call that’s already been ingested
returns a conflict rather than replacing it.
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": "end_timestamp must be after start_timestamp"
}{
"detail": "Not authenticated"
}{
"detail": "Workspace has insufficient credits"
}{
"detail": "User does not have access to workspace 42"
}{
"detail": "Agent with remote identifier agent_abc123 not found"
}{
"detail": "Call with ID call_abc123 already exists for provider 4"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"detail": "Rate limit exceeded: 60 requests per minute allowed for this workspace."
}{
"detail": "Failed to create call"
}Authorizations
Use Tuner API key (tr_api_...) or user session token. Find your API key in Workspace Settings > API Keys.
Query Parameters
Workspace ID. Find this in Workspace > General Settings.
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 - 100The call timeline in chronological order. Each item is a user turn, an agent turn, a tool call or its result, or a workflow node transition.
User and agent turns must carry timing — as words, as start_ms and end_ms, or as start_ms and duration_ms. Latency and voice metrics are computed from it.
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