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.