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

pip install callingbox

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=...).

Custom API base URL

The SDK uses https://api.callingbox.io by default. If your organization uses a private CallingBox deployment, set the base URL via the environment and optional constructor argument:
export CALLINGBOX_BASE_URL=https://your-deployment.example
export CALLINGBOX_API_KEY=sk_live_...
from callingbox import Callingbox

client = Callingbox(
    api_key="sk_live_...",
    base_url="https://your-deployment.example",
)

Module-level usage

The SDK exposes callingbox.calls and callingbox.numbers as lazy module-level accessors backed by a default client:
import callingbox

numbers = callingbox.numbers.list()
calls = callingbox.calls.list()
For agents (and anywhere else you’d rather be explicit), use a Callingbox(...) instance:
from callingbox import Callingbox

client = Callingbox()
agents = client.agents.list()
The rest of this page uses an explicit client for consistency, since every call dispatch needs an agent_id.

Manage phone numbers

Numbers are the connection between agents and the outside world. The Python SDK exposes the same public number APIs as the dashboard:

List your numbers

from callingbox import Callingbox

client = Callingbox()

for number in client.numbers.list():
    print(number.e164, number.status, number.inbound_agent_id)

Search for available numbers

available = client.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 = client.numbers.purchase("+14155551234")
print(number.e164)

Create an outbound agent

Agents are where persona, instructions, voice, language, returns schema, tools, and caller IDs live. Create one once, then dispatch calls against it.
from callingbox import Callingbox

client = Callingbox()

agent = client.agents.create(
    name="Appointment reminders",
    type="outbound",
    instructions="Confirm dental appointments. Offer to reschedule if needed.",
    returns={"confirmed": "boolean", "reschedule_to": "string"},
    number_ids=[number.id],
    primary_number_id=number.id,
)

print(agent.id)

Dispatch a call

Once you have an outbound agent with an attached number, calls.create(...) needs only agent_id and to. Everything else is optional per-call overrides.
call = client.calls.create(
    agent_id=agent.id,
    to="+15551234567",
    context={"patient": "Maria Lopez", "doctor": "Dr. Chen"},
)

print(call.id, call.status)

Choose a specific caller ID

In Python, the argument is from_ because from is a reserved keyword:
call = client.calls.create(
    agent_id=agent.id,
    to="+15551234567",
    from_="+15557654321",
)
The SDK sends that to the API as from_number. The value must already be attached to the agent; otherwise the API returns 400.

Replace instructions for a single call

Per-call instructions wholly replace the agent’s default for this one execution. Persona, voice, and tools stay the same.
call = client.calls.create(
    agent_id=agent.id,
    to="+15551234567",
    instructions="Follow up on the invoice sent last week. Negotiate a payment plan if needed.",
)

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

call = client.calls.create(agent_id=agent.id, to="+15551234567")

terminal = {"completed", "no_answer", "busy", "canceled", "failed"}
while call.status not in terminal:
    time.sleep(2)
    call = client.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 (inbound and outbound)
calls = client.calls.list()

# Retrieve a single call by ID
call = client.calls.retrieve("CALL_ID")
print(call.direction, call.agent_id, call.status)
print(call.result)

Fetch the transcript

The transcript is stored separately from the call object. Fetch it on demand:
segments = client.calls.retrieve_transcript("CALL_ID")
for s in segments:
    print(f"{s.role}: {s.text}")

Error handling

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

try:
    call = client.calls.create(agent_id=agent.id, 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}")

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 with the same API key and /v1 endpoints:
callingbox login
callingbox call \
  --agent YOUR_AGENT_ID \
  --to "+15551234567"
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.