saperly

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/sdk
pip install saperly

No 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 with keys:admin for 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.

On this page