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

client = VaaniClient(api_key="YOUR_API_KEY")

# Trigger an outbound call
result = client.trigger_call(
    agent_id="8cf3373e-eb6f-4b4c-9f3c-324a56a91147",
    contact_number="+919876543210",
    name="Nishank",
)
print(result.call_id)  # "outbound-1776774443-863aa698"

client.close()

Using the client as a context manager (recommended — ensures the HTTP connection is closed):

with VaaniClient(api_key="YOUR_API_KEY") as client:
    history = client.get_call_history(page=1, page_size=10)
    for call in history.data:
        print(call.call_id)

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

Create an outbound call dispatch.

Parameter Type Required Description
agent_id str Yes Agent UUID from the Agent Config page on app.vaanivoice.ai
contact_number str Yes Phone number in E.164 format (e.g. +919876543210)
name str Yes Customer name
voice str No Override the agent's default voice for this call
metadata dict No Template variables configured in the agent's prompt, injected at call time
outbound_number str No Override the caller ID (E.164 format). Must be a number configured in your Telephony settings
result = client.trigger_call(
    agent_id="8cf3373e-eb6f-4b4c-9f3c-324a56a91147",
    contact_number="+919876543210",
    name="Nishank",
    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

Success response shape:

{
  "success": true,
  "message": "Call initiated successfully",
  "output": {
    "agent_name": "my-sales-agent",
    "call_id": "outbound-1776774443-863aa698"
  },
  "error": null
}

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)

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

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

Each call record includes call_id, call_type, call_status, agent_name, from_number, to_number, Start_time, End_time, duration_ms, call_cost, call_summary, recording_api, call_transcription, and more.


client.get_transcript(call_id)

Retrieve the full conversation transcript for a completed call, with speaker labels (AGENT: / USER:).

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

Returns "Transcript not found in Azure Blob Storage" if the call is still in progress or the transcript hasn't been generated yet.


client.get_call_details(call_id)

Get detailed call information including transcript, extracted entities, conversation 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"))

Response includes transcription, entity (extracted entities like callback requests), conversation_eval, summary, and call_eval_tag.


client.stream_audio(call_id)

Download the audio recording for a call. Returns audio/ogg or audio/mpeg binary data.

audio = client.stream_audio("outbound-1776774443-863aa698")
print(audio.content_type)  # e.g. "audio/ogg"

with open("recording.ogg", "wb") as f:
    f.write(audio.content)

For large files, stream in chunks to avoid loading everything into memory:

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 associated with your client.

Parameter Type Required Description
agent_display_name str Yes Display name for the new agent
config dict No Optional initial agent configuration (persona, etc.)
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"

client.webrtc_token(...)

Generate a WebRTC token for voice chat with an agent via LiveKit.

Parameter Type Default Description
agent_id str None Agent UUID (optional if agent_name provided)
agent_name str None Agent name (optional if agent_id provided)
voice_gender str "female" Voice gender ('male' or 'female')
primary_language str "hi" Primary language code (e.g. 'en', 'hi')
secondary_language str "en" Secondary language code
welcome_message str None Custom welcome message (optional)
welcome_interruptible bool True Whether welcome message can be interrupted
bg_noise_enabled bool False Enable background noise
bg_noise_volume int 60 Background noise volume (0-100)
voice_speed float 1.0 Voice speed multiplier (0.6-1.4)
metadata dict None Arbitrary key-value pairs (optional)
result = client.webrtc_token(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    voice_gender="female",
    primary_language="en",
    welcome_message="Hi! How can I help you today?",
)
print(result.token)     # "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
print(result.room_url)  # "wss://livekit.vaanivoice.ai"

client.update_agent_persona(agent_id, persona)

Partially update the persona section of an agent's configuration. Deep-merges the provided payload with the existing persona config.

Parameter Type Required Description
agent_id str Yes Agent UUID
persona dict Yes Persona config dict (identity, senses_capabilities, actions, memories, etc.)
result = client.update_agent_persona(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    persona={
        "identity": {
            "system_prompt": "You are a helpful customer service agent.",
            "greeting_message": {
                "agent_message": "Hi! How can I help you today?",
                "interruptible": True,
            }
        },
        "senses_capabilities": {
            "language": "English",
            "brain": {
                "llm": {
                    "primary": {
                        "provider": "google",
                        "model": "gemini-2.5-flash",
                        "parameters": {
                            "temperature": 0.7,
                            "max_tokens": 1000
                        }
                    }
                }
            }
        }
    },
)
print(result.agent_display_name)  # Updated agent name
print(result.raw["persona"])      # Full merged persona config

client.update_agent_training(agent_id, training)

Partially update the training section (knowledge base, FAQ, guardrails) of an agent's configuration.

