SmileCloudDocs

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

FieldTypeDescription
idstringUnique call id.
directionstringinbound or outbound.
statusstring | nullanswered or no_answer.
extensionstring | nullThe clinic-side line that handled the call.
caller_phonestring | nullThe number that placed the call.
callee_phonestring | nullThe number that was dialed.
patient_phonestring | nullThe non-clinic side, whichever direction the call ran in.
started_atstring | nullISO 8601 start time.
ended_atstring | nullISO 8601 end time.
duration_secondsinteger | nullDerived from the timestamps.
notesstring | nullFree-text note written by clinic staff.
patientsobject[]Patient summaries matched on patient_phone.
recordingobject{ "available": boolean } - fetch the audio link separately.
transcriptobjectSee below.
created_atstring | nullISO 8601 timestamp.
updated_atstring | nullISO 8601 timestamp. Bumps when a transcript lands.

#The transcript object

FieldTypeDescription
statusstring | nullprocessing, done, failed, or null when transcription was never attempted.
summarystring | nullOne-line AI summary of the conversation.
segmentsarray | nullSpeaker 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 paramDescription
from, toCall start time, inclusive (ISO 8601 date or timestamp).
updated_sinceRows changed at or after this instant, oldest change first. See below.
directioninbound or outbound.
statusanswered or no_answer.
extensionThe clinic-side line.
phoneMatches either side of the call; separators are ignored.
patient_idCalls to or from that patient's number.
has_recordingtrue or false.
has_transcripttrue or false (a completed transcript).
response_formatconcise (default) or detailed to include transcript.segments.
bash
curl "https://api.smile-app.co.il/v1/calls?from=2026-07-01&status=no_answer" \
  -H "Authorization: Bearer sk_live_..."
json
{
  "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.

bash
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.

bash
curl "https://api.smile-app.co.il/v1/calls/8421?response_format=detailed" \
  -H "Authorization: Bearer sk_live_..."
json
{
  "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

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).

json
{
  "data": {
    "url": "https://s3.eu-central-1.amazonaws.com/...",
    "expires_at": "2026-07-24T00:49:00+03:00"
  }
}