Part 2C — Calls, call-outs, OTP, reports ← Contents · Previous: Part 2B — Call flows · Next: Part 2D — Agents All endpoints: 🔒 Protected · Bearer API key. A call or call-out of another client app gives 404 . G. Calls and their reports Every call (in or out) is one record with a summary, a timeline of what happened, and — when something was recorded — audio and a transcript. The same summary arrives in the call.ended webhook ( Part 3 ). G1. List calls Endpoint : GET {base_url}/calls Query Type Required Description Default accountId uuid No One account (without it: all the client app's calls) from / to ISO instant No Started between ( 2026-11-13T00:00:00Z ) type string No INCOMING · BROADCAST · CAMPAIGN · OTP · AGENT_CALL · TEST result string No e.g. MISSED , VOICEMAIL ( Part 4 ) status string No e.g. LIVE for calls in progress number string No Calls from or to this E.164 number calloutId uuid No Calls placed by one call-out page / size integer No Page (from 0) and page size 0 / 50 Success Response JSON Sample (one call shown; each item is a G2 summary): { "success": true, "httpStatus": "200 OK", "message": "Calls", "action": null, "action_time": "2026-11-13T20:05:32.490000000", "data": { "calls": [ { "callId": "355760f8-51c0-47c8-b3b0-49c3612e4b96", "type": "INCOMING", "result": "VOICEMAIL", "…": "…" } ], "page": 0, "size": 50, "total": 65 } } Newest first. A wrong value for a filter → 400 Invalid value for parameter: . G2. Get a call Endpoint : GET {base_url}/calls/{callId} Success Response JSON Sample (a caller left a voicemail while waiting for an agent): { "success": true, "httpStatus": "200 OK", "message": "Call", "action": null, "action_time": "2026-11-13T20:05:32.497509178", "data": { "callId": "355760f8-51c0-47c8-b3b0-49c3612e4b96", "accountRef": "softphone", "accountId": "adb72fac-66a2-471b-a437-035fe008197d", "type": "INCOMING", "direction": "INBOUND", "from": "+255745051250", "to": "+255677000001", "status": "ENDED", "result": "VOICEMAIL", "endReason": "SCRIPT_END", "endedBy": "SYSTEM", "handledBy": "VOICEMAIL", "startedAt": "2026-11-13T16:45:27.909648Z", "answeredAt": "2026-11-13T16:45:27.909648Z", "endedAt": "2026-11-13T16:46:20.533012Z", "durations": { "ringSeconds": null, "totalSeconds": 53, "scriptSeconds": 16, "waitSeconds": 35, "talkSeconds": 0, "holdSeconds": 0, "aiSeconds": 0 }, "keys": null, "lastBlock": "vm", "outcomes": [], "usage": { "pstnSeconds": 53, "trunkSeconds": 53, "waitSeconds": 35, "aiSeconds": 0, "ttsChars": 0, "sttSeconds": 0 }, "providerCost": { "tzs": 25.61, "usd": 0.000893, "items": [ { "provider": "AT", "tzs": 25.61, "usd": 0.0, "lines": [ { "item": "AT_INBOUND", "qty": 1, "unit": "MINUTE", "rate": 17, "currency": "TZS", "amount": 17, "source": "RATE", "model": null }, { "item": "AT_SIP_TRUNK", "qty": 1, "unit": "MINUTE", "rate": 8.61, "currency": "TZS", "amount": 8.61, "source": "RATE", "model": null } ] }, { "provider": "OPENAI", "tzs": 0.0, "usd": 0.000893, "lines": [ { "item": "OPENAI_CHAT_IN", "qty": 474, "unit": "TOKEN", "rate": 1e-07, "currency": "USD", "amount": 4.74e-05, "source": "OPENAI", "model": "gpt-6-luna" }, { "item": "OPENAI_CHAT_OUT", "qty": 42, "unit": "TOKEN", "rate": 5e-07, "currency": "USD", "amount": 2.1e-05, "source": "OPENAI", "model": "gpt-6-luna" }, { "item": "OPENAI_TRANSCRIBE", "qty": 0.1833, "unit": "MINUTE", "rate": 0.0045, "currency": "USD", "amount": 0.00082485, "source": "MEASURED", "model": "gpt-transcribe" } ] } ] }, "recorded": true, "script": { "versionId": "e183c7f1-3137-4848-95c1-11a7e8bef17a", "version": 1, "ref": "desk-test" }, "calloutId": null, "hangupCause": null, "sipStatus": null, "meta": null } } Field Description type / direction What kind of call ( Part 4 ); INBOUND = someone called us from / to E.164 numbers. Incoming: caller → our number. Outgoing: our number → person status Live state; ENDED once over result How it went, set when it ends: HANDLED_BY_SCRIPT · HANDLED_BY_AGENT · HANDLED_BY_AI · VOICEMAIL · MISSED · ABANDONED · HUNG_UP_EARLY · REJECTED ; outgoing: ANSWERED · NO_ANSWER · BUSY · DECLINED · UNREACHABLE · INVALID_NUMBER · FAILED · NOT_DIALED endReason / endedBy Why and by whom it ended ( CALLER_HUNG_UP / CALLER , SCRIPT_END / SYSTEM …) handledBy Who dealt with the caller in the end: SCRIPT · AGENT · AI · VOICEMAIL answeredAt Incoming: when the engine picked up (= start). Outgoing: when the person answered; null if never durations (s) ringSeconds (outgoing, before answer) · totalSeconds · scriptSeconds (in blocks) · waitSeconds (waiting room) · talkSeconds (with an agent) · holdSeconds · aiSeconds keys Every key the caller pressed, in order ( "1234" ) lastBlock The block the call ended in outcomes Tags the flow set on the way ( callback_scheduled , opted_out , an App action's outcome…) usage Measured units: phone seconds ( pstnSeconds , trunkSeconds ), ttsChars (new text made into audio for this call), sttSeconds (caller speech transcribed) providerCost Cost to run it, per provider and line ( Part 1 §1.11 ) recorded Something was recorded: GET …/recording works script The flow version it ran calloutId Set when a call-out placed it hangupCause / sipStatus Outgoing calls that failed: short network reason ( 603 Decline , 486 Busy here ) and SIP code meta What the client app attached (call-out meta , OTP meta , scheduled callbacks' {said, scheduledBy} ) G3. Timeline of a call Purpose : Everything that happened, step by step: blocks entered, sentences said, keys, speech heard, rings, transfers, recordings. For a call detail screen and for support. Endpoint : GET {base_url}/calls/{callId}/timeline Success Response JSON Sample (first events): { "success": true, "httpStatus": "200 OK", "message": "Timeline", "action": null, "action_time": "2026-11-13T20:05:32.529813711", "data": [ { "seq": 1, "type": "CALL_RECEIVED", "block": null, "at": "2026-11-13T16:45:27.912895Z", "offsetMs": 3, "data": { "to": "+255677000001", "from": "+255745051250" } }, { "seq": 2, "type": "SAY", "block": null, "at": "2026-11-13T16:45:27.915036Z", "offsetMs": 5, "data": { "text": "Habari, unazungumza na huduma ya kidijitali ya Ringmaster Lab.", "voice": "marin" } }, { "seq": 4, "type": "BLOCK_ENTER", "block": "hi", "at": "2026-11-13T16:45:27.915108Z", "offsetMs": 5, "data": { "type": "say" } }, { "seq": 9, "type": "QUEUED", "block": "desk", "at": "2026-11-13T16:45:40.577Z", "offsetMs": 12668, "data": { "department": "Mapokezi" } }, { "seq": 12, "type": "WAIT_OPTION", "block": "desk", "at": "2026-11-13T16:46:03.869Z", "offsetMs": 35960, "data": { "key": "9", "exit": "vm" } }, { "seq": 16, "type": "VOICEMAIL", "block": "vm", "at": "2026-11-13T16:46:17.441Z", "offsetMs": 49532, "data": { "recorded": true } } ] } Field Description seq Order (gaps are possible) type What happened ( Part 4 — timeline events ) block The block it happened in, if any offsetMs Milliseconds since the call started data Details for that type (texts said, keys, speech, department, exit taken…) A SAY event is written when the sentence is queued to play; the audio itself follows in order. G4. Recording of a call Purpose : The MP3 of the call's latest recording (a voicemail, or the recorded part with an agent). Endpoint : GET {base_url}/calls/{callId}/recording Success Response : 200 , Content-Type: audio/mpeg , the audio bytes (not JSON). Stream it to the client app's users through its own backend (the API key must not reach a browser). Errors (JSON): 404 "No recording for this call" — nothing recorded, or not ready yet (wait for recording.ready ); 404 "Recording file missing" — deleted after retentionDays . G5. Transcript and summary Endpoint : GET {base_url}/calls/{callId}/transcript Success Response JSON Sample : { "success": true, "httpStatus": "200 OK", "message": "Transcript", "action": null, "action_time": "2026-11-13T20:05:32.551771069", "data": { "callId": "355760f8-51c0-47c8-b3b0-49c3612e4b96", "status": "READY", "language": "sw", "text": "Huu ndio ujumbe wangu, na shukrani sana.\n", "summary": "Mpigaji amesema huo ndio ujumbe wake na ametoa shukrani nyingi.", "sentiment": "positive", "unanswered": [], "fields": {}, "model": "gpt-6-luna", "updatedAt": "2026-11-13T16:46:27.176884Z" } } Field Description status READY · FAILED (transcription failed; text is empty) language Detected language ( sw , en ) text What was said summary One or two sentences, in the call's language sentiment positive · neutral · negative unanswered Questions the caller asked that the AI could not answer (for the knowledge base) fields Values the flow asked the summary to pick out (e.g. {"amount": "45000"} ), with fixed English keys Ready when the summary.ready webhook arrives. Before that, and when nothing was recorded or recording.transcribe is off: 404 "No transcript for this call". G6. Export calls (CSV) Endpoint : GET {base_url}/calls/export.csv Query Type Required Description Default accountId uuid Yes The account from / to date No Days YYYY-MM-DD , account time; at most 400 days the last 7 days Success Response : 200 , text/csv attachment, up to 100,000 rows, oldest first. Header row: callId,type,direction,fromE164,toE164,status,result,endReason,endedBy,handledBy,startedAt,answeredAt,endedAt,totalSeconds,waitSeconds,talkSeconds,aiSeconds,pstnSeconds,trunkSeconds,ttsChars,sttSeconds,hangupCause,sipStatus,keys,lastBlock,calloutId,agentRef,outcomes,meta G7. Agent calls a number (click to call) Purpose : An agent calls a customer from the browser, from one of the account's numbers. The engine dials; the agent joins the call room with the token returned and hears it ring. Endpoint : POST {base_url}/calls/agent Request JSON Sample : { "accountId": "adb72fac-66a2-471b-a437-035fe008197d", "numberId": "8a8d9c13-bda2-4a18-8410-c5ec49ed2c66", "to": "+255745051250", "agentRef": "asha", "meta": { "ticket": "T-1042" } } Parameter Type Required Description accountId uuid Yes The account numberId uuid Yes Calling from (one of the account's numbers) to string Yes Tanzanian number agentRef string Yes The agent who calls meta object No Kept on the call, returned in its summary and webhooks Success Response JSON Sample ( 201 Created ): { "success": true, "httpStatus": "201 CREATED", "message": "Calling", "action": null, "action_time": "2026-11-13T20:10:00.000000000", "data": { "callId": "6a1f…", "room": { "url": "wss://", "room": "call-6a1f…", "identity": "agent-0ea57aeb-…", "token": "eyJhbGciOi…" } } } The browser joins room with token (LiveKit JS SDK, microphone on). The agent is BUSY until the call ends. Errors : 404 "Agent not found: asha" · 409 AGENT_BUSY · 403 CAN_CALL_REFUSED (the client app's can-call check said no, Part 3 ) · 400 "Only Tanzanian numbers can be called". H. Call-outs (calling people) Rules applied to every call-out (quiet hours, opt-outs, retries, pace): Part 1 §1.5 . Call-outs play an Outgoing flow; its vars must be given for every person. Quick call: POST /v1/calls ─────────────────────────────── (created + people added + started in one go) Step by step: POST /v1/callouts → POST …/{id}/recipients (one or more times) → POST …/{id}/start DRAFT ─start─► SCHEDULED (startsAt later) ─► RUNNING ⇄ PAUSED ─► COMPLETED │ │ │ └──cancel──► CANCELLED ◄──cancel──┘ └──stop──► STOPPED H1. Quick call Purpose : Call 1–1000 people now with one request ("Habari Asha, oda yako iko tayari"). Endpoint : POST {base_url}/calls Request JSON Sample : { "accountId": "51f815ba-e9eb-4e29-9297-3c56033d32cd", "scriptVersionId": "9f0d2a77-…", "fromNumberId": "2c4e…", "name": "Order ready", "to": [ { "e164": "+255745051250", "vars": { "product": "Acetic Acid", "qty": "20" }, "meta": { "orderId": "ORD-88" } }, { "e164": "+255712345678", "vars": { "product": "Zinc Dust", "qty": "5" } } ], "maxTries": 3, "retryGapSec": 300, "meta": { "batch": "evening" } } Parameter Type Required Description Validation accountId uuid Yes The account scriptVersionId uuid Yes A version of an Outgoing flow of the account not revoked fromNumberId uuid Yes Caller ID: one of the account's numbers to array Yes People: {e164, vars?, meta?} 1–1000 to[].vars object When the flow has vars Values the flow says ( {product} ) every flow var, not blank to[].meta object No Kept on the person and their calls name string No Shown in lists default "API broadcast" maxTries integer No Tries per person (busy / no answer / unreachable / failed) 1–3, default 1 retryGapSec integer No Wait between tries 300–86400, default 300 meta object No Kept on the call-out Success Response : 201 Created , message "Calling", data = the call-out ( H7 ), already RUNNING (or SCHEDULED in quiet hours: it waits). Errors : 403 FEATURE_OFF "Call-outs are not enabled for this client app" (no CALLOUTS feature) 400 "Call-outs run Outgoing scripts only" · "Script version belongs to another account" 409 VERSION_REVOKED 422 VALIDATION_FAILED "Some people have no value for a script variable", data: [{"e164": "+2557…", "missing": "product"}] 422 VALIDATION_FAILED "Nobody can be called", data = the skipped list ( H3 ) H2. Create a call-out Purpose : A broadcast built in steps, or a campaign (a list called over days, in a window, at a pace). Endpoint : POST {base_url}/callouts Request JSON Sample (campaign): { "accountId": "51f815ba-e9eb-4e29-9297-3c56033d32cd", "externalRef": "debt-reminder-2026-11", "name": "Debt reminder November", "kind": "CAMPAIGN", "scriptVersionId": "9f0d2a77-…", "fromNumberId": "2c4e…", "startsAt": "2026-11-14T06:00:00Z", "endsAt": "2026-11-21T15:00:00Z", "windowFrom": "09:00", "windowTo": "17:00", "days": [1, 2, 3, 4, 5], "maxTries": 3, "retryGapSec": 3600, "pacePerMin": 30, "fallback": { "action": "send_sms", "params": { "text": "Habari {name}, tafadhali lipa deni lako la {amount}." } }, "meta": { "segment": "overdue-30" } } Parameter Type Required Description Validation / default accountId uuid Yes name string Yes not blank kind string Yes BROADCAST · CAMPAIGN scriptVersionId uuid Yes Outgoing flow version. May still wait for approval: the call-out shows waitingApproval: true and starts once approved not revoked fromNumberId uuid Yes Caller ID the account's number externalRef string No The client app's id startsAt instant No Don't call before ( start makes it SCHEDULED ) default: at start endsAt instant No Campaign: stop for good after this ( STOPPED ) windowFrom / windowTo HH:mm No Campaign: only call between these each day (account time) both or neither days int[] No Campaign: week days, 1 = Monday … 7 = Sunday quietOverride boolean No Call even in quiet hours (urgent notices only) default false maxTries integer No Tries per person 1–5, default 1 retryGapSec integer No Wait between tries ≥ 300, default 3600 pacePerMin integer No New calls per minute 1–600, default 60 fallback object No Campaign: after a person's last failed try, ask the client app to run one of its registered actions ( {action, params} ); not one that waits meta object No Success Response : 201 Created , message "Call-out created", data = the call-out, status: "DRAFT" . Errors : 400 "Give both windowFrom and windowTo" · "Window times must be HH:mm" · "Days are 1 (Monday) to 7 (Sunday)" · "fallback.action must be one of the client app's registered actions" · "A fallback action can't be one that waits for an outcome" · 403 FEATURE_OFF · the same flow errors as H1 . H3. Add people Purpose : Add people to a DRAFT call-out (call it several times for long lists). Endpoint : POST {base_url}/callouts/{id}/recipients Request JSON Sample : { "recipients": [ { "e164": "+255745051250", "vars": { "name": "Asha", "amount": "45000" }, "meta": { "customerId": "C-77" } }, { "e164": "0712345678", "vars": { "name": "Juma", "amount": "12000" } }, { "e164": "+14155550100", "vars": { "name": "Tom", "amount": "1" } } ] } Parameter Type Required Description Validation recipients array Yes {e164, vars?, meta?} ≤ 10,000 per request; every flow var given Success Response JSON Sample : { "success": true, "httpStatus": "200 OK", "message": "Recipients added", "action": null, "action_time": "2026-11-13T20:12:00.000000000", "data": { "added": 2, "skipped": [ { "e164": "+14155550100", "reason": "NOT_TANZANIAN" } ] } } skipped[].reason Means INVALID_NUMBER Not a phone number NOT_TANZANIAN Only +255 numbers are called DUPLICATE Already on this call-out (or twice in the request) OPTED_OUT On the account's opt-out list: kept as SKIPPED with result OPTED_OUT , never called Local numbers ( 0712… ) are turned into E.164. Errors : 409 LIST_LOCKED "The list is locked once a call-out starts; create a new call-out" · 422 VALIDATION_FAILED "Some people have no value for a script variable" (nobody added). H4. Start, pause, resume, stop, cancel Endpoint : POST {base_url}/callouts/{id}/{action} {action} From → to Refused with start DRAFT → RUNNING (or SCHEDULED when startsAt is later). Locks the list 409 ALREADY_STARTED · 409 NO_RECIPIENTS "Nobody to call" pause RUNNING / SCHEDULED → PAUSED ; calls in progress finish. Optional body {"reason": "…"} (default PAUSED_BY_CLIENT ) 409 NOT_RUNNING resume PAUSED → RUNNING 409 NOT_PAUSED stop any unfinished → STOPPED ; people not yet called are not called. Stopping a finished call-out changes nothing — cancel DRAFT / SCHEDULED → CANCELLED (nothing was dialled) 409 ALREADY_RUNNING "A running call-out is stopped, not cancelled" Success Response : 200 , message "Call-out start" (… "pause", "resume", "stop", "cancel"), data = the call-out. Unknown action → 400 "Unknown action: explode". The engine itself also pauses call-outs, with a pauseReason : ACCOUNT_SUSPENDED , VERSION_REVOKED , FEATURE_OFF (the owner took CALLOUTS away), … and sends callout.paused ( Part 3 ). It never resumes them by itself. H5. List call-outs Endpoint : GET {base_url}/callouts?accountId={accountId} Query Type Required Description accountId uuid Yes Missing → 400 Missing parameter: accountId Success Response : data = array of call-outs, newest first. Scheduled callbacks booked by callers are here too, with externalRef schedule:: . H6. Get a call-out's people Endpoint : GET {base_url}/callouts/{id}/recipients Query Type Required Description Default status string No PENDING · DIALING · DONE · SKIPPED all page / size integer No Page from 0; size up to 500 0 / 100 Success Response JSON Sample : { "success": true, "httpStatus": "200 OK", "message": "Recipients", "action": null, "action_time": "2026-11-13T20:05:37.426862727", "data": [ { "id": 11, "e164": "+255745051250", "status": "DONE", "result": "ANSWERED", "attempts": 1, "lastCallId": "fff4aa3f-8ed5-44e6-947c-c82bb3628c41", "answeredSeconds": 28, "keys": "1234", "outcomes": null, "meta": { "said": "After five minutes, baada ya dakika tano.", "scheduledBy": "ca10b2f7-a5a3-41bb-be8b-2e486b2b5dbf" }, "nextAttemptAt": null } ] } Field Description status PENDING (waiting or between tries) · DIALING · DONE · SKIPPED result The last try's result ( ANSWERED , NO_ANSWER , BUSY , DECLINED , OPTED_OUT …) attempts / nextAttemptAt Tries so far; when the next try is due (while PENDING ) lastCallId The last call to this person ( G2 ) answeredSeconds / keys / outcomes From the answered call H7. Get a call-out Endpoint : GET {base_url}/callouts/{id} Success Response JSON Sample (a callback a caller booked for "baada ya dakika tano"): { "success": true, "httpStatus": "200 OK", "message": "Call-out", "action": null, "action_time": "2026-11-13T20:05:37.397238463", "data": { "id": "510fca7b-b226-46ad-b80a-0082ab4ab0d5", "externalRef": "schedule:account-callback:+255745051250", "name": "Callback +255745051250", "kind": "BROADCAST", "status": "COMPLETED", "pauseReason": null, "waitingApproval": false, "scriptVersionId": "3bcb496b-e302-4a98-9e8e-fd3e4c80b768", "startsAt": "2026-11-13T14:41:00Z", "endsAt": null, "windowFrom": null, "windowTo": null, "days": null, "maxTries": 2, "retryGapSec": 300, "pacePerMin": 60, "total": 1, "byStatus": { "DONE": 1 }, "byResult": { "ANSWERED": 1 }, "byOutcome": {}, "createdAt": "2026-11-13T14:36:38.242481Z", "startedAt": "2026-11-13T14:36:38.282846Z", "completedAt": "2026-11-13T14:41:34.766757Z" } } Field Description status / pauseReason See the diagram above waitingApproval The flow version is not runnable yet; nobody is called until it is approved days Campaign days as text ( "1,2,3,4,5" ) total / byStatus / byResult / byOutcome Counts over its people H8. Call-out stats Endpoint : GET {base_url}/callouts/{id}/stats Success Response JSON Sample : { "success": true, "httpStatus": "200 OK", "message": "Call-out stats", "action": null, "action_time": "2026-11-13T20:05:37.463714267", "data": { "calloutId": "510fca7b-b226-46ad-b80a-0082ab4ab0d5", "total": 1, "byStatus": { "DONE": 1 }, "byResult": { "ANSWERED": 1 }, "byOutcome": {}, "byAttempts": { "1": 1 }, "byHour": [ { "key": "2026-11-13T17:00", "values": { "dialed": 1, "answered": 1, "noAnswer": 0, "busy": 0, "failed": 0, "seconds": 28 } } ] } } Field Description byAttempts People by the try that finished them ( {"1": 80, "2": 15, "3": 5} ) byHour[].key Hour in the account's time zone byHour[].values Calls dialled, answered, not answered, busy, failed; answered seconds H9. Export a call-out (CSV) Endpoint : GET {base_url}/callouts/{id}/export.csv Success Response : text/csv attachment, one row per person: e164,status,result,attempts,answeredSeconds,keys,outcomes,callId,meta,updatedAt +255745051250,DONE,ANSWERED,1,28,1234,,fff4aa3f-8ed5-44e6-947c-c82bb3628c41,"{""said"": ""After five minutes, baada ya dakika tano."", ""scheduledBy"": ""ca10b2f7-…""}",2026-11-13T14:41:34.763432Z M. OTP (a code by voice) M1. Call a code to a number Purpose : Read a one-time code to a person ("Namba yako ya siri ni moja, mbili, tatu, nne"), e.g. when SMS fails. Not subject to quiet hours. The code is kept encrypted and never shown in timelines or logs. Endpoint : POST {base_url}/otp Access Level : 🔒 Protected · Bearer API key · feature OTP Request JSON Sample : { "accountId": "adb72fac-66a2-471b-a437-035fe008197d", "to": "+255745051250", "code": "482913", "lang": "sw", "numberId": "8a8d9c13-bda2-4a18-8410-c5ec49ed2c66", "meta": { "purpose": "login" } } Parameter Type Required Description Validation accountId uuid Yes to string Yes Tanzanian number code string Yes Digits only 4–10 digits lang string No sw · en default: the account's language numberId uuid No Calling from default: the account's first number meta object No Kept on the call Success Response JSON Sample ( 201 Created ): { "success": true, "httpStatus": "201 CREATED", "message": "Calling", "action": null, "action_time": "2026-11-13T20:15:00.000000000", "data": { "callId": "a7c3…", "status": "CALLING" } } Follow the call with call.answered / call.ended webhooks (type OTP ). Errors : { "success": false, "httpStatus": "422 UNPROCESSABLE_CONTENT", "message": "Validation failed", "code": "VALIDATION_FAILED", "action_time": "2026-11-13T20:05:41.000000000", "data": { "code": "must match \"\\d{4,10}\"" } } 400 "Only Tanzanian numbers can be called" · 400 "This account has no number to call from" · 403 FEATURE_OFF · 429 RATE_LIMITED "Too many codes to this number; try again later" ( otpPerDestinationPer10Min ). N. Account stats N1. Calls per day, hour, number or type Purpose : A business dashboard: how many calls, how they ended, how long. Endpoint : GET {base_url}/accounts/{accountId}/stats Query Type Required Description Default from / to date No YYYY-MM-DD , account time; at most 400 days the last 7 days groupBy string No day · hour · number · type day Success Response JSON Sample ( groupBy=day ): { "success": true, "httpStatus": "200 OK", "message": "Account stats", "action": null, "action_time": "2026-11-13T20:05:41.000000000", "data": [ { "key": "2026-11-13", "values": { "incoming": 38, "outgoing": 2, "answered": 39, "byScript": 11, "byAgent": 3, "byAi": 9, "voicemail": 6, "missed": 0, "abandoned": 1, "hungUpEarly": 8, "seconds": 2311.0 } } ] } values (day / hour / number) Description incoming / outgoing Calls in / out answered Answered calls byScript / byAgent / byAi / voicemail Who dealt with them missed Callers who waited for an agent and nobody answered abandoned Callers who hung up while waiting hungUpEarly Callers who hung up in the first seconds seconds Total call seconds With groupBy=type , key is the call type and values = {calls, answered, seconds, pstnSeconds} : [ { "key": "BROADCAST", "values": { "calls": 2, "answered": 1, "seconds": 28, "pstnSeconds": 28 } }, { "key": "INCOMING", "values": { "calls": 38, "answered": 38, "seconds": 2283, "pstnSeconds": 2283 } } ] Errors : 400 "groupBy must be day, hour, number or type". Agents' stats: Part 2D .