Docs/SDKs/Python

Python SDK

pip install wordcab. Python 3.9+. Sync and async. httpx under the hood, Pydantic models on top.

Install

bash
pip install wordcab
# async only:
pip install "wordcab[async]"

Requires Python 3.9+. No native dependencies; the SDK is pure Python with httpx under the hood.

Create a client

python
from wordcab import Wordcab

client = Wordcab()                                      # reads WORDCAB_API_KEY
client = Wordcab(api_key="wc_live_...")                 # explicit
client = Wordcab(base_url="https://wc.internal.example.com")   # self-hosted
client = Wordcab(timeout=30, max_retries=5)

Async

python
from wordcab import AsyncWordcab
import asyncio

async def main():
    async with AsyncWordcab() as client:
        agents = await client.agents.list()
        async for a in client.agents.auto_paging_iter():
            print(a.id, a.name)

asyncio.run(main())

Resources

Every resource mirrors the API:

python
client.transcripts.create(audio_url=..., model="qwen3-asr")
client.transcripts.get(transcript_id)
client.transcripts.list(limit=50)
client.transcripts.delete(transcript_id)
client.transcripts.wait(job_id, poll_interval=2, timeout=600)  # helper

client.audio.speech.create(...)
client.audio.speech.stream(...)
client.audio.transcriptions.stream(model="voxtral-realtime", ...)

client.agents.create(...)
client.agents.calls.create(agent_id=..., phone_number=...)
client.calls.get(call_id)
client.calls.end(call_id)

client.test_suites.create(...)
client.test_suites.runs.create(suite_id=..., agent_id=...)

client.deployments.list()
client.api_keys.create(name=..., scopes=[...])
client.webhooks.create(url=..., events=[...])

Streaming

python
# Chat streaming
stream = client.chat.completions.create(
    model="qwen3.5-4b",
    messages=[...],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

# TTS streaming
with client.audio.speech.stream(
    input="...", model="qwen3-tts", voice="ember", format="pcm16", sample_rate=24000
) as audio:
    for frame in audio:
        sink.write(frame)

# STT WebSocket streaming
async with client.audio.transcriptions.stream(
    model="voxtral-realtime", sample_rate=16000
) as stt:
    await stt.send_audio(pcm_bytes)
    async for evt in stt:
        print(evt.type, evt.text)

Errors

python
from wordcab.errors import (
    APIError,
    AuthenticationError,
    NotFoundError,
    PermissionError,
    RateLimitError,
    ValidationError,
)

try:
    agent = client.agents.get("missing")
except NotFoundError as e:
    print(e.message, e.request_id)

Logging

The SDK uses stdlib logging under the wordcab logger. Set to DEBUG to see request ids, URLs, and retry counts — never bodies (which may contain audio or PHI).

python
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger("wordcab").setLevel(logging.DEBUG)

Typed models

Every response is a Pydantic model. Use .model_dump() / .model_dump_json() for serialization, .model_validate() to parse webhook bodies.