Core concepts
The Saperly model — numbers, connections, your prepaid balance, workspaces, and the compliance layer that wraps them.
A short mental model. Saperly has five moving parts: numbers, connections, your balance, workspaces, and the compliance layer that wraps them. Everything else is built on these.
Numbers
A number is a real phone number provisioned under your workspace. Provision one with a country, type, and optional area code:
{ "country": "US", "numberType": "local", "areaCode": "415" }Each number carries its price (monthlyPriceCents) and the connectionId of the
handler bound to it. Monthly rent is swept automatically against your prepaid
balance, idempotent per billing period. Releasing a number soft-deletes it
(releasedAt is set) and stops the rent.
See the Numbers guide.
Connections
A connection is the handler bound to a number — the thing that answers. A
connection has a mode:
- Hosted — an in-network voice assistant (speech-to-text → LLM → text-to-speech). Bring your own OpenAI-compatible LLM, pick a TTS voice, and optionally declare MCP servers the assistant can call.
- Manual — bring your own LLM as the brain. Saperly forwards each text
turn to your agent (over an HTTP endpoint or an outbound websocket) and
executes the directives it returns (
speak,wait_for_user,hangup,transfer,send_dtmf).
One number → one connection. The same connection can answer many numbers. See Connections and Manual mode.
Your balance (prepaid)
Saperly is prepaid. You top up a balance; usage is metered against it through a reserve → settle → release cycle:
- Reserve — before an action (a call, a number), funds are held. You can never over-spend a balance or a scoped key's spend cap — the reservation simply fails first.
- Settle — after the action, the actual cost is applied.
- Release — if the action never happens, the held funds return.
Top up manually or enable auto-recharge. See Billing.
Workspaces & tenancy
A workspace is your tenant. Members are humans (with roles); agents
authenticate with scoped sk_ API keys. The workspace an action belongs to is
always read from the credential — never from client input — so a key can only
ever touch its own workspace's data.
See Authentication.
Compliance
Consent, disclosures, and 10DLC registration are first-class and enforced independently of any LLM — so a model you swap out can never route around them:
- Consent — record
implied_inbound/explicit_outboundconsent per (number, peer), check it before outbound contact, and revoke onSTOP. - Disclosures — the AI/TCPA notice lives on a connection (
complianceEnabled+disclosure); when on, it is spoken as the line's first, uninterruptible utterance. - 10DLC — register a campaign (brand + use case) so your US SMS is carrier-certified and delivers reliably.
See Compliance.
Audio stays in-network
Saperly runs the phone network for you, and call audio never reaches your servers. Saperly handles signaling, identity, compliance, the record, and billing; your code only ever sees text and tool calls.
Even in manual mode, where your LLM is the brain, speech-to-text and text-to-speech happen in-network — you receive transcribed turns and return directives, and no audio socket is ever opened to your server. That's what keeps Saperly simple to run at scale: no media pipeline to operate, no audio egress, and nothing of yours that has to be online for a call to happen.
Two ways to call the API
Saperly exposes the same capabilities through two REST surfaces:
| Surface | Style | Best for |
|---|---|---|
| v2 (current) | camelCase, scoped sk_ keys | new integrations, fleets, MCP |
| v1 (SDK-compatible) | snake_case, wrapped envelopes | the published @saperly/sdk / saperly SDKs |
Both run over the same backend. The SDKs target v1; the API reference documents every endpoint of both.
Your first call
Provision a hosted line, call it, and read back the transcript — the voice version of the quickstart, in about five minutes.
Node / TypeScript
@saperly/sdk is the typed, zero-dependency TypeScript client for Saperly — provision numbers, send SMS, place calls, and verify webhooks with full IntelliSense.