Skip to main content

Voxplo Python SDK

Zero-dependency Python client for the Voxplo Agent Outbound-Call API. Place objective-driven AI calls, poll for results, and verify webhooks using only the Python standard library.

Requires Python 3.8+. No third-party packages needed.


Quick start

Place a call and wait for the result

from voxplo import Client

client = Client(api_key="bys_ak_YOUR_KEY")

# Place an outbound call with an objective
call = client.place_call(
    to="+14155550123",
    objective="Confirm the appointment for tomorrow at 2pm and ask if they need to reschedule.",
    fields=[
        {"name": "confirmed", "type": "boolean"},
        {"name": "new_time", "type": "string"},
    ],
)
print("Placed:", call["callId"], "status:", call["status"])

# Poll until the call reaches a terminal status (default timeout: 180s)
result = client.wait_for_call(call["callId"], timeout=180, interval=5)
print("Final status:", result["status"])
print("Extracted fields:", result.get("extracted"))

List recent calls

calls = client.list_calls(limit=10)
for c in calls:
    print(c["callId"], c["status"])

Get a specific call

call = client.get_call("call_abc123")
print(call)

Call statuses

Status Meaning
queued Call accepted, waiting to be placed
in_progress Call is active
completed Call finished normally (terminal)
no_answer Recipient did not pick up (terminal)
voicemail Reached voicemail (terminal)
declined Recipient declined the call (terminal)
failed Call could not complete (terminal)

wait_for_call returns once the status is one of the five terminal states.


Webhook verification

Voxplo sends a X-BYS-Signature header with each webhook delivery. Verify it before processing the payload.

Flask example

from flask import Flask, request, abort
from voxplo import verify_webhook

app = Flask(__name__)
WEBHOOK_SECRET = "whsec_YOUR_SECRET"

@app.route("/webhook/bys", methods=["POST"])
def bys_webhook():
    sig = request.headers.get("X-BYS-Signature", "")
    raw_body = request.get_data(as_text=True)
    if not verify_webhook(sig, raw_body, WEBHOOK_SECRET):
        abort(400, "Invalid signature")
    payload = request.get_json()
    print("Call update:", payload["callId"], payload["status"])
    return "", 200

The signature format is t=<unix_seconds>,v1=<hex> where hex = HMAC-SHA256(secret, f"{t}.{raw_body}").

verify_webhook never raises. It returns False for invalid or expired signatures (default tolerance: 300 seconds).


Error handling

All API errors raise ByoursideError:

from voxplo import Client, ByoursideError

client = Client(api_key="bys_ak_YOUR_KEY")
try:
    client.place_call(to="+19001234567", objective="Sell something")
except ByoursideError as e:
    print(e.code)    # e.g. "destination_blocked"
    print(e.status)  # HTTP status, or 0 for network/timeout errors
    print(str(e))    # Human-readable message

Common error codes:

Code Meaning
destination_blocked Destination not allowed (premium, IRSF, or unsupported country)
invalid_number Number must be E.164, e.g. +14155550123
to_required Missing destination number
objective_required Missing call objective
caller_id_not_owned Caller ID not on your account
rate_limited Rate limit reached, retry shortly
over_minute_cap Outbound usage limit reached
unauthorized Invalid or missing API key
not_found Call ID not found
placement_failed Carrier or trunk issue, retry shortly
store_error Temporary service error, retry shortly
network_error Could not reach the API
timeout wait_for_call deadline exceeded

Development

Clone the repo. No install step needed for local use: run tests from the sdks/python/ directory so that voxplo/ is on the path automatically.

cd sdks/python
python3 -m unittest discover -s tests

Expected output: all tests pass (11 tests across errors, client, wait, and webhooks).

If your environment does not add CWD to the path automatically, use:

cd sdks/python
PYTHONPATH=. python3 -m unittest discover -s tests

Syntax check all source files:

python3 -m py_compile voxplo/errors.py voxplo/client.py voxplo/webhooks.py voxplo/__init__.py

Publishing to PyPI is deferred. Do not publish without explicit owner approval.

Metadata

Release files for voxplo 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for voxplo 0.1.0
File Size Uploaded Provenance Actions
voxplo-0.1.0.tar.gz 9.7 kB Without provenance Details for voxplo-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for voxplo 0.1.0
File Interpreter ABI Platform Actions
voxplo-0.1.0-py3-none-any.whl Python 3 none any Details for voxplo-0.1.0-py3-none-any.whl

Total release size: 17.1 kB

Release files / voxplo-0.1.0.tar.gz

Download URL voxplo-0.1.0.tar.gz
Size 9.7 kB
Tags Source
SHA-256 checksum
How to use checksums
972b1c7402531ee32641e0c18aa1d89598a91a7405680e2993c98e8e8623f927
BLAKE2b-256 checksum
How to use checksums
65b01e751c77d31d1a46926923d87342071869fee036877d57dbe49f2a5a0770
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release files / voxplo-0.1.0-py3-none-any.whl

Download URL voxplo-0.1.0-py3-none-any.whl
Size 7.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c482af60575d144cf450f74c0ed97c9f7873af870ba76b59e5d530875188cad
BLAKE2b-256 checksum
How to use checksums
59629228cc2d2acccab1a52efce297f7312f0718e6797500ece27d44df4c7dbc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Security for voxplo 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page