curl --request POST \
--url https://api.cekura.ai/observability/v1/observe/ \
--header 'Content-Type: application/json' \
--header 'X-CEKURA-API-KEY: <api-key>' \
--data '
{
"call_id": "<string>",
"trace_id": "",
"agent": 123,
"assistant_id": "<string>",
"voice_recording": "<string>",
"voice_recording_url": "<string>",
"transcript_json": "<unknown>",
"call_ended_reason": "<string>",
"customer_number": "<string>",
"metadata": "<unknown>",
"timestamp": "2023-11-07T05:31:56Z",
"dynamic_variables": "<unknown>",
"feedback": "<string>",
"redact_fields": [],
"metric_ids": "<string>",
"main_agent_channel_index": 123
}
'import requests
url = "https://api.cekura.ai/observability/v1/observe/"
payload = {
"call_id": "<string>",
"trace_id": "",
"agent": 123,
"assistant_id": "<string>",
"voice_recording": "<string>",
"voice_recording_url": "<string>",
"transcript_json": "<unknown>",
"call_ended_reason": "<string>",
"customer_number": "<string>",
"metadata": "<unknown>",
"timestamp": "2023-11-07T05:31:56Z",
"dynamic_variables": "<unknown>",
"feedback": "<string>",
"redact_fields": [],
"metric_ids": "<string>",
"main_agent_channel_index": 123
}
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({
call_id: '<string>',
trace_id: '',
agent: 123,
assistant_id: '<string>',
voice_recording: '<string>',
voice_recording_url: '<string>',
transcript_json: '<unknown>',
call_ended_reason: '<string>',
customer_number: '<string>',
metadata: '<unknown>',
timestamp: '2023-11-07T05:31:56Z',
dynamic_variables: '<unknown>',
feedback: '<string>',
redact_fields: [],
metric_ids: '<string>',
main_agent_channel_index: 123
})
};
fetch('https://api.cekura.ai/observability/v1/observe/', 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/observability/v1/observe/",
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>',
'trace_id' => '',
'agent' => 123,
'assistant_id' => '<string>',
'voice_recording' => '<string>',
'voice_recording_url' => '<string>',
'transcript_json' => '<unknown>',
'call_ended_reason' => '<string>',
'customer_number' => '<string>',
'metadata' => '<unknown>',
'timestamp' => '2023-11-07T05:31:56Z',
'dynamic_variables' => '<unknown>',
'feedback' => '<string>',
'redact_fields' => [
],
'metric_ids' => '<string>',
'main_agent_channel_index' => 123
]),
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/observability/v1/observe/"
payload := strings.NewReader("{\n \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\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/observability/v1/observe/")
.header("X-CEKURA-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cekura.ai/observability/v1/observe/")
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 \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\n}"
response = http.request(request)
puts response.read_body{
"call_id": "<string>",
"id": 123,
"duration": "<string>",
"success": true,
"is_reviewed": true,
"status": "success",
"feedback": "<string>",
"metrics": [
{
"id": 123,
"name": "<string>",
"type": "<string>",
"score": 123,
"enum": "<string>",
"value": "<string>"
}
],
"call_ended_reason": "<string>",
"customer_number": "<string>",
"agent": 123,
"agent_name": "<string>",
"trace_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"error_message": "<string>",
"dropoff_point": "<string>",
"topic": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"transcript": "<string>",
"transcript_object": "<string>",
"evaluation": "<string>"
}{
"field_name": [
"<string>"
]
}Send Calls
Primary ingestion endpoint for production call logs. Your agent (or its provider’s post-call webhook) POSTs here with the transcript, recording URL, and metadata; Cekura stores it as a CallLog, schedules metric evaluation, and surfaces it in Observability.
curl --request POST \
--url https://api.cekura.ai/observability/v1/observe/ \
--header 'Content-Type: application/json' \
--header 'X-CEKURA-API-KEY: <api-key>' \
--data '
{
"call_id": "<string>",
"trace_id": "",
"agent": 123,
"assistant_id": "<string>",
"voice_recording": "<string>",
"voice_recording_url": "<string>",
"transcript_json": "<unknown>",
"call_ended_reason": "<string>",
"customer_number": "<string>",
"metadata": "<unknown>",
"timestamp": "2023-11-07T05:31:56Z",
"dynamic_variables": "<unknown>",
"feedback": "<string>",
"redact_fields": [],
"metric_ids": "<string>",
"main_agent_channel_index": 123
}
'import requests
url = "https://api.cekura.ai/observability/v1/observe/"
payload = {
"call_id": "<string>",
"trace_id": "",
"agent": 123,
"assistant_id": "<string>",
"voice_recording": "<string>",
"voice_recording_url": "<string>",
"transcript_json": "<unknown>",
"call_ended_reason": "<string>",
"customer_number": "<string>",
"metadata": "<unknown>",
"timestamp": "2023-11-07T05:31:56Z",
"dynamic_variables": "<unknown>",
"feedback": "<string>",
"redact_fields": [],
"metric_ids": "<string>",
"main_agent_channel_index": 123
}
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({
call_id: '<string>',
trace_id: '',
agent: 123,
assistant_id: '<string>',
voice_recording: '<string>',
voice_recording_url: '<string>',
transcript_json: '<unknown>',
call_ended_reason: '<string>',
customer_number: '<string>',
metadata: '<unknown>',
timestamp: '2023-11-07T05:31:56Z',
dynamic_variables: '<unknown>',
feedback: '<string>',
redact_fields: [],
metric_ids: '<string>',
main_agent_channel_index: 123
})
};
fetch('https://api.cekura.ai/observability/v1/observe/', 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/observability/v1/observe/",
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>',
'trace_id' => '',
'agent' => 123,
'assistant_id' => '<string>',
'voice_recording' => '<string>',
'voice_recording_url' => '<string>',
'transcript_json' => '<unknown>',
'call_ended_reason' => '<string>',
'customer_number' => '<string>',
'metadata' => '<unknown>',
'timestamp' => '2023-11-07T05:31:56Z',
'dynamic_variables' => '<unknown>',
'feedback' => '<string>',
'redact_fields' => [
],
'metric_ids' => '<string>',
'main_agent_channel_index' => 123
]),
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/observability/v1/observe/"
payload := strings.NewReader("{\n \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\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/observability/v1/observe/")
.header("X-CEKURA-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cekura.ai/observability/v1/observe/")
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 \"call_id\": \"<string>\",\n \"trace_id\": \"\",\n \"agent\": 123,\n \"assistant_id\": \"<string>\",\n \"voice_recording\": \"<string>\",\n \"voice_recording_url\": \"<string>\",\n \"transcript_json\": \"<unknown>\",\n \"call_ended_reason\": \"<string>\",\n \"customer_number\": \"<string>\",\n \"metadata\": \"<unknown>\",\n \"timestamp\": \"2023-11-07T05:31:56Z\",\n \"dynamic_variables\": \"<unknown>\",\n \"feedback\": \"<string>\",\n \"redact_fields\": [],\n \"metric_ids\": \"<string>\",\n \"main_agent_channel_index\": 123\n}"
response = http.request(request)
puts response.read_body{
"call_id": "<string>",
"id": 123,
"duration": "<string>",
"success": true,
"is_reviewed": true,
"status": "success",
"feedback": "<string>",
"metrics": [
{
"id": 123,
"name": "<string>",
"type": "<string>",
"score": 123,
"enum": "<string>",
"value": "<string>"
}
],
"call_ended_reason": "<string>",
"customer_number": "<string>",
"agent": 123,
"agent_name": "<string>",
"trace_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"error_message": "<string>",
"dropoff_point": "<string>",
"topic": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"transcript": "<string>",
"transcript_object": "<string>",
"evaluation": "<string>"
}{
"field_name": [
"<string>"
]
}Authorizations
API Key Authentication. It should be included in the header of each request.
Body
Unique identifier for the call. Example:
"call_abc123xyz""stereo_audio_session_456"
100OpenTelemetry trace ID (32-char hex string). Example: "4bf92f3577b34da6a3ce929d0e0e4736"
32Agent ID, required if assistant_id not provided
Example: 2421
Provider's Assistant ID, required if agent not provided Example:
"asst_abc123xyz""agent_xyz789"
Audio recording file of the call.
Example: Binary data "recordings/call_123_20240315.mp3"
URL to call recording audio file
Example: "https://storage.example.com/recordings/call_123.mp3"
Format of the transcript_json payload. Tells Cekura how to parse roles and timestamps.
vapi— Vapi webhook format:[{"role": "bot"|"user", "message": "...", "time": 0.0}]retell— Retell webhook formatelevenlabs— ElevenLabs formatlivekit— LiveKit formatpipecat— Pipecat formatdeepgram— Deepgram formatcekura(default) —[{"role": "Testing Agent"|"Main Agent", "content": "...", "start_time": 0.0, "end_time": 2.5}]. Valid roles are"Testing Agent"and"Main Agent"only — using"agent"or"user"will return a validation error.none-mono— mono audio with no transcript; Cekura generates the transcript automatically.
Omit this field to use the default Cekura format.
cekura- cekuravocera- voceravapi- vapiretell- retelldeepgram- deepgrampipecat- pipecatlivekit- livekitelevenlabs- elevenlabsnone-mono- none-mono
cekura, vocera, vapi, retell, deepgram, pipecat, livekit, elevenlabs, none-mono Call transcript in supported format (Vapi, Retell, Deepgram, ElevenLabs, Cekura)
Check the Transcript Format documentation for more details.
Cekura Transcript Format Example:
[ { "role": "Testing Agent", "content": "Hello.", "end_time": 1.9399999, "start_time": 1.4399999 }, { "role": "Main Agent", "content": "Hello. I want to book appointment today. My name is John.", "end_time": 7.539999511718751, "start_time": 3.1 }, { "role": "Testing Agent", "content": "Well, I mean, sure. What time exactly are we talking about here", "end_time": 15.71, "start_time": 12.01 }, { "role": "Main Agent", "content": "6 PM.", "end_time": 18.269999, "start_time": 17.609999 } ]
Reason why the call ended Example:
"customer-ended-call""agent-ended-call"
Customer's phone number or identifier Example:
"+1234567890""customer_abc123"
Additional call metadata Example:
{ "customer_id": "123", "order_id": "ORD-12345", "name": "John Doe" }
When the call occurred.
Example: 2024-03-15T10:15:45Z
Dynamic variables used to replace {{variables}} in agent description. Example:
{ "subscription_id": "SUB-12345", "product_type": "premium" }
Feedback about the call
Example: "Great call"
Optional list of sensitive fields to redact from the transcript and audio. Overrides the agent's configured redaction fields for this call; when omitted, the agent's configuration applies.
Available fields include: phone_number, email_address, credit_card, ssn, dob, healthcare_number, etc.
Note: Redacting any fields incurs a cost of 0.1 credits per minute by default, regardless of how many fields are selected.
Example: ["phone_number", "email_address", "credit_card"]
person_name- person_nameage- agephone_number- phone_numberemail_address- email_addressdate- datetime- timelocation- locationorigin- origingender_sexuality- gender_sexualityphysical_attribute- physical_attributeoccupation- occupationusername- usernamepassword- passwordip_address- ip_addressurl- urlfilename- filenameevent- eventvehicle_id- vehicle_iddob- dobhealthcare_number- healthcare_numbermedical_professional- medical_professionalcredit_card- credit_cardaccount_number- account_numberbank_account- bank_accountmoney- moneyssn- ssnpassport_number- passport_numberdriver_license- driver_licensenumerical_pii- numerical_pii
person_name, age, phone_number, email_address, date, time, location, origin, gender_sexuality, physical_attribute, occupation, username, password, ip_address, url, filename, event, vehicle_id, dob, healthcare_number, medical_professional, credit_card, account_number, bank_account, money, ssn, passport_number, driver_license, numerical_pii Comma-separated metric IDs to evaluate for this call. Example: "118,119". To run metrics after the call is created, use the evaluate_metrics endpoint instead.
Channel index (0 or 1) of the main agent in stereo recordings. When provided, skips automatic channel detection. Example: 0 means channel 0 is the main agent, channel 1 is the customer/testing agent.
Response
Unique identifier for the call. Example:
"call_abc123xyz""stereo_audio_session_456"
100Call duration in minutes in MM:SS format.
Example: 01:10
Whether the call was successful.
Example: true or false
Whether the call has been reviewed.
Example: true or false
Status of the call or conversation.
Example: "completed" or "failed"
success- Successfailure- Failurereviewed_success- Reviewed Successreviewed_failure- Reviewed Failure
success, failure, reviewed_success, reviewed_failure Feedback about the call.
Example: "Great Call"
Metrics of the call
Show child attributes
Show child attributes
Reason why the call ended. Example:
"customer-ended-call""agent-ended-call"
100Customer's phone number or identifier. Example:
"+1234567890""customer_abc123"
100Agent ID
Agent name
OpenTelemetry trace ID (32-char hex). Set when OTel tracing is enabled.
32When the call occurred.
Example: 2024-03-15T10:15:45Z
Point in conversation where user disengaged.
Example: "end of conversation as no queries remaining"
1000Topic of the call. Example:
"product_inquiry""technical_support"
1000When this record was created.
Example: 2024-03-15T10:30:45Z
When this record was last updated.
Example: 2024-03-15T10:35:11Z
Full text transcript of the call. Example:
[00:01] Testing Agent: Hello. [00:02] Main Agent: Hello, how can I help you today? [00:03] Testing Agent: Well, I mean, sure. What time exactly are we talking about here [00:04] Main Agent: 6 PM. [00:05] Testing Agent: Great. I'll book that for you. Just a sec. [00:06] Main Agent: Okay.
Structured transcript data with timestamps. Example:
[ { "role": "Testing Agent", "content": "Hello", "start_time": 1.2, "end_time": 1.8 }, { "role": "Main Agent", "content": "Hello, how can I help you today?", "start_time": 1.8, "end_time": 2.5 } ]`
Evaluation of the call