Skip to main content

Python SDK for the Vaani External API

Project description

vaani-sdk

Python SDK for the Vaani API. Authenticate once with your API key and call all available endpoints from clean, typed Python methods — both synchronous and asynchronous.

Installation

pip install vaani-sdk

Or install directly from source:

git clone https://github.com/your-org/vaani-sdk
cd vaani-sdk
pip install -e .

Quick Start

from vaani_sdk import VaaniClient

with VaaniClient(api_key="YOUR_API_KEY") as client:
    # Telephony call
    result = client.trigger_call(
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        contact_number="+919876543210",
        name="Rahul",
    )
    print(result.call_id)  # "outbound-1776774443-863aa698"

    # WebRTC session (same endpoint, different medium)
    result = client.trigger_call(
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        medium="webrtc",
        primary_language="en",
    )
    print(result.token)           # LiveKit participant JWT
    print(result.connection_url)  # wss://livekit.vaaniresearch.com

Configuration

Parameter Description Default
api_key Your Vaani API key (X-API-Key) (required)
base_url Base URL of the Vaani API https://api.vaanivoice.ai
timeout Request timeout in seconds 120.0
client = VaaniClient(
    api_key="YOUR_API_KEY",
    base_url="https://api.vaanivoice.ai",
    timeout=60.0,
)

Getting your API key

  1. Log in to app.vaanivoice.ai
  2. Navigate to Settings > API Keys
  3. Click Generate API Key, give it a descriptive name, and copy the key immediately

Your key is shown only once at creation time. Store it securely in an environment variable or secrets manager — never commit it to version control.

import os
from vaani_sdk import VaaniClient

client = VaaniClient(api_key=os.getenv("VAANI_API_KEY"))

API Reference

client.health()

Check the health of the Vaani API.

resp = client.health()
print(resp.status)   # "healthy"
print(resp.service)  # "vaani-external-api"

client.trigger_call(...)

Unified endpoint for telephony outbound calls and WebRTC voice sessions. Select the mode with the medium parameter.

Telephony

Parameter Type Required Description
agent_id str Yes Agent UUID from app.vaanivoice.ai
medium str No "telephony" (default)
contact_number str Yes Phone number in E.164 format (e.g. +919876543210)
name str Yes Customer display name
voice str No Override the agent's default voice for this call
metadata dict No Template variables injected into the agent's prompt at call time
outbound_number str No Override the caller ID (E.164). Must be configured in Telephony settings
sip_trunk_id str No SIP trunk identifier
test_mode bool No When True, simulates the call without placing it
dnd_check_skipped bool No Skip Do-Not-Disturb registry check
modify_agent ModifyAgentConfig No Inline agent config overrides for this call
result = client.trigger_call(
    agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
    contact_number="+919876543210",
    name="Rahul Sharma",
    metadata={
        "customer_name": "Rahul Sharma",
        "property_name": "Prateek Laurel",
    },
    outbound_number="+919873446283",
)
print(result.call_id)  # "outbound-1776774443-863aa698"
print(result.raw)      # full API response dict

Telephony response shape:

{
  "success": true,
  "message": "Call initiated successfully",
  "output": {
    "agent_name": "my-sales-agent",
    "call_id": "outbound-1776774443-863aa698",
    "live_captions_url": "wss://api.vaanivoice.ai/api/live-transcripts/ws/outbound-..."
  }
}

WebRTC

Parameter Type Required Default Description
agent_id str Yes Agent UUID
medium str Yes "webrtc"
voice_gender str No "female" "male" or "female"
primary_language str No "hi" Primary language code (e.g. "en", "hi")
secondary_language str No "en" Secondary language code
welcome_message str No None Custom opening message
welcome_interruptible bool No True Can the user interrupt the welcome message
bg_noise_enabled bool No False Enable background noise
bg_noise_volume int No 60 Background noise volume (0–100)
voice_speed float No 1.0 Voice speed multiplier (0.6–1.4)
metadata dict No {} Arbitrary key-value pairs
modify_agent ModifyAgentConfig No None Inline agent overrides
result = client.trigger_call(
    agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
    medium="webrtc",
    primary_language="en",
    voice_gender="female",
    welcome_message="Hi! How can I help you today?",
)
print(result.token)            # LiveKit participant JWT
print(result.room_name)        # "room_<agent_id>_<hash>"
print(result.connection_url)   # "wss://livekit.vaaniresearch.com"
print(result.live_captions_url)# WebSocket URL for live transcription

WebRTC response shape:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "room_name": "room_d62cc9bd-2f51-4581-9f38-6c3b7d58a988_abc123",
  "agent_name": "my-agent",
  "connection_url": "wss://livekit.vaaniresearch.com",
  "live_captions_url": "ws://api.vaanivoice.ai/api/live-transcripts/ws/room_..."
}

ModifyAgentConfig

Inline agent configuration overrides applied for the duration of this call only. Works for both mediums.

from vaani_sdk import VaaniClient
from vaani_sdk.models import ModifyAgentConfig

