curl "https://first-signal-api.fly.dev/v1/agents/6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b/calls/0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e" \
-H "Authorization: Bearer $SIGNAL_API_KEY"import requests
url = "https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}', 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://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "call",
"id": "0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e",
"providerCallId": "call_5e0c2b7a91d34f6e8a1b",
"version": 8,
"startedAt": "2026-10-01T15:42:05.000Z",
"endedAt": "2026-10-01T15:44:51.000Z",
"durationMs": 166000,
"direction": "inbound",
"disconnectionReason": "user_hangup",
"outcome": "abandoned",
"objective": "Book a cleaning for next week",
"intent": {
"slug": "book_appointment",
"label": "Book appointment"
},
"useCase": {
"slug": "scheduling",
"label": "Scheduling"
},
"subUseCase": {
"slug": "new_booking",
"label": "New booking"
},
"callerPersona": {
"slug": "hurried-returning-patient",
"label": "Hurried returning patient"
},
"caller": {
"kind": "repeat",
"nth": 2,
"of": 3
},
"counts": {
"turns": 24,
"callerTurns": 12,
"agentTurns": 12,
"toolFailures": 1,
"frictions": 2
},
"signalCodes": [
"tool_timeout",
"dead_air"
],
"analysis": {
"intentConfidence": 0.94,
"objectiveFulfilled": false,
"fulfillmentConfidence": 0.81,
"reasoning": "The caller asked for a cleaning next week; the availability lookup did not answer and the caller hung up before a time was offered.",
"source": "llm",
"analyzedAt": "2026-10-01T15:47:30.000Z",
"frictions": []
},
"alsoAsked": [
{
"slug": "insurance_question",
"label": "Insurance question",
"coverage": "designed"
}
],
"traits": [
{
"slug": "in_a_hurry",
"label": "In a hurry",
"trait": "demeanour"
}
],
"coverage": {
"useCase": "designed",
"subUseCase": "designed"
},
"audio": {
"noiseDb": -58.2,
"speechDb": -21.4,
"snrDb": 36.8
},
"issues": [
{
"object": "issue",
"id": "a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
"key": "tool_timeout:check_availability",
"title": "The agent did not reply in Book appointment",
"status": "discovered",
"klass": "technical"
}
]
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}Get a call
One call with its analysis, who called and why, and the open issues it is evidence for. The transcript is in the call’s trace.
curl "https://first-signal-api.fly.dev/v1/agents/6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b/calls/0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e" \
-H "Authorization: Bearer $SIGNAL_API_KEY"import requests
url = "https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}', 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://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://first-signal-api.fly.dev/v1/agents/{agentId}/calls/{callId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "call",
"id": "0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e",
"providerCallId": "call_5e0c2b7a91d34f6e8a1b",
"version": 8,
"startedAt": "2026-10-01T15:42:05.000Z",
"endedAt": "2026-10-01T15:44:51.000Z",
"durationMs": 166000,
"direction": "inbound",
"disconnectionReason": "user_hangup",
"outcome": "abandoned",
"objective": "Book a cleaning for next week",
"intent": {
"slug": "book_appointment",
"label": "Book appointment"
},
"useCase": {
"slug": "scheduling",
"label": "Scheduling"
},
"subUseCase": {
"slug": "new_booking",
"label": "New booking"
},
"callerPersona": {
"slug": "hurried-returning-patient",
"label": "Hurried returning patient"
},
"caller": {
"kind": "repeat",
"nth": 2,
"of": 3
},
"counts": {
"turns": 24,
"callerTurns": 12,
"agentTurns": 12,
"toolFailures": 1,
"frictions": 2
},
"signalCodes": [
"tool_timeout",
"dead_air"
],
"analysis": {
"intentConfidence": 0.94,
"objectiveFulfilled": false,
"fulfillmentConfidence": 0.81,
"reasoning": "The caller asked for a cleaning next week; the availability lookup did not answer and the caller hung up before a time was offered.",
"source": "llm",
"analyzedAt": "2026-10-01T15:47:30.000Z",
"frictions": []
},
"alsoAsked": [
{
"slug": "insurance_question",
"label": "Insurance question",
"coverage": "designed"
}
],
"traits": [
{
"slug": "in_a_hurry",
"label": "In a hurry",
"trait": "demeanour"
}
],
"coverage": {
"useCase": "designed",
"subUseCase": "designed"
},
"audio": {
"noiseDb": -58.2,
"speechDb": -21.4,
"snrDb": 36.8
},
"issues": [
{
"object": "issue",
"id": "a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
"key": "tool_timeout:check_availability",
"title": "The agent did not reply in Book appointment",
"status": "discovered",
"klass": "technical"
}
]
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}Authorizations
An API key (sig_...), or a session token from the web app.
Path Parameters
The agent's id.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
The call's id in Signal (not the platform's call id).
Response
The call.
call The call's id in Signal.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
The call's id on the voice platform. Unique within an agent, not across agents.
The agent version that took the call.
"2026-10-02T14:03:07.120Z"
"2026-10-02T14:03:07.120Z"
inbound or outbound, as the platform reports it.
Why the call ended, in the platform's words (user_hangup, agent_hangup, ...).
How the call ended for the caller. Null until the call is analysed.
resolved, unresolved, transferred, abandoned, no_contact, null One line, in the caller's terms, of what they were trying to do. Null until analysed.
The intent the analysis gave the call. Null until analysed.
Show child attributes
Show child attributes
What the caller wanted, from the use case classification. Null when not classified.
Show child attributes
Show child attributes
The narrower use case under useCase, when there is one.
Show child attributes
Show child attributes
The kind of caller the call was read as. Null when not classified.
Show child attributes
Show child attributes
Who called, from facts alone. The phone number itself is never returned.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Codes of the signals detected on the call, sorted. A signal is a symptom noticed on a call, not a diagnosed issue; what to fix is on the issues. Null until analysed, empty when nothing was noticed.
The call's analysis. Null until the call is analysed.
Show child attributes
Show child attributes
Use cases the caller asked for besides useCase.
Show child attributes
Show child attributes
The caller's traits as classified: who they are to the business, demeanour, speech, surroundings, language.
Show child attributes
Show child attributes
Whether the agent was built for what this caller wanted.
Show child attributes
Show child attributes
What the recording measured on the caller's side. Null when it was not read.
Show child attributes
Show child attributes
Open issues this call is evidence for, highest priority first. Resolved and withdrawn issues are left out.
Show child attributes
Show child attributes
Was this page helpful?