Skip to main content
The CallingBox Python SDK wraps the same public /v1 API you see in the API Reference, but gives you a more natural Python interface for managing numbers, creating calls, polling for results, and handling errors.

Install

If you’re using the published package:
pip install callingbox
If you’re working from this monorepo locally:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ./py-sdk

Authenticate

The SDK reads your API key from CALLINGBOX_API_KEY by default:
export CALLINGBOX_API_KEY=sk_live_...
Then you can use the module-level client:
import callingbox

numbers = callingbox.numbers.list()
If you prefer to manage your own client instance:
from callingbox import Callingbox

client = Callingbox(api_key="sk_live_...")
numbers = client.numbers.list()
The Python SDK does not use callingbox.api_key = "...". Authentication is environment-based or explicit through Callingbox(api_key=...).

Run against a local backend

For local development, point the SDK at your local backend instead of production:
export CALLINGBOX_BASE_URL=http://localhost:3002
export CALLINGBOX_API_KEY=sk_test_...
Now the default import callingbox flow will use your local server:
import callingbox

numbers = callingbox.numbers.list()
You can also pass the base URL explicitly:
from callingbox import Callingbox

client = Callingbox(
    api_key="sk_test_...",
    base_url="http://localhost:3002",
)

Module-level usage

The simplest way to use the SDK is the module-level default client:
import callingbox

call = callingbox.calls.create(
    to="+15551234567",
    prompt="Confirm appointment tomorrow 2pm",
    context={"patient": "Maria Lopez"},
    returns={"confirmed": "boolean"},
)
This works because callingbox.calls and callingbox.numbers are lazy module-level accessors backed by a default client.

Manage phone numbers

Every outbound call needs a caller ID. The Python SDK exposes the same public number APIs as the dashboard:

List your numbers

import callingbox

numbers = callingbox.numbers.list()
for number in numbers:
    print(number.e164, number.status)

Search for available numbers

available = callingbox.numbers.search_available(
    country_code="US",
    area_code="415",
    number_type="local",
    limit=10,
)

for number in available:
    print(number.phone_number, number.monthly_cost_cents)

Purchase a number

number = callingbox.numbers.purchase("+14155551234")
print(number.e164)

Create a call

Once your org has at least one active phone number, you can create outbound calls:
import callingbox

call = callingbox.calls.create(
    to="+15551234567",
    prompt="Confirm dental appointment tomorrow at 2pm for Maria Lopez",
    context={"patient": "Maria Lopez", "doctor": "Dr. Chen"},
    returns={"confirmed": "boolean", "reschedule_to": "string"},
)

print(call.id, call.status)
If you do not pass a caller ID, CallingBox uses your organization’s oldest active purchased number.

Choose a specific caller ID

In Python, the argument is from_ because from is a reserved keyword:
call = callingbox.calls.create(
    to="+15551234567",
    prompt="Confirm appointment tomorrow 2pm",
    from_="+15557654321",
)
The SDK sends that to the API as from_number. The value must be an active number owned by your organization.

Poll for completion

Call creation is immediate, but the conversation and result extraction happen asynchronously. Poll the call until it reaches a terminal status:
import time
import callingbox

call = callingbox.calls.create(
    to="+15551234567",
    prompt="Confirm appointment tomorrow 2pm",
    returns={"confirmed": "boolean"},
)

terminal = {"completed", "no_answer", "busy", "canceled", "failed"}
while call.status not in terminal:
    time.sleep(2)
    call = callingbox.calls.retrieve(call.id)

print(call.status)
print(call.result)
Terminal statuses are:
  • completed
  • no_answer
  • busy
  • canceled
  • failed

List and retrieve calls

# List recent calls
calls = callingbox.calls.list()

# Retrieve a single call by ID
call = callingbox.calls.retrieve("CALL_ID")
print(call.status)
print(call.result)

Error handling

The SDK raises typed exceptions based on the API response:
from callingbox import (
    APIError,
    AuthenticationError,
    BadRequestError,
    NotFoundError,
)

try:
    call = callingbox.calls.create(to="+15551234567")
except BadRequestError as exc:
    print(f"Invalid request: {exc.message}")
except AuthenticationError:
    print("Check your API key")
except NotFoundError:
    print("Resource not found")
except APIError as exc:
    print(f"API error [{exc.status_code}]: {exc.message}")

Full runnable example

For a complete example that:
  • checks whether your org already has a number
  • purchases one if needed
  • places a call
  • polls until the call finishes
  • prints the result
see the example script in the repo: You can run it with:
export CALLINGBOX_API_KEY=sk_live_...
python py-sdk/examples/quickstart.py +15551234567
If you’re running your backend locally:
export CALLINGBOX_BASE_URL=http://localhost:3002
export CALLINGBOX_API_KEY=sk_test_...
python py-sdk/examples/quickstart.py +15551234567

Command-line interface

The Python package also ships a callingbox CLI, gated behind an optional extra so SDK-only users don’t pick up the extra dependencies:
pip install 'callingbox[cli]'
After installing, you can place a call directly from your terminal — same API key, same /v1 endpoints:
callingbox login
callingbox call \
  --to "+15551234567" \
  --prompt "Confirm appointment tomorrow 2pm" \
  --returns '{"confirmed": "boolean"}'
The CLI is a first-class interface, not a demo — it supports the full call flow, cursor-paginated calls list / numbers list, JSON output for scripting, and shell completions. See the CLI reference for the full command catalog, auth resolution order, exit codes, and scripting tips.

Webhooks

Manage endpoints and verify signatures with callingbox.webhooks:
from callingbox import Callingbox

cb = Callingbox(api_key="sk_live_...")

# Create an endpoint (signing_secret is returned once)
endpoint = cb.webhooks.create_endpoint(
    url="https://your-server.com/callingbox-webhook",
    description="Production CRM sync",
    enabled_events=["call.completed", "call.failed"],
)
print(endpoint.signing_secret)  # whsec_... — store somewhere secure

# Verify an incoming webhook
event = cb.webhooks.construct_event(
    payload=request.body,                              # raw bytes
    sig_header=request.headers["CallingBox-Signature"],
    secret=os.environ["CALLINGBOX_WEBHOOK_SECRET"],
)
# event.type, event.data["call"] are now trustworthy

# Replay a failed delivery
cb.webhooks.redeliver("9c1d9f9e-21a1-4f6d-8fce-bf4a4b8a9e3f")
See Webhooks for the full integration guide.

Next steps

SDK overview

Compare the Python SDK, TypeScript SDK, CLI, and raw HTTP.

CLI

The callingbox command-line interface that ships with this package.

Call object

Understand every field returned by create, list, and retrieve.

Delivery

Polling vs webhooks for receiving results.