result = client.trigger_call(
    agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
    contact_number="+919876543210",
    name="Rahul",
    modify_agent=ModifyAgentConfig(
        persona={
            "identity": {
                "system_prompt": "You are a concise support agent. Keep answers under 2 sentences."
            }
        },
        training={
            "know_how": {
                "faq": {"What are your hours?": "9 AM to 5 PM."}
            }
        },
    ),
)
Field Type Description
persona dict Persona section override
training dict Training section override
experience dict Experience section override
analysis dict Analysis section override

client.get_call_history(page, page_size)

Retrieve paginated call history for the authenticated user's workspace.

Parameter Type Default Description
page int 1 Page number (1-indexed)
page_size int 50 Records per page (max 200)
history = client.get_call_history(page=1, page_size=20)

print(history.pagination.total)        # e.g. 1028
print(history.pagination.total_pages)  # e.g. 21

for call in history.data:
    print(call.call_id, call.raw.get("call_status"), call.raw.get("duration_ms"))

client.get_transcript(call_id)

Retrieve the full conversation transcript for a completed call.

transcript = client.get_transcript("outbound-1776774443-863aa698")
print(transcript.transcript)

client.get_call_details(call_id)

Get detailed call information including transcript, extracted entities, evaluation, and AI-generated summary.

details = client.get_call_details("outbound-1776774443-863aa698")
print(details.raw.get("summary"))
print(details.raw.get("entity"))
print(details.raw.get("call_eval_tag"))

client.stream_audio(call_id)

Download the audio recording for a call (audio/ogg or audio/mpeg).

audio = client.stream_audio("outbound-1776774443-863aa698")
with open("recording.ogg", "wb") as f:
    f.write(audio.content)

# Stream in chunks for large files
with open("recording.ogg", "wb") as f:
    for chunk in client.stream_audio_iter("outbound-1776774443-863aa698"):
        f.write(chunk)

client.create_agent(agent_display_name, config)

Create a new agent.

result = client.create_agent(
    agent_display_name="my-support-bot",
    config={
        "persona": {
            "identity": {
                "system_prompt": "You are a helpful support agent."
            }
        }
    },
)
print(result.agent_id)    # "33ac5907-0e44-43c4-934e-08e335cca6ee"
print(result.agent_name)  # "vaani123my-support-bot"

Agent config update methods

Partially update any section of an agent's configuration:

# Persona (identity, senses, actions, memories)
client.update_agent_persona(agent_id, persona={...})

# Training (knowledge base, FAQ, guardrails)
client.update_agent_training(agent_id, training={...})

# Experience (conversational settings, idle/end-call behavior)
client.update_agent_experience(agent_id, experience={...})

# Analysis (dispositions, evaluations, data extraction)
client.update_agent_analysis(agent_id, analysis={...})

# Deployment (phone call types, inbound/outbound numbers)
client.update_agent_deployment(agent_id, deployment={...})

Each returns AgentConfigResponse with agent_id, agent_display_name, and raw (full merged config).


WebRTC Sessions

The client.sessions namespace provides the full session-based WebRTC flow for embedding voice chat in your own UI.

Flow

  1. client.sessions.create(...) — returns a session_token and embeddable session_url
  2. client.sessions.connect(session_token) — exchange for LiveKit credentials
  3. Pass creds.lk_url + creds.lk_token to the LiveKit client SDK in your browser/app
  4. Optionally watch real-time events via client.sessions.ws_url(session_token)
  5. client.sessions.disconnect(session_token) — end the session
with VaaniClient(api_key="YOUR_API_KEY") as client:
    session = client.sessions.create(
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        ui_type="widget",
        grace_period=60,
        session_ttl=1800,
        metadata={"user_id": "user_123"},
    )
    print(session.session_token)
    print(session.session_url)

    creds = client.sessions.connect(session.session_token)
    print(creds.lk_url)    # "wss://livekit.vaaniresearch.com"
    print(creds.lk_token)  # LiveKit participant JWT
    print(creds.room_name)

    client.sessions.disconnect(session.session_token, explicit_end=True)

Sessions reference

Method Description Returns
sessions.create(agent_id, ...) Create a session token + embeddable URL WebRTCSession
sessions.connect(token) Exchange token for LiveKit credentials WebRTCSessionConnect
sessions.get(token) Fetch current session state WebRTCSessionStatus
sessions.disconnect(token, explicit_end=False) Signal disconnect or end session WebRTCSessionStatus
sessions.ws_url(token) Build WebSocket URL for real-time events str

Resource Namespaces

client.calls

with VaaniClient(api_key="YOUR_API_KEY") as client:
    # Trigger a telephony call
    resp = client.calls.trigger(
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        contact_number="+919876543210",
        name="Rahul",
        medium="telephony",
        dnd_check_skipped=True,
    )
    print(resp.call_id)

    # Trigger a WebRTC session
    resp = client.calls.trigger(
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        contact_number="+919876543210",
        medium="webrtc",
    )
    print(resp.token)

    # Get call details, transcript, history
    details = client.calls.get_details(resp.call_id)
    transcript = client.calls.get_transcript(resp.call_id)
    history = client.calls.get_history(page=1, page_size=50)

