curl --request GET \
--url https://app.thinnest.ai/api/v1/calls/{id} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.thinnest.ai/api/v1/calls/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/calls/{id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"id": "out_9f2c1a44-6b0e-4c1d-8a7f-2e5b3c9d1f60",
"callRef": "out_9f2c1a44-6b0e-4c1d-8a7f-2e5b3c9d1f60",
"reference": "LSQ-42",
"metadata": {
"deal_id": "D-19",
"owner": "Ravi"
},
"attempt": 1,
"status": "completed",
"direction": "outbound",
"phone": "919876543210",
"from": "918045678901",
"agent": {
"id": "ag_5c4a5f93-2b1e-4d7a-9f60-8e2d1c3b4a71",
"name": "Skyline Sales"
},
"scheduledFor": null,
"startedAt": "2026-10-06T04:30:02.118Z",
"answeredAt": "2026-10-06T04:30:09.540Z",
"endedAt": "2026-10-06T04:33:11.902Z",
"seconds": 182,
"hangup": "answered",
"variables": {
"lead_name": "Asha",
"project": "Sky Towers"
},
"summary": "Asha is keen on a 2 BHK at Sky Towers with a budget around 80 lakh. She asked to visit the site on Saturday.",
"fields": {
"budget": 8000000,
"interest": "Hot",
"site_visit": true
},
"transcript": [
{
"speaker": "agent",
"text": "Hello Asha, I'm calling from Skyline Homes about your enquiry for Sky Towers.",
"at": "2026-10-06T04:30:10.204Z"
},
{
"speaker": "customer",
"text": "Haan, boliye. I wanted a 2 BHK.",
"at": "2026-10-06T04:30:16.880Z"
}
],
"recording": {
"url": "https://app.thinnest.ai/api/v1/recordings/3b7e1c90-5a2d-4e8f-9c61-0d4b7a2e8f13?expires=1762403402&sig=8c1f0e7a92b4d3c6e5f1a0b9c8d7e6f5a4b3c2d1",
"expiresAt": "2026-11-05T04:30:02.118Z",
"ready": true
},
"analysedAt": "2026-10-06T04:33:20.311Z",
"retryScheduledFor": null,
"costMicro": 6370000,
"currency": "INR",
"quality": {
"turns": 14,
"responseMs": {
"median": 1180,
"p90": 1920,
"max": 3410
},
"firstTokenMs": {
"median": 610,
"p90": 940,
"max": 1730
},
"longSilences": 1,
"longSilenceSeconds": 10,
"longestSilenceSeconds": 12.4,
"interruptions": 2,
"modelErrors": 0,
"rescues": 1
},
"usage": {
"inputTokens": 5120,
"outputTokens": 410,
"cachedInputTokens": 3584,
"inputTokensEstimated": false,
"ttsCharacters": 1840
},
"billing": {
"keys": "off",
"voicePlan": "standard",
"ratePerMinuteMicro": 1820000,
"billedSeconds": 210,
"currency": "INR"
},
"forwardedTo": null,
"error": null
}Get Call
One call and everything it learned: status, timings, how it ended, the summary, the collected fields, the transcript, a signed recording link and the call’s quality figures (reply times, silences, interruptions, model errors). It is exactly the object call.analysed delivers, so a missed delivery can be read back here; analysedAt null means the summary and fields are not final yet. Any id List Calls hands out works — out_… and sch_… for calls you placed, the call reference for any other.
curl --request GET \
--url https://app.thinnest.ai/api/v1/calls/{id} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.thinnest.ai/api/v1/calls/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/calls/{id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"id": "out_9f2c1a44-6b0e-4c1d-8a7f-2e5b3c9d1f60",
"callRef": "out_9f2c1a44-6b0e-4c1d-8a7f-2e5b3c9d1f60",
"reference": "LSQ-42",
"metadata": {
"deal_id": "D-19",
"owner": "Ravi"
},
"attempt": 1,
"status": "completed",
"direction": "outbound",
"phone": "919876543210",
"from": "918045678901",
"agent": {
"id": "ag_5c4a5f93-2b1e-4d7a-9f60-8e2d1c3b4a71",
"name": "Skyline Sales"
},
"scheduledFor": null,
"startedAt": "2026-10-06T04:30:02.118Z",
"answeredAt": "2026-10-06T04:30:09.540Z",
"endedAt": "2026-10-06T04:33:11.902Z",
"seconds": 182,
"hangup": "answered",
"variables": {
"lead_name": "Asha",
"project": "Sky Towers"
},
"summary": "Asha is keen on a 2 BHK at Sky Towers with a budget around 80 lakh. She asked to visit the site on Saturday.",
"fields": {
"budget": 8000000,
"interest": "Hot",
"site_visit": true
},
"transcript": [
{
"speaker": "agent",
"text": "Hello Asha, I'm calling from Skyline Homes about your enquiry for Sky Towers.",
"at": "2026-10-06T04:30:10.204Z"
},
{
"speaker": "customer",
"text": "Haan, boliye. I wanted a 2 BHK.",
"at": "2026-10-06T04:30:16.880Z"
}
],
"recording": {
"url": "https://app.thinnest.ai/api/v1/recordings/3b7e1c90-5a2d-4e8f-9c61-0d4b7a2e8f13?expires=1762403402&sig=8c1f0e7a92b4d3c6e5f1a0b9c8d7e6f5a4b3c2d1",
"expiresAt": "2026-11-05T04:30:02.118Z",
"ready": true
},
"analysedAt": "2026-10-06T04:33:20.311Z",
"retryScheduledFor": null,
"costMicro": 6370000,
"currency": "INR",
"quality": {
"turns": 14,
"responseMs": {
"median": 1180,
"p90": 1920,
"max": 3410
},
"firstTokenMs": {
"median": 610,
"p90": 940,
"max": 1730
},
"longSilences": 1,
"longSilenceSeconds": 10,
"longestSilenceSeconds": 12.4,
"interruptions": 2,
"modelErrors": 0,
"rescues": 1
},
"usage": {
"inputTokens": 5120,
"outputTokens": 410,
"cachedInputTokens": 3584,
"inputTokensEstimated": false,
"ttsCharacters": 1840
},
"billing": {
"keys": "off",
"voicePlan": "standard",
"ratePerMinuteMicro": 1820000,
"billedSeconds": 210,
"currency": "INR"
},
"forwardedTo": null,
"error": null
}Authorizations
Your API key (ta_live_…) from Settings → API keys, sent as Authorization: Bearer <key>. Keep it on a server: it can message every customer you have. A key is full, build or read-only; a request its level does not allow is refused with 403.
Headers
Developers only: the customer workspace this request acts in — its org_… id from POST /customers. Leave it out to act in your own workspace. Refused with 404 (Workspace not found.) when the id is unknown, is not one of your customers, or is not an org_… id; 410 when that customer was deleted (restore it with POST /customers/{id}/restore until it is erased); 403 when the key belongs to one customer workspace (it cannot act as another); 400 when your workspace is not a developer workspace. /customers/* and GET /customers/usage are your own workspace's and refuse the header with 400: call them without it.
"org_3fKq9TzQ1mN8vB2xR7cLpA"
Path Parameters
The call's id as Place Call or List Calls gave it: out_… or sch_… for a call you placed, the call reference for any other.
"out_9f2c1a44-6b0e-4c1d-8a7f-2e5b3c9d1f60"
Response
The call.
One call and what it learned — the same object call.analysed delivers.
What the call was billed as. Null for a booked call that has not rung.
Carrier-only calls. A call that ended before the agent spoke, and a call forwarded to another number without an agent, run no agent (no recogniser, model or voice), so they are charged the phone carrier's fee only: ₹0.38 a minute in INR, charged in 30-second blocks (₹0.19 each; in USD at our conversion rate). billedSeconds is the length rounded up to the block. For these calls voicePlan and ratePerMinuteMicro still show the plan and rate the call was set up on, which is not what was charged: reconcile such a call by costMicro.
Free trial calls. voicePlan, ratePerMinuteMicro and billedSeconds are null for a call paid from a free-plan workspace's trial minutes. A call in a workspace on a paid plan, a developer's own test calls included, is billed from its balance and carries them.
Show child attributes
Show child attributes
The id to open it by: out_… / sch_… for a call you placed, the call reference otherwise.
The reference of the attempt that actually rang. Null on a call that has not rung.
Your reference from Place Call.
Your metadata from Place Call, untouched.
Show child attributes
Show child attributes
1 for the first try, 2 for the first retry.
x >= 1Where the call is. scheduled and cancelled only appear on calls you placed for later.
scheduled, ringing, connected, completed, missed, failed, cancelled Who rang whom.
inbound, outbound The customer's number.
Your number the call rang from. Null until it rings, unless the request chose one, and always null on a call that came in.
The agent on the call. Null on a call forwarded to a phone when no agent answered the number (forwardedTo is set).
Show child attributes
Show child attributes
When a booked call will ring. Null once it has.
When it started ringing.
When it was picked up.
When it ended.
How long it lasted. On a call forwarded to a phone (forwardedTo) this is how long the caller was connected - answer to hang-up - even when nothing was billed (a number you brought bills nothing for a forward). 0 for a forward nobody picked up (status missed).
x >= 0Why it ended. Null while live; not_placed for a booked call that never rang.
answered, no_answer, busy, rejected, unreachable, cancelled, voicemail, before_agent, failed, not_placed, null The {{name}} values the call used.
Show child attributes
Show child attributes
Two or three sentences about the call, when summarised.
The collected details, keyed by field name. Empty when nothing was said.
When the summary and fields were written. Null means they may still arrive.
Every agent the call was handed to mid-call, oldest first (set on the agent's Actions page, under Hand calls to another agent). Empty when it stayed with agent, which is always the agent the call was placed or answered as. A hand-off to another agent is not a hand-over to a person: it sends no conversation.escalated.
Show child attributes
Show child attributes
The phone this call was forwarded to, when the number forwards every call (forwardTo on the phone number) and no agent answered it. Null on every other call. A forwarded call has no transcript, summary or fields.
True once the call's recording and transcript were deleted — by Delete Call Content, or by the workspace's callRetentionDays. The summary, fields, transcript and recording are then empty; when it happened, how long it lasted and what it cost stay.
When its content was deleted; null while it is kept.
Why a booked call could not be placed, in words. Null otherwise.
This call's spoken turns, oldest first.
Show child attributes
Show child attributes
A signed link to the audio that needs no key — Get Recording By Signed Link. Null when the call was not recorded.
Show child attributes
Show child attributes
When the next try will ring, if this one did not reach them and another is queued.
What this call cost the workspace, in millionths of currency (6370000 is 6.37) — the figure GET /usage/calls gives, at a white-label reseller's price for its clients. Null until the call is settled. Settlement runs before call.analysed is sent, so the webhook normally carries it, but it is null there too when the call has not settled; read Get Call later for the figure.
The currency costMicro is in — the workspace's. Null only for a booked call that has not rung.
INR, USD, null How the call went, in numbers, written once when it ends. Null for a call that was not measured — a call from before call quality was recorded, a call that never connected, or one whose voice connection never reported. A figure inside is null when the part of the call that measures it did not report.
Show child attributes
Show child attributes
What the call used: the language-model tokens its replies used, whether the model is ours or your own key's (BYOK), and the characters sent to the voice. Each is null when it was not recorded: a call that never reached the model (a missed call, a forward, a booked call that has not rung). The input count is what the provider reported; where a provider reports none it is estimated from the prompt's length, and inputTokensEstimated says so. The call's summary and field extraction after it ends are not counted.
Show child attributes
Show child attributes