Parameter Type Required Description
agent_id str Yes Agent UUID
training dict Yes Training config dict (knowledge, know_how)
result = client.update_agent_training(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    training={
        "know_how": {
            "faq": {
                "What are your hours?": "We are open 9 AM to 5 PM.",
                "How do I reset my password?": "Click 'Forgot Password' on the login page."
            },
            "guardrails": {
                "no_personal_info": "Never ask for credit card numbers or passwords."
            }
        }
    },
)
print(result.agent_display_name)

client.update_agent_experience(agent_id, experience)

Partially update the experience section (conversational settings, idle/end-call behavior) of an agent's configuration.

Parameter Type Required Description
agent_id str Yes Agent UUID
experience dict Yes Experience config dict (conversational_experience, settings)
result = client.update_agent_experience(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    experience={
        "conversational_experience": {
            "bg_noise": {
                "enabled": True,
                "volume": 0.3,
                "sound": "https://example.com/office-ambience.mp3"
            },
            "filler_words": {
                "filler_words_frequency": 0.5,
                "filler_words_list": ["umm", "uhh", "ok"]
            }
        },
        "settings": {
            "call_settings": {
                "max_call_duration": 30
            },
            "idle_conversation_settings": {
                "idle_call_hangup_timeout": 20,
                "idle_call_warning_message": "Are you still there?"
            }
        }
    },
)
print(result.agent_display_name)

client.update_agent_analysis(agent_id, analysis)

Partially update the analysis section (dispositions, evaluations, data extraction) of an agent's configuration.

Parameter Type Required Description
agent_id str Yes Agent UUID
analysis dict Yes Analysis config dict (evaluations, extraction)
result = client.update_agent_analysis(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    analysis={
        "evaluations": {
            "dispositions": {
                "enabled": True,
                "prompt_based": [
                    {
                        "name": "purchase_intent",
                        "type": "bool",
                        "prompt": "Did the user express intent to purchase?",
                        "list_of_tags": {
                            "Yes": "User is interested",
                            "No": "User declined"
                        }
                    }
                ]
            },
            "conversation_evaluation": {
                "enabled": True
            }
        },
        "extraction": {
            "data_collection": {
                "enabled": True,
                "data_points": [
                    {
                        "name": "customer_email",
                        "prompt": "Extract the customer's email address",
                        "nullable": True
                    }
                ]
            }
        }
    },
)
print(result.agent_display_name)

client.update_agent_deployment(agent_id, deployment)

Partially update the deployment section (phone call types, inbound/outbound numbers) of an agent's configuration.

Parameter Type Required Description
agent_id str Yes Agent UUID
deployment dict Yes Deployment config dict (phone settings)
result = client.update_agent_deployment(
    agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
    deployment={
        "deployment": {
            "phone": {
                "call_type": {
                    "Inbound": "",
                    "Outbound": ["+919876543210", "+919876543211"]
                }
            }
        }
    },
)
print(result.agent_display_name)
print(result.raw["deployment_config"])  # Full merged deployment config

WebRTC Sessions

The client.sessions namespace provides the full session-based WebRTC flow, which is the recommended approach for embedding voice chat into your own UI.

WebRTC Flow

  1. Create a session with client.sessions.create(...) — returns a session_token and embeddable session_url.
  2. Call client.sessions.connect(session_token) when the user is ready to join — returns LiveKit credentials.
  3. Pass creds.lk_url and creds.lk_token to the LiveKit client SDK in your browser or mobile app.
  4. Optionally watch real-time events with client.sessions.ws_url(session_token).
  5. End the session with client.sessions.disconnect(session_token).
from vaani_sdk import VaaniClient

with VaaniClient(api_key="YOUR_API_KEY") as client:
    # 1. Create a session
    session = client.sessions.create(
        agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
        ui_type="widget",
        grace_period=60,
        session_ttl=1800,
        initial_message="User is asking about order #1234",
        metadata={
            "user_id": "user_123",
            "ticket_id": "T-1234",
        },
    )
    print(session.session_token)  # JWT session token
    print(session.session_url)    # embeddable/shareable URL
    print(session.expires_at)     # expiry datetime

    # 2. Exchange token for LiveKit credentials
    creds = client.sessions.connect(session.session_token)
    print(creds.lk_url)    # "wss://livekit.vaanivoice.ai"
    print(creds.lk_token)  # LiveKit participant JWT
    print(creds.room_name) # LiveKit room name

    # 3. Check session status
    status = client.sessions.get(session.session_token)
    print(status.status)  # "created" | "agent_ready" | "active" | "reconnecting" | "ended"

    # 4. End the session (with grace period for reconnection)
    client.sessions.disconnect(session.session_token)

    # Or end immediately with no grace period
    client.sessions.disconnect(session.session_token, explicit_end=True)

Session Events via WebSocket

Use client.sessions.ws_url(token) to build a WebSocket URL and listen to server-side push events:

import asyncio
import json
import websockets
from vaani_sdk import VaaniClient

client = VaaniClient(api_key="YOUR_API_KEY")

