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
- Log in to app.vaanivoice.ai
- Navigate to Settings > API Keys
- 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
Async Usage
Every method on VaaniClient has an exact async equivalent on AsyncVaaniClient.
import asyncio
from vaani_sdk import AsyncVaaniClient
async def main():
async with AsyncVaaniClient(api_key="YOUR_API_KEY") as client:
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)
asyncio.run(main())
Error Handling
All exceptions inherit from VaaniError and carry a status_code attribute.
| Exception | HTTP status | Cause |
|---|---|---|
AuthenticationError |
401 / 403 | Invalid or missing API key |
NotFoundError |
404 | Resource does not exist |
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, NotFoundError, VaaniError
with VaaniClient(api_key="YOUR_API_KEY") as client:
try:
transcript = client.get_transcript("non-existent-id")
except AuthenticationError:
print("Bad API key — check X-API-Key header value")
except NotFoundError:
print("Call not found or transcript not yet generated")
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vaani_sdk-0.1.3.tar.gz.
File metadata
- Download URL: vaani_sdk-0.1.3.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d184daa39bbe2a2cbd763cc0ff714127b7d65db8f5cca2a4c2cd1f09074582e4
|
|
| MD5 |
34e92e7ead18077545cc4d4d7e105227
|
|
| BLAKE2b-256 |
2ed941af5fcf1cf946d80863e7640327df1be6d3a4643144d859bf0ee6d30e1f
|
File details
Details for the file vaani_sdk-0.1.3-py3-none-any.whl.
File metadata
- Download URL: vaani_sdk-0.1.3-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f16b4b1beb79b02b13e3e548c4a11b91f5749e3e43704b12b995696482263996
|
|
| MD5 |
18c97109d4a97b7bd427129684e919ce
|
|
| BLAKE2b-256 |
ae11fcd395adf73a2272b48dbd0bfa114f99db3da557415e5e4743636edd0c85
|