MCP: prompt-cache hit rate and per-turn LLM timings in debug_call, new get_latency_summary tool
debug_call now returns the LLM-side numbers for a call alongside the caller-perceived latency it already reported: usage (prompt, completion and cached tokens, LLM call count, and prompt-cache hit percentage), turns (per-turn LLM time to first token, generation time and total turn time) and toolCalls (each tool’s execution time and context tokens). Before this, those numbers were only recoverable by parsing the raw event timeline.
Call actions endpoints removed from API reference
POST /call-actions, GET /call-actions, GET /call-actions/{id}, PUT /call-actions/{id}, and DELETE /call-actions/{id} are no longer part of the customer API surface and have been removed from the reference.
The routes remain in place for the dashboard, which uses cookie-session auth, but they were never reachable with a bearer API key. Any client that tried to call them with an API token received a 401. The API-ref section previously implied otherwise; that was incorrect.
Calls per second (CPS) — control how fast outbound calls start
You can now control how fast the platform starts your outbound calls, separately from how many run at once. Instead of sending requests slowly to protect your phone carrier, send everything in one go and tell us the rate your carrier accepts. Calls wait in the queue and start at exactly that rate. Nothing is dropped.
For numbers you import over SIP, org admins set the rate per SIP trunk on the Concurrency page. Every number on a trunk shares one rate, because that is where carriers enforce the limit. New trunks start at the safe default of 1 call/sec, and a change takes effect within about a second, including for calls already queued. Rented Smallest numbers are paced per provider by your plan.
PCA: aggregate limits on disposition metrics: combined prompt length and enum choices
The Write to draft endpoint now enforces two aggregate limits when the payload includes postCallAnalyticsConfig.dispositionMetrics:
- Combined
dispositionMetricPromptlength. The sum across all metrics must be ≤ 50,000 characters. Exceeding it returns400withThe combined disposition metric prompts can be at most 50000 characters. - ENUM choices per metric. Each
dispositionMetricType: ENUMmetric can have at most 20choices. Exceeding it returns400withEach enum metric can have at most 20 choices. Ones already over the limit can stay as they are, but can't grow any further. Remove the extra choices to save.
PCA: document the three no-transcript fallback shapes
Three call outcomes skip post-call analytics and return a fixed fallback in postCallAnalytics. Documented on the Post call metrics prose page and on the postCallAnalytics object description across the three call-response schemas.
Response is still 200; every dispositionMetrics[].value is null with confidence: 0 and a reasoning string. Exact strings:
Inbound SIP trunks: connection details for every trunk
Every inbound SIP trunk row on the SIP Trunks dashboard page now has a Connection details dialog. It shows the SIP origination host to point your carrier at, your numbers as entered, and a ready-to-paste example SIP URI with the transport suffix (;transport=tls preferred, ;transport=tcp fallback).
The same value is exposed in the API: GET /sip-trunk/inbound and POST /sip-trunk/inbound responses now include sipHost on every trunk. The host is derived at read time and is identical across your trunks.
Recordings: authenticated presigned-URL flow
New endpoint documented: GET /atoms/v1/recordings/{callId}?channel=mono|dual returns a short-lived presigned S3 URL for the call’s audio (atoms-platform#3625, Phase 1 of PRO-2775). Presigned URLs expire in 15 minutes. Response envelope is { status: true, data: { url: "..." } }.
Both channels are supported: channel=mono (default) for the composite track, channel=dual for stereo when the call was captured with per-side audio.
Telephony rework: SIP trunks as resources, agents answer, calls choose their caller ID
The telephony model is reorganized around one idea: who answers a number is durable configuration, what a call dials from is a property of the call. Full details and migration steps: Telephony API migration guide.
New
- SIP trunks are first-class resources, one per direction:
POST /sip-trunk/inboundandPOST /sip-trunk/outbound, with a dedicated SIP Trunks dashboard page. - An agent answers on a number or trunk via
POST /agent/{agentId}/answers; a source is answered by exactly one agent, and conflicts identify the agent holding it. - Every call names its caller ID:
fromNumberon outbound calls,fromNumbers(rotating, frozen at creation, retry-stable) on campaigns, and a per-agent transfer caller ID viaPUT /agent/{agentId}/transfer-source. - A temporary caller-ID bridge on the agent (
POST /agent/{agentId}/caller-ids): shared attachments that outbound calls without afromNumberdial from, first attached wins. Deprecated at introduction (responses carryDeprecation: true) and removed with the migration window; passfromNumberper call instead. - Guarded deletions everywhere: deleting a trunk still in use returns
409naming what uses it, and releasing a number an agent answers on or dials from is refused.
New page: SIP Wire Reference
New deep-dive page for SIP trunk integrators: SIP Wire Reference, linked from the SIP Trunking page.
It documents the exact wire contract, sourced from production packet captures: inbound and outbound call-flow ladders (including the digest-auth challenge on outbound), a real sanitised INVITE with its SDP, how each of your final responses is handled (what gets retried, what gets CANCELled), transfer semantics (a second outbound INVITE carrying X-Caller-ID, never SIP REFER, two channels per transferred call), the timer table (RTP keepalive, ringing, max duration), and how to debug with support using the SCL_ call ID that rides on the From tag of every INVITE we send.
SIP Trunking: UDP is accepted; the real hazard is fragmentation
Correction to the 2026-08-28 transport contract. The previous version stated our SIP ingress rejects UDP signalling outright. That was wrong: the ingress accepts UDP, TCP, and TLS, verified with a live OPTIONS probe over UDP answered with 200 OK.
What is actually true, and why the old advice still mostly worked. Full-size INVITEs (SDP body, several codecs, custom headers) can exceed the size a UDP datagram survives on the path. Fragments are silently discarded by many networks and firewalls, so the INVITE never arrives: no reply, no ICMP, retransmissions time out. A small OPTIONS ping over the same UDP path succeeds, which is what makes the failure look mysterious. Switching signalling to TCP or TLS fixes it, which is why the earlier “use TCP/TLS” recommendation resolved real integrations even though the stated reason was wrong.
Voice Agents: Tools registry and Secrets vault on the API reference
The reusable Tools library and Secrets vault now render on the API reference (and generate SDK methods).
Tools
GET /tool,POST /tool,PATCH /tool/{toolId},DELETE /tool/{toolId},POST /tool/{toolId}/duplicate: create org-level tools once and reference them from any agent.toolIdformattool_<24 lowercase alphanumerics>. Editing a tool propagates to every referencing agent; deleting one is blocked while agents still reference it.
API reference: schema and enum corrections against backend Zod validators
Atoms and Waves API reference updated to match what the backend actually enforces. Every change is Zod-derived and, where possible, live-verified against production.
Atoms
DELETE /agent/{id}/archive.onquery flipped from optionalboolean(defaulttrue) to required string enum"true" | "false". This matches the Zod validator; passing a JSON boolean was already rejected, the previous docs were misleading. See the endpoint description for the exact accepted values.GET /conversation/{callId}/recording/download-url. Added the callId regex pattern^CALL-\d{13}-[a-fA-F0-9]{6}$so the SDK types it correctly and clients see it in the API-ref.POST /conversation/{callId}/cancel. AddedminLength: 1on the path parameter (matches Zod).POST /campaign.namegainsmaxLength: 40.POST /knowledgebase.descriptiongainsmaxLength: 150.POST /audience.namegainsmaxLength: 80.PUT /account/update-org-name.nameminLength grew from 1 to 2, gainsmaxLength: 50.GET /product/get-available-numbersandPOST /product/rent-number.providerenum extended to[twilio, plivo, custom, whatsapp](was[plivo, twilio]) on both query and response.POST /product/import-phone-number. AddscpsLimit(number,minimum: 1,default: 1, capped server-side byCUSTOM_NUMBER_CPS_CEILING). Every imported number is always paced.slmModeland the threeCreateAgentRequestLLM enums. Extended to includegpt-5.2-azurealongsidegpt-5.2for Azure-hosted access.WorkflowTypeenum. Addsmulti_agentsalongside the existingworkflow_graphandsingle_prompt.multi_agentsis restricted; the server requiresslmModelto be one of[electron, gpt-5.2-azure].
Realtime Agent WebSocket: per-direction audio format contract
The realtime voice-agent WebSocket API now has a documented contract for the audio you send and the audio the agent sends back. Previously the only knob was sample_rate, and it silently set only the output; input audio was read at a hardcoded rate regardless of what the client asked for. That mismatch was invisible: the call worked, the transcription was wrong.
Save-agent API: `timezone` object shape, expanded language enum, native-types callout
Fixed two drifts on PUT /agent/{id}/branches/{branchId}/draft that were sending real integrations into hours of 400s.
timezone is an object, not a string. The UpdateBranchDraftRequest.timezone field was documented as a bare string; the backend expects {"label": "(GMT+5:30) Asia/Kolkata", "offset": 330}. A brand-new customer sending "Asia/Kolkata" was refused with Invalid config: timezone: Expected object, received string for 48h before we caught it. Corrected + example added.
SIP Trunking: transport contract, E.164 formatting, and a real troubleshooting section
SIP Trunking is rewritten to document what actually works and to remove guidance that was silently wrong.
The transport contract. Our SIP ingress accepts TCP (port 5060) and TLS (port 5061). UDP INVITEs are dropped with no response, no rejection, no ICMP. The origination URL your dashboard shows is bare (sip:YOUR_SIP_INGRESS.sip.smallest.ai); customers need to append ;transport=tls (preferred) or ;transport=tcp when they paste it into their provider or SBC. That single missing parameter is what has been costing hours on new integrations. The page now leads with the transport table, the two working URL shapes, and a sipsak OPTIONS ping you can run to confirm reachability.
Voice Agents API reference: Agents-first ordering, widget endpoints deprecated
The API reference sidebar now opens with Agents at the top, followed by Calls, Campaigns, Phone Numbers, and Knowledge Base. User, Account, and Billing sit at the bottom. Matches the ordering pattern used by every peer voice-AI reference (Vapi, Retell, Bland, Deepgram Voice Agent, ElevenLabs Conversational AI). No URL slugs changed; only the sidebar ordering.
Voice Agents: Account, Web Call, and Campaign export endpoints on the API reference
Six previously undocumented Voice Agents endpoints now render on the API reference:
Account
GET /account/get-account-details: user profile plus the orgs the user belongs toPUT /account/update-org-name: rename the org scoped by the API key (owner role)
Web Call
Voice Agents: Subscription and plan-limits endpoint on the API reference
One previously undocumented Voice Agents endpoint now renders on the API reference:
User
GET /user/subscription: the org’s plan id, credit balance, per-planlimits(agents, campaigns, numbers, daily and concurrent calls, knowledge-base sizes), and thefeaturesflags that gate capabilities
SDK 5.5.0: typed errors, waves helpers, CLI expansion, crew custom-LLM gotcha, warm/cold transfer clarified
Docs updates for the smallestai 5.5.0 release, plus the sibling platform fix for crew transfer audio.
Typed errors with actionable hints. Plan or entitlement-gated requests (HTTP 400 with “…upgrade to a higher plan…”) now raise PlanNotEntitledError (subclass of BadRequestError), importable from smallestai or the new smallestai.errors module. Error messages carry an actionable hint: 401 points at SMALLEST_API_KEY, plan-gated 400 points at upgrading, org-gated 403 points at the account team.
New docs: smallestai agents CLI, expanded SDK overview, quickstart env + layout FAQs
Three updates under Developer → Get Started.
Agents CLI reference. New page walking every command under smallestai agents (create, list, get, dashboard, phone-status, call) with argument and option tables, an end-to-end example, and the SMALLEST_API_KEY / SMALLEST_BASE_URL env-var contract.
SDK overview expanded. What is Atoms Agent Crews SDK? now covers the full picture in one page. The crew, node, and crew-code term model. The two independent versioning axes (config vs builds) with a summary table. An eight-step lifecycle from create to live call. A versioning API sample. A working end-to-end sample (server.py, assistant.py, requirements.txt). A six-item FAQ that names the common gotcha: agent-crew links to an existing agent, it doesn’t create one.

