Calls
Calls are the clinic's phone log: who called, when, whether it was answered, and - when the clinic has AI features and call recording enabled - an AI summary and a speaker-by-speaker transcript. All endpoints require the calls:read scope.
Calls carry no patient foreign key. The link to a patient is a phone-number match made when you read, so patients may contain more than one person (a shared household number) or none at all.
#The call object
| Field | Type | Description |
|---|---|---|
id | string | Unique call id. |
direction | string | inbound or outbound. |
status | string | null | answered or no_answer. |
extension | string | null | The clinic-side line that handled the call. |
caller_phone | string | null | The number that placed the call. |
callee_phone | string | null | The number that was dialed. |
patient_phone | string | null | The non-clinic side, whichever direction the call ran in. |
started_at | string | null | ISO 8601 start time. |
ended_at | string | null | ISO 8601 end time. |
duration_seconds | integer | null | Derived from the timestamps. |
notes | string | null | Free-text note written by clinic staff. |
patients | object[] | Patient summaries matched on patient_phone. |
recording | object | { "available": boolean } - fetch the audio link separately. |
transcript | object | See below. |
created_at | string | null | ISO 8601 timestamp. |
updated_at | string | null | ISO 8601 timestamp. Bumps when a transcript lands. |
#The transcript object
| Field | Type | Description |
|---|---|---|
status | string | null | processing, done, failed, or null when transcription was never attempted. |
summary | string | null | One-line AI summary of the conversation. |
segments | array | null | Speaker turns, each { speaker, text, start_seconds }. Populated only when you pass response_format=detailed; the key is always present. |
Transcripts and recordings are patient conversations
A transcript is the textual equivalent of listening to the call. Both it and the recording link are covered by the single calls:read scope - only grant that scope to integrations that genuinely need to read what patients said.
#List calls
GET
Returns a paginated list, newest call first.
| Query param | Description |
|---|---|
from, to | Call start time, inclusive (ISO 8601 date or timestamp). |
updated_since | Rows changed at or after this instant, oldest change first. See below. |
direction | inbound or outbound. |
status | answered or no_answer. |
extension | The clinic-side line. |
phone | Matches either side of the call; separators are ignored. |
patient_id | Calls to or from that patient's number. |
has_recording | true or false. |
has_transcript | true or false (a completed transcript). |
response_format | concise (default) or detailed to include transcript.segments. |
curl "https://api.smile-app.co.il/v1/calls?from=2026-07-01&status=no_answer" \
-H "Authorization: Bearer sk_live_..."
{
"data": [
{
"id": "8421",
"direction": "inbound",
"status": "no_answer",
"extension": "036477878",
"caller_phone": "0522859234",
"callee_phone": "036477878",
"patient_phone": "0522859234",
"started_at": "2026-07-23T14:49:00+03:00",
"ended_at": "2026-07-23T14:49:20+03:00",
"duration_seconds": 20,
"notes": null,
"patients": [{ "id": "8842", "first_name": "Dana", "last_name": "Levi" }],
"recording": { "available": false },
"transcript": { "status": null, "summary": null, "segments": null },
"created_at": "2026-07-23T14:49:25+03:00",
"updated_at": "2026-07-23T14:49:25+03:00"
}
],
"next_cursor": null
}
#Syncing incrementally
Transcription finishes minutes or hours after a call ends, so a row can change long after its started_at. Poll with updated_since - it orders by the change time, oldest first - and store the highest updated_at you have seen as your next watermark. Ordering by call time would miss those late updates.
curl "https://api.smile-app.co.il/v1/calls?updated_since=2026-07-23T14:00:00%2B03:00" \
-H "Authorization: Bearer sk_live_..."
#Retrieve a call
GET
Pass response_format=detailed for the full transcript.
curl "https://api.smile-app.co.il/v1/calls/8421?response_format=detailed" \
-H "Authorization: Bearer sk_live_..."
{
"data": {
"id": "8421",
"direction": "outbound",
"status": "answered",
"duration_seconds": 80,
"transcript": {
"status": "done",
"summary": "The clinic representative called technical support about a receipt issue; it was resolved during the call.",
"segments": [
{ "speaker": "clinic representative", "text": "Hello?", "start_seconds": 2 },
{ "speaker": "patient", "text": "Yes, can you hear me?", "start_seconds": 7 }
]
}
}
}
#List a patient's calls
GET
Same object and pagination, restricted to calls matching that patient's phone number. A patient with no phone on file returns an empty list rather than an error.
#Get a recording link
GET
Mints a short-lived signed URL to the call audio. Fetch it when you are about to play or download the file - the link expires, so it should not be cached or stored. Returns 404 when the call has no recording (unanswered calls, or recording disabled for the clinic).
{
"data": {
"url": "https://s3.eu-central-1.amazonaws.com/...",
"expires_at": "2026-07-24T00:49:00+03:00"
}
}