Quickstart
Provision a phone number for your agent in one API call, then send an SMS — in Node, Python, or curl.
Goal: get a working phone number attached to your agent and send your first message — in about five minutes. You'll need a Saperly account.
Signup is portal-only. Create an account at the dashboard, create your first workspace, and the onboarding wizard will walk you through the phone number, connection, setup output, and one-time API key reveal. You can also create or rotate keys later from Keys in the dashboard.
Install an SDK
The fastest path is one of the official SDKs. They are typed, dependency-light, and wrap the Saperly REST API.
npm install @saperly/sdkpip install saperlyNo install needed — every endpoint is plain HTTPS with a bearer token.
export SAPERLY_API_KEY=sk_live_...Provision a line
A line is a phone number plus the handler that answers it. Creating one in
hosted mode gives you a number backed by an in-network voice assistant — no
infrastructure of your own.
import { Saperly } from '@saperly/sdk'
const saperly = new Saperly({ apiKey: process.env.SAPERLY_API_KEY! })
const line = await saperly.lines.create({
name: 'my agent',
mode: 'hosted',
systemPrompt: 'You are a helpful assistant answering calls for Acme Inc.',
})
console.log(line.phoneNumber) // → +1...import os
from saperly import SaperlyClient
saperly = SaperlyClient(api_key=os.environ["SAPERLY_API_KEY"])
line = saperly.lines.create(
name="my agent",
mode="hosted",
system_prompt="You are a helpful assistant answering calls for Acme Inc.",
)
print(line.phone_number) # → +1...curl -X POST https://api.saperly.com/api/v1/lines \
-H "Authorization: Bearer $SAPERLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my agent",
"mode": "hosted",
"system_prompt": "You are a helpful assistant answering calls for Acme Inc."
}'That single call provisions a real number, certifies it, and attaches the assistant. Call the number and the hosted assistant answers — speech-to-text, the LLM, and text-to-speech all run in-network, so no call audio ever reaches your servers.
Send an SMS
const sms = await saperly.lines.sendSms(line.id, {
toNumber: '+15555550123',
message: 'Hi from my agent 👋',
})sms = saperly.lines.send_sms(
line.id,
to_number="+15555550123",
message="Hi from my agent 👋",
)curl -X POST "https://api.saperly.com/api/v1/lines/$LINE_ID/sms" \
-H "Authorization: Bearer $SAPERLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "to_number": "+15555550123", "message": "Hi from my agent 👋" }'What just happened
You provisioned a number. Saperly reserved it from the carrier, recorded it under your workspace, and started metering its monthly rent against your prepaid balance.
You attached a brain. In hosted mode the number is answered by an
in-network assistant. (Want your own LLM to be the brain? See
manual mode.)
You sent a message through a compliant path — consent state and disclosures are tracked automatically.
Next steps
- Core concepts — the model behind lines, connections, and the prepaid ledger.
- Voice channels — make your own agent (Claude Code / openclaw) phone-reachable.
- Authentication — scoped
sk_keys, spend caps, and minting per-agent child keys withkeys:adminfor fleets. - API reference — every endpoint with a try-it playground.
Two API versions
The SDKs above target Saperly's stable v1 API (/api/v1/*, snake_case). The
newer v2 API (camelCase: /numbers, /connections, /messages, /calls)
is documented in the API reference and is what you'll use
for new, scoped-key integrations. Both run over the same backend.