client.campaigns

Manage outbound campaigns:

with VaaniClient(api_key="YOUR_API_KEY") as client:
    campaign = client.campaigns.create(
        name="Q3 Outreach",
        agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
        csv_content=open("contacts.csv", "rb").read(),
    )
    client.campaigns.start(campaign.id)
    status = client.campaigns.get_status(campaign.id)
    print(status.status)   # "running"

    client.campaigns.pause(campaign.id)
    client.campaigns.resume(campaign.id)
    client.campaigns.stop(campaign.id)

client.agents

with VaaniClient(api_key="YOUR_API_KEY") as client:
    agents = client.agents.list()
    for agent in agents:
        print(agent.id, agent.agent_name)

    agent = client.agents.get("d62cc9bd-2f51-4581-9f38-6c3b7d58a988")
    print(agent.agent_language)

Async Usage

Every method has an exact async counterpart on AsyncVaaniClient:

import asyncio
from vaani_sdk import AsyncVaaniClient

async def main():
    async with AsyncVaaniClient(api_key="YOUR_API_KEY") as client:
        # Telephony
        result = await client.trigger_call(
            agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
            contact_number="+919876543210",
            name="Rahul",
        )
        print(result.call_id)

        # WebRTC
        result = await client.trigger_call(
            agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988",
            medium="webrtc",
            primary_language="en",
        )
        print(result.token)

        history = await client.get_call_history(page=1, page_size=5)
        session = await client.sessions.create(
            agent_id="d62cc9bd-2f51-4581-9f38-6c3b7d58a988"
        )
        creds = await client.sessions.connect(session.session_token)

asyncio.run(main())

Error Handling

All exceptions inherit from VaaniError and carry a status_code attribute.

Exception HTTP status Cause
AuthenticationError 401 Invalid or missing API key
ForbiddenError 403 Operation not allowed (e.g. DND block, wrong key)
NotFoundError 404 Resource does not exist
SessionExpiredError 410 WebRTC session has ended or expired
InsufficientBalanceError 402 Wallet balance too low
ValidationError 422 Request parameters failed validation
RateLimitError 429 Too many requests
ServerError 5xx Vaani server-side error
TimeoutError Request timed out
ConnectionError Could not reach the API
from vaani_sdk import VaaniClient, ForbiddenError, VaaniError

with VaaniClient(api_key="YOUR_API_KEY") as client:
    try:
        result = client.trigger_call(
            agent_id="my-agent",
            contact_number="+919876543210",
            name="Test",
        )
    except ForbiddenError as exc:
        # e.g. "Call blocked: destination number is in DND registry"
        # Use dnd_check_skipped=True to bypass DND in test environments
        print(f"Forbidden: {exc}")
    except VaaniError as exc:
        print(f"API error {exc.status_code}: {exc}")

Development

Setup

# Install with dev extras (uses uv)
uv sync --dev

# Or with pip
pip install -e ".[dev]"

Running tests

# Unit tests (no server required — all mocked)
uv run pytest tests/test_client.py tests/test_resources.py -v

# Integration tests (requires local API stack)
uv run pytest tests/integration/ -v -s

Integration test setup

The integration tests target a locally-running vaani-external-api (port 8001) which proxies to vaani-backend-new (port 8500).

# 1. Start vaani-backend-new
cd vaani-backend-new && docker compose -f docker-compose.dev.yaml up -d

# 2. Start vaani-external-api
cd external/vaani-external-api && docker compose up -d

# 3. Run integration tests
cd external/vaani-sdk
VAANI_API_KEY=vaani_... VAANI_AGENT_ID=<uuid> uv run pytest tests/integration/ -v -s

Environment variables for integration tests:

Variable Default Description
VAANI_API_KEY vaani_c1fc7e33c05632830ffe16da5e314b0d API key
VAANI_BASE_URL http://localhost:8001 External API base URL
VAANI_AGENT_ID d62cc9bd-2f51-4581-9f38-6c3b7d58a988 Agent UUID for tests

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vaani_sdk-0.3.0.tar.gz (84.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vaani_sdk-0.3.0-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

File details

Details for the file vaani_sdk-0.3.0.tar.gz.

File metadata

  • Download URL: vaani_sdk-0.3.0.tar.gz
  • Upload date:
  • Size: 84.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for vaani_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7350238dc9d08ecc497a9fe783f25cd51abed702d4f0e5d2f86dedf86d9e6e25
MD5 9af561730d927efedc27b5a8265e6409
BLAKE2b-256 8cc8f5b4932ef7b00d80490defa683e7d0bc6efd125211a2d8da1cd54a895773

See more details on using hashes here.

File details

Details for the file vaani_sdk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: vaani_sdk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 24.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for vaani_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 051960d5b31c710e25990fca6dd5aa25b7682c8e818e43da398670a24483a275
MD5 a75e505c5402119ae2f9431566a97508
BLAKE2b-256 16931d6b4c25da406669a1f6a87a844b921b5871d887160c20ff32a335c567da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page