async def listen(session_token: str) -> None:
    url = client.sessions.ws_url(session_token)
    async with websockets.connect(url) as ws:
        async for message in ws:
            event = json.loads(message)
            if event["event"] == "agent_ready":
                print("Agent has joined the room")
            elif event["event"] == "agent_timeout":
                print("Agent failed to join:", event.get("reason"))
            elif event["event"] == "session_ended":
                print("Session ended:", event.get("reason"))

asyncio.run(listen("session-token-here"))

Sessions Reference

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

sessions.create() parameters:

Parameter Type Default Description
agent_id str required Agent UUID or name
ui_type str "fullpage" Display mode: "fullpage" or "widget"
grace_period int None Reconnection window in seconds (0–3600)
session_ttl int None Session lifetime in seconds (60–86400)
initial_message str None Message injected into agent context at session start
metadata dict None Arbitrary key-value data forwarded to the agent

Resource Namespaces

client.calls

Manage calls via the resource namespace (an alternative to the flat trigger_call, get_transcript, etc. methods):

with VaaniClient(api_key="YOUR_API_KEY") as client:
    # Trigger an outbound call
    call = client.calls.trigger(
        agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee",
        contact_number="+919876543210",
        name="Rahul",
        metadata={"ticket_id": "T-1234"},
    )
    print(call.call_id)    # "outbound-1776774443-863aa698"
    print(call.status)     # "in_progress"

    # Get a specific call
    call = client.calls.get(call.call_id)

    # Get call transcript
    transcript = client.calls.get_transcript(call.call_id)

    # List calls (with optional agent filter and pagination)
    calls = client.calls.list(agent_id="33ac5907-0e44-43c4-934e-08e335cca6ee", page=1, page_size=50)
    for c in calls:
        print(c.call_id, c.status)

client.agents

List and inspect agents via the resource namespace:

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

    # Get a specific agent
    agent = client.agents.get("33ac5907-0e44-43c4-934e-08e335cca6ee")
    print(agent.agent_name)
    print(agent.agent_language)
    print(agent.created_at)

Async Usage

Every method on VaaniClient has an exact async equivalent on AsyncVaaniClient, including all resource namespaces.

import asyncio
from vaani_sdk import AsyncVaaniClient

async def main():
    async with AsyncVaaniClient(api_key="YOUR_API_KEY") as client:
        # Flat methods
        result = await client.trigger_call(
            agent_id="8cf3373e-eb6f-4b4c-9f3c-324a56a91147",
            contact_number="+919876543210",
            name="Nishank",
        )
        print(result.call_id)

        history = await client.get_call_history(page=1, page_size=5)
        for call in history.data:
            print(call.call_id)

        transcript = await client.get_transcript(history.data[0].call_id)
        print(transcript.transcript)

        details = await client.get_call_details(history.data[0].call_id)
        print(details.raw)

        # Stream audio asynchronously
        with open("recording.ogg", "wb") as f:
            async for chunk in client.stream_audio_iter(history.data[0].call_id):
                f.write(chunk)

        # Resource namespaces
        session = await client.sessions.create(agent_id="8cf3373e-eb6f-4b4c-9f3c-324a56a91147")
        creds = await client.sessions.connect(session.session_token)
        print(creds.lk_url, creds.lk_token)

        calls = await client.calls.list(page=1, page_size=10)
        agents = await client.agents.list()

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 for this 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,
    AuthenticationError,
    ForbiddenError,
    InsufficientBalanceError,
    NotFoundError,
    SessionExpiredError,
    VaaniError,
)

with VaaniClient(api_key="YOUR_API_KEY") as client:
    try:
        session = client.sessions.create(agent_id="my-agent")
        creds = client.sessions.connect(session.session_token)
    except AuthenticationError:
        print("Bad API key — check X-API-Key header value")
    except ForbiddenError:
        print("Agent not owned by this API key")
    except InsufficientBalanceError:
        print("Wallet balance is too low")
    except SessionExpiredError:
        print("Session has already ended")
    except NotFoundError:
        print("Agent not found")
    except VaaniError as exc:
        print(f"API error {exc.status_code}: {exc.message}")

Development

# Install with dev extras
pip install -e ".[dev]"

# Run tests
pytest 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.2.0.tar.gz (48.6 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.2.0-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: vaani_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 48.6 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.2.0.tar.gz
Algorithm Hash digest
SHA256 655846bf0215fc3eb5fbe61a0456434f5eb8dcc40682872e065429a53b96a9bc
MD5 54f8a88b5fca09e83d813a4c80731081
BLAKE2b-256 92d40c0a9af1adbf9cbb0737c14a18cfcaf4c8419f39536c7af0eaa0cb1a0e77

See more details on using hashes here.

File details

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

File metadata

  • Download URL: vaani_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b156a7e72ac0cdcb5a70e9a456d8b5b3747fd6c15791a60e6499a0641faed38d
MD5 aab983089a63b5844d78d2c93728282e
BLAKE2b-256 1d3384b9f3264c81a56303a42d48ce3d2fb6017ceb6cb16036a3666959dcff40

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