API Reference
v1.0Build next-gen voice AI products on the Vanira Sovereign Engine. Manage agents, trigger outbound traffic, and embed real-time conversational intelligence with zero effort.
Start in 2 minutes
Live voice demo
Try a live voice demo
Production demos with embedded Vanira voice agents — same sites shown in our , plus our on-site refund workflow at .
To test with your agent: open the dashboard, copy your pk_live_* key, and use the API Playground panel on the right — or paste it into a starter repo.
Template agents
Clone a pre-built agent into your account. Make your own agents public via Agent → Share to share with other developers.
Refund & Returns Agent
E-commerceLive camera inspection, guided return UI, and multimodal refund confirmation.
Kisan Support Agent
AgricultureFarmer-facing welfare intake — live camera, forms, regional languages.
Citizen Services Agent
Citizen accessVoice-guided portal navigation — search, dates, and forms in regional language.
Starter repos
vanira-starter-web
Vite + React + VaniraCallBox — voice pill and presets in minutes.
About the SDK
Two paths — pick one
| Path | When to use |
|---|---|
| Widget embed | No-code / marketing sites — paste a script tag, Vanira renders the UI |
| npm SDK | Developers building React, Next.js, Vue, or vanilla apps with their own UI |
npm integration surfaces
| Surface | Import | What you get |
|---|---|---|
VaniraCallBox | @vanira/sdk | Voice pill + presets + custom tool hook |
| Headless | @vanira/sdk/headless | VaniraClient + PresetRenderer — you build the call UI |
What you need
- Agent ID from the dashboard
- Publishable key
pk_live_*for browser code (ortokeninside the Vanira dashboard) - No backend URL — the SDK uses Vanira's cloud API automatically
Read next (in order)
2. SDK Installation —
npm install @vanira/sdk3. API Keys & Configuration — keys and props reference
4. VaniraCallBox — drop-in React voice pill
5. Build Your Own UI — headless
VaniraClient6. Preset Handler — built-in UI tools (forms, calendar, navigate, …)
7. Custom Tool Handler — your own client-side tools
8. Client-Side Events / Server-Side Events — lifecycle and data-channel events
9. Session Continuity — resume calls across refresh
React Native
Widget Embed
1<script2 src="https://unpkg.com/@vanira/sdk@latest/dist/vanira-sdk.js"3 data-widget-id="YOUR_WIDGET_ID"4 data-pk-key="pk_live_YOUR_PUBLISHABLE_KEY"5 defer6></script><vanira-convai> custom element on document.body. It survives SPA route changes because it lives outside your React/Vue tree.SPA navigation
vanira_navigate preset, add a listener so in-app routing stays in-SPA:1// Add once on your site (same page as the Vanira widget).2// Required when your agent uses the vanira_navigate preset.3window.addEventListener('vanira:navigate', (event) => {4 const path = event.detail.path; // e.g. "/pricing" or "/docs#section"5 6 // Option A — multi-page site or simple fallback:7 window.location.assign(path);8 9 // Option B — SPA router (pick one that matches your stack):10 // router.push(path); // React Router: useNavigate()11 // navigate(path); // Vue Router12 // router.push(path); // Next.js App Router13 14 event.detail.handled = true; // required — tells the SDK navigation succeeded15});vanira_navigate, the SDK dispatches a browser event instead of forcing a full page reload:| Target | SDK behavior |
|---|---|
Same-origin path (e.g. /pricing, /docs#faq) | Fires vanira:navigate with detail.path — your site must handle it |
| External URL (different origin) | Opens in a new tab automatically — no listener needed |
- *SPA sites (React, Vue, Next.js, etc.) must register a
vanira:navigatelistener** that routes with your framework and setsevent.detail.handled = true. Without it, same-origin navigation fails withstatus: cancelledand the console shows:No SPA listener handled vanira:navigate.
- *Blocking tool:** the AI pauses until the SDK sends
client_tool_result. Success payload:{ status: 'success', navigated_to, target_url }. Server interrupt (clearAudio/client_tool_cancel):{ status: 'interrupted', reason, target_url }.
- *Multi-page sites** can use
window.location.assign(event.detail.path)in the listener, or the same pattern as a fallback.
When to use npm instead
Powered by Vanira
SDK Installation
@vanira/sdk when you want VaniraCallBox or a headless integration with your own UI.1npm install @vanira/sdk2# or3yarn add @vanira/sdkImports
| Use case | Import |
|---|---|
| Drop-in voice pill | import { VaniraCallBox } from '@vanira/sdk' |
| Your own call UI | import { VaniraClient, PresetRenderer } from '@vanira/sdk/headless' |
| Low-level (same class) | import { VaniraClient } from '@vanira/sdk' |
Requirements
- Agent ID + publishable key
pk_live_* - HTTPS in production (microphone access)
- Start calls from a user click on mobile browsers
API Keys & Configuration
API keys
| Key | Where | Use |
|---|---|---|
pk_live_* | Browser, widget embed, VaniraCallBox | Web calls only — safe for frontend |
sk_live_* | Your backend only | Full API access — never expose in browser code |
apiKey: 'pk_live_…' in browser integrations. The SDK provisions the call and opens WebRTC — no backend URL, no manual REST calls.data-pk-key. Inside the Vanira dashboard, VaniraCallBox can use token (Bearer JWT) instead of apiKey.VaniraCallBox props
| Prop | Required | Description |
|---|---|---|
agentId | Yes | Agent UUID from dashboard |
apiKey | Yes* | pk_live_* for external sites |
token | Yes* | Dashboard Bearer JWT (*one of apiKey or token) |
onNavigate | Recommended | SPA router hook for vanira_navigate preset |
onCustomTool | As needed | Handler for custom client tools (not presets) |
sessionBehavior | No | 'new' (default) or 'continue' |
autoStart | No | Default false — tap-to-talk |
onMinimize / onClose | No | Host UI callbacks |
VaniraClient props
| Prop | Required | Description |
|---|---|---|
agentId | Yes | Agent UUID |
apiKey or token | Yes* | Auth (*unless serverUrl + callId + iceServers pre-supplied) |
sessionBehavior | No | 'new' or 'continue' |
prospectId / callId | No | Manual session resume |
trackRouteContext | No | Default true — auto page-route context sync |
onConnected / onDisconnected / onError | Recommended | Lifecycle callbacks |
onClientToolCall | As needed | All client tool calls (presets + custom) |
onTranscription | No | User speech-to-text stream |
.on(event) + start() — same class, two styles.Example
1// Browser2const client = new VaniraClient({3 agentId: 'YOUR_AGENT_ID',4 apiKey: 'pk_live_<uuid>',5 onConnected: () => setStatus('connected'),6});7await client.connect();VaniraCallBox
VaniraCallBox is the fastest npm integration — voice pill, presets, and a hook for custom tools.agentId + apiKey required. Mount above your router so SPA navigation does not tear down the call.1import { VaniraCallBox } from '@vanira/sdk';2import { useNavigate } from 'react-router-dom';3 4function AppShell() {5 const navigate = useNavigate();6 7 return (8 <>9 <YourRoutes />10 <VaniraCallBox11 agentId={import.meta.env.VITE_VANIRA_AGENT_ID}12 apiKey={import.meta.env.VITE_VANIRA_PK_KEY}13 onNavigate={(path) => navigate(path)}14 onCustomTool={(call, client) => {15 if (call.name === 'say_hi') {16 showGreetingPopup();17 if (call.execution_mode !== 'fire_and_forget') {18 client.sendToolResult(call.tool_call_id, { status: 'success' });19 }20 }21 }}22 />23 </>24 );25}Rules
- Presets (form, calendar, navigate, …) — automatic, no code
- Custom tools — implement in
onCustomToolonly - Do not mount inside a single page behind
{showCall && …}on multi-route SPAs
Custom call button (optional)
1<VaniraCallBox agentId="..." apiKey="...">2 {({ status, startCall, endCall }) =>3 status === 'connected'4 ? <button onClick={endCall}>Hang up</button>5 : <button onClick={startCall}>Talk to us</button>6 }7</VaniraCallBox>Build Your Own UI
@vanira/sdk/headless:1import { useRef } from 'react';2import {3 VaniraClient,4 PresetRenderer,5 type PresetRendererHandle,6} from '@vanira/sdk/headless';7 8const presetRef = useRef<PresetRendererHandle>(null);9let client: VaniraClient | null = null;10 11async function startCall() {12 client = new VaniraClient({13 agentId: 'YOUR_AGENT_ID',14 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',15 onConnected: () => setStatus('connected'),16 onDisconnected: () => setStatus('idle'),17 onClientToolCall: (raw) => presetRef.current?.enqueueToolCall(raw),18 });19 await client.connect();20}1<PresetRenderer ref={presetRef} client={client} onCustomTool={handleCustomTool} />Callbacks or events
1// Style A — constructor callbacks + connect()2await client.connect();3 4// Style B — .on() listeners + start()5client.on('connected', () => setStatus('connected'));6client.on('tool_call', (tc) => presetRef.current?.enqueueToolCall(tc));7await client.start();onConnected / connected — not on onSessionStarted (provisioning only).Preset Handler
- *Presets** are built-in client tools the SDK renders automatically — forms, calendars, uploads, navigation, DOM actions, and more.
VaniraCallBox, presets work with zero code. With headless VaniraClient, mount PresetRenderer and enqueue tool calls via presetRef.enqueueToolCall() or onClientToolCall.- *Dashboard: Agent → Tools → Create tool → Client → pick a preset tile. Full `POST /tools` bodies are in the Tools → Preset Tools** doc.
| Preset ID | UI | Mode |
|---|---|---|
vanira_form | Data Collection Form | blocking |
vanira_calendar | Date & Time Picker | blocking |
vanira_upload | File Upload | blocking |
vanira_camera | Camera Capture | fire_and_forget |
vanira_navigate | Navigate to Route — requires vanira:navigate listener on SPAs | blocking |
vanira_highlight_element | Highlight Element | blocking |
vanira_click_element | Click Element | blocking |
vanira_select_option | Select Dropdown Option | blocking |
vanira_set_date | Set Date Field | blocking |
vanira_type_text | DOM Typing Simulation | blocking |
vanira_erase_text | Whiteboard / DOM Erase | blocking |
vanira_erase_draw | Erase Drawing Board | blocking |
vanira_draw | Chalkboard Shape Drawing | blocking |
vanira_live_vision | Live Vision (Streaming Camera) | fire_and_forget |
vanira_close_live_camera | Stop Live Camera | blocking |
vanira_live_screen | Live Screen Share | fire_and_forget |
vanira_close_live_screen | Stop Live Screen Share | blocking |
vanira_clip_region | Page Region Clip | blocking |
vanira_tab_screenshot | Tab Screenshot | blocking |
vanira_screen_ink | Screen Ink | blocking |
vanira_screen_cursor | Screen Cursor | blocking |
vanira_screen_click | Screen Click | blocking |
vanira_clear_screen_overlay | Clear Screen Overlay | blocking |
vanira_page_scan | Page Scan | blocking |
vanira_point_at | Point At | blocking |
vanira_outline_targets | Outline Targets | blocking |
vanira_clear_guide | Clear Guide | blocking |
- *Blocking presets (most): the AI waits until the SDK calls `sendToolResult()`. fire_and_forget**:
vanira_camera,vanira_live_vision.
onCustomTool.Navigate preset — host-site setup
vanira_navigate, the SDK dispatches a browser event instead of forcing a full page reload:| Target | SDK behavior |
|---|---|
Same-origin path (e.g. /pricing, /docs#faq) | Fires vanira:navigate with detail.path — your site must handle it |
| External URL (different origin) | Opens in a new tab automatically — no listener needed |
- *SPA sites (React, Vue, Next.js, etc.) must register a
vanira:navigatelistener** that routes with your framework and setsevent.detail.handled = true. Without it, same-origin navigation fails withstatus: cancelledand the console shows:No SPA listener handled vanira:navigate.
- *Blocking tool:** the AI pauses until the SDK sends
client_tool_result. Success payload:{ status: 'success', navigated_to, target_url }. Server interrupt (clearAudio/client_tool_cancel):{ status: 'interrupted', reason, target_url }.
- *Multi-page sites** can use
window.location.assign(event.detail.path)in the listener, or the same pattern as a fallback.
DOM presets — route field
vanira_click_element, vanira_select_option, vanira_set_date, vanira_type_text, and vanira_erase_text, set client_fields.route to the SPA path where the target element lives (e.g. /checkout). If the user is on a different page, the SDK dispatches vanira:navigate first, waits for the route (and element when possible), then clicks/types/erases. Requires the same vanira:navigate listener as the Navigate preset on SPA sites.POST /tools JSON for every preset.React Integration Example
1import { useEffect, useState } from 'react';2import { VaniraClient, PresetRenderer } from '@vanira/sdk';3 4function App() {5 const [client] = useState(() => new VaniraClient({6 agentId: 'YOUR_AGENT_ID',7 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY'8 }));9 const [activeToolCall, setActiveToolCall] = useState(null);10 11 useEffect(() => {12 client.on('tool_call', (toolCall) => {13 setActiveToolCall(toolCall);14 });15 16 client.start();17 return () => client.stop();18 }, [client]);19 20 return (21 <div>22 <MainDashboard />23 24 {/* Mount the PresetRenderer to automatically handle forms, calendars, etc. */}25 {activeToolCall && (26 <PresetRenderer27 client={client}28 toolCall={activeToolCall}29 onCustomTool={(toolCall) => {30 console.log('Handle your custom tool:', toolCall.name);31 }}32 />33 )}34 </div>35 );36}Custom Tool Handler
Two data layers (do not confuse them)
| Layer | Dashboard section | Who fills it | Where it lands in code |
|---|---|---|---|
| 1. Agent parameters | *Agent parameters* | The AI extracts from the conversation | Tool schema only — tells the AI what to collect |
| 2. Frontend payload | *Frontend payload* | You map keys → {{param}} or static values | call.arguments in onCustomTool |
- *Agent parameters** define the conversation contract (e.g.
customer_name,order_id).
- *Frontend payload** (
client_fieldsin the API) defines what your app receives. Use{{param_name}}for dynamic agent values or plain strings for static fields.
Dashboard example
- *Agent parameters**
customer_name(string, required) — "Person's name from the conversation"
- *Frontend payload**
| Payload key | Value |
|---|---|
name | {{customer_name}} |
source | website |
- *At runtime** your handler receives:
1{2 "name": "Teja",3 "source": "website"4}call.arguments.Execution mode
| Mode | AI behavior | Your code |
|---|---|---|
blocking | Pauses until sendToolResult() | Must call client.sendToolResult(tool_call_id, result) |
fire_and_forget | Keeps speaking | No result required |
VaniraCallBox handler
1<VaniraCallBox2 agentId="YOUR_AGENT_ID"3 apiKey="pk_live_YOUR_PUBLISHABLE_KEY"4 onCustomTool={(call, client) => {5 const { name, arguments: args, tool_call_id, execution_mode } = call;6 7 if (name === 'greet_user') {8 openGreetingModal(args.name); // args.name from frontend payload mapping9 10 if (execution_mode !== 'fire_and_forget' && tool_call_id) {11 client.sendToolResult(tool_call_id, {12 status: 'success',13 message: 'Greeting shown',14 });15 }16 }17 }}18/>API equivalent (POST /tools)
1{2 "name": "greet_user",3 "description": "Show a personalized greeting popup when the user says hello",4 "type": "client",5 "execution_mode": "blocking",6 "channels": ["voice_web"],7 "parameters": [8 {9 "name": "customer_name",10 "type": "string",11 "description": "The person's name from the conversation",12 "required": true13 }14 ],15 "client_fields": {16 "name": "{{customer_name}}",17 "source": "website"18 }19}client_fields.preset_id — handled automatically by PresetRenderer, not onCustomTool.Tool call payload
| Field | Description |
|---|---|
name | Tool name or ref_code |
arguments | Resolved frontend payload your app reads |
tool_call_id | ID for sendToolResult() / sendToolError() |
execution_mode | blocking or fire_and_forget |
client_tool_ack within ~2.3s — you do not ack manually.On error or cancel
sendToolError(tool_call_id, message) when the operation fails so the agent can recover:1try {2 await bookSlot(args.date);3 client.sendToolResult(tool_call_id, { status: 'success' });4} catch (e) {5 client.sendToolError(tool_call_id, e.message || 'Booking failed');6}Client-Side Events
- *Client-side events** are callbacks the SDK fires in your browser — connection lifecycle, transcription, tool calls, and media tracks.
onConnected, …) or .on('connected', …) + start() — same events either way.| Event / callback | When it fires |
|---|---|
onSessionStarted / session_started | Session provisioned — not live yet |
onConnected / connected | WebRTC live — show your "connected" UI here |
onDisconnected / disconnected | Call ended |
onError / error | Connection or permission failure |
onTranscription / transcription | User speech-to-text (isFinal flag) |
onLocalStream | Microphone stream ready |
onRemoteTrack | Agent audio/video track arrives |
onClientToolCall / tool_call | AI requested a browser action |
onSessionStarted. Wait for onConnected.VaniraClient Example
1const client = new VaniraClient({2 agentId: 'YOUR_AGENT_ID',3 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',4 5 onSessionStarted: ({ prospectId, callId, serverUrl }) => {6 // Phase 1 — provisioned, still connecting to worker7 console.log('Provisioned:', { prospectId, callId, serverUrl });8 setStatus('connecting');9 },10 11 onConnected: () => {12 // Phase 2 — live (Talk to Agent connected state)13 setStatus('connected');14 },15 16 onDisconnected: () => setStatus('idle'),17 18 onError: (error) => {19 console.error('Connection error:', error);20 setStatus('error');21 },22 23 onTranscription: (text, isFinal) => {24 // isFinal = true means committed utterance.25 setTranscript(text);26 },27 28 onLocalStream: (stream) => {29 localAudioDebugRef.current.srcObject = stream;30 },31 32 onRemoteTrack: (track, stream) => {33 if (track.kind === 'audio') {34 audioElement.srcObject = stream;35 audioElement.play();36 }37 },38 39 onClientToolCall: (toolCall) => {40 // See "Client Tool Calls" section for full usage41 console.log('AI wants to:', toolCall.name, toolCall.arguments);42 }43});Server-Side Events
- *Server-side events are messages your app sends to the agent** over the WebRTC data channel.
High-level methods (preferred)
| Method | Purpose |
|---|---|
sendContextUpdate(data) | Silent UI state sync (page, cart, map location) |
sendActionTrigger(name, data) | User action that should interrupt and get a spoken response |
triggerActionInterrupt() | Cut agent speech before an action trigger |
sendToolResult(id, result) | Reply to a blocking client tool |
sendToolError(id, message) | Report tool failure to the agent |
uploadMedia(file, reason) | Vision upload during a live call |
trackRouteContext, default on).Low-level: sendEvent()
1client.sendEvent('client_live_camera_started', { resolution: '720p' });2client.sendEvent('client_live_camera_stopped');| Parameter | Required | Description |
|---|---|---|
event | Yes | Event name string |
data | No | JSON payload merged into the message |
Session Continuity
WebRTC connections end when a page refreshes or a component unmounts. Session continuity lets you reconnect with the same user identity and conversation context instead of creating a completely unrelated call.
prospectId and callId in browser storage after a call starts. With sessionBehavior: 'continue', the next connect() reuses that context.Storage Keys
| Key | Meaning |
|---|---|
vanira_prospect_id | The user/prospect identity used across chat and voice |
vanira_latest_call_id | The latest web-call session ID |
sessionStorage and localStorage when the SDK creates a call.Configuration Reference
sessionBehavior: 'new': start a fresh call. This is the default.sessionBehavior: 'continue': reuse stored or explicitly suppliedprospectIdandcallId.prospectId: pass this when you want to bind the call to your own user/contact record.callId: pass this if your app stores and restores call sessions manually.onSessionStarted: use this callback to persist or display the resolvedprospectId,callId, andserverUrl.
React Integration Example
1import React, { useEffect, useState, useRef } from 'react';2import { VaniraClient } from '@vanira/sdk';3 4export function VoiceCallWidget() {5 const [status, setStatus] = useState<'idle' | 'connecting' | 'connected' | 'disconnected'>('idle');6 const [sessionInfo, setSessionInfo] = useState<{ callId: string; prospectId: string } | null>(null);7 const clientRef = useRef<VaniraClient | null>(null);8 9 const startCall = async () => {10 setStatus('connecting');11 12 clientRef.current = new VaniraClient({13 agentId: 'YOUR_AGENT_ID',14 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY', // Browser-safe publishable key15 sessionBehavior: 'continue', // Attempt to continue session on page load/refresh16 17 onSessionStarted: ({ callId, prospectId }) => {18 setSessionInfo({ callId, prospectId });19 console.log('Provisioned (Phase 1):', { callId, prospectId });20 },21 onConnected: () => {22 setStatus('connected');23 },24 onDisconnected: () => {25 setStatus('disconnected');26 setSessionInfo(null);27 },28 onError: (err) => {29 console.error('Call Error:', err);30 setStatus('idle');31 }32 });33 34 try {35 await clientRef.current.connect();36 } catch (e) {37 console.error('Failed to start call', e);38 setStatus('idle');39 }40 };41 42 const endCall = () => {43 if (clientRef.current) {44 clientRef.current.disconnect();45 clientRef.current = null;46 }47 setStatus('idle');48 };49 50 // Safe cleanup when component unmounts51 useEffect(() => {52 return () => {53 if (clientRef.current) {54 clientRef.current.disconnect();55 }56 };57 }, []);58 59 return (60 <div className="p-4 border rounded-lg bg-zinc-900 text-white">61 <p>Status: {status}</p>62 {sessionInfo && (63 <p className="text-xs text-zinc-400">Call ID: {sessionInfo.callId}</p>64 )}65 {status === 'connected' ? (66 <button onClick={endCall} className="bg-red-500 px-4 py-2 rounded">End Call</button>67 ) : (68 <button onClick={startCall} disabled={status === 'connecting'} className="bg-emerald-500 px-4 py-2 rounded">69 {status === 'connecting' ? 'Connecting...' : 'Start / Resume Call'}70 </button>71 )}72 </div>73 );74}Context Update
sendContextUpdate() or the updateContext() alias on VaniraClient.Automatic page route sync (built-in)
client_context_update for page navigation — no extra code required:| Event | Payload highlights |
|---|---|
| Call connects | user_action: call_started_on_page, current_route, current_page |
| User navigates | user_action: user_navigated, previous_route, current_route |
history.pushState / replaceState, popstate, hashchange, vanira:navigate, and a lightweight location poll for SPA routers.trackRouteContext: false on VaniraClient to disable. Default is on.Code Example
1// User navigated to a pricing page.2client.sendContextUpdate({3 active_page: '/dashboard/pricing',4 customer_tier: 'gold',5 last_viewed_item: 'Premium Plan'6});7 8// Map demo: user panned the map. Debounce this in production.9map.on('moveend', async () => {10 const center = map.getCenter();11 const placeName = await reverseGeocode(center.lat, center.lng);12 13 client.sendContextUpdate({14 active_map_location: placeName,15 user_action: 'panning_map'16 });17});18 19// Alias:20client.updateContext({21 active_page: '/checkout',22 cart_total: 149.9923});Action Trigger
VaniraClient, call triggerActionInterrupt() first to cut current agent speech, then call sendActionTrigger() with an action name and a structured payload. Or use triggerInterrupt(actionName, data) — it sends both events in the correct order.uploadMedia(). Media uploads already notify the agent through client_media_update, and sending another interrupt can make the agent respond twice.When to use this
- User clicks an important CTA
- User selects a product, location, plan, or appointment
- User submits a form outside a preset
- Your app navigates to a new page and you want an immediate spoken response
Code Example
1// VaniraClient: interrupt, then send the action.2client.triggerActionInterrupt();3client.sendActionTrigger('map_click', {4 location: 'Tokyo, Japan',5 prompt: 'User clicked on Tokyo. Tell them 2 interesting facts about Tokyo immediately.'6});7 8// Or use the combined alias:9client.triggerInterrupt('plan_selected', {10 plan: 'Enterprise',11 prompt: 'The user selected Enterprise. Explain the next onboarding step.'12});Interrupt Audio Only
Interrupt Audio Only
triggerActionInterrupt() to cut current agent speech, or interruptAudioOnly() for audio-only interrupt.Code Example
1// Cut agent speech right before initiating a custom file upload flow2document.getElementById('upload-area').addEventListener('dragenter', () => {3 client.interruptAudioOnly();4});5 6// Or the lower-level interrupt:7client.triggerActionInterrupt();Ending a Call
disconnect() or stop() — both release the microphone, close the data channel, close the peer connection, and emit a disconnected event.Code Example
1client.disconnect();2client = null;3 4// React cleanup5useEffect(() => {6 return () => {7 clientRef.current?.disconnect();8 clientRef.current = null;9 };10}, []);Error Handling
serverUrl, failed /calls/create (Phase 1), or WebRTC/ICE failure reaching the worker (Phase 2).POST /calls/create in the network tab, Phase 1 succeeded but Phase 2 did not — check onError, microphone permission, and worker POST …/webrtc responses.onError and treat it as a user-facing state. Also clean up the client when a connection attempt fails so the next retry starts from a fresh peer connection.Common Errors
| Symptom | Likely cause | What to do |
|---|---|---|
Only POST /calls/create in network tab | Phase 2 failed (mic, worker SDP, ICE) | Check onError; call connect() from button click; allow microphone |
onSessionStarted fires but never onConnected | Stuck in Phase 2 | Check worker /webrtc POST response and ICE; see console [WebRTC] logs |
serverUrl is missing | No apiKey and no manual worker URL | Pass apiKey, or pass serverUrl and callId from your backend |
createCall failed (401/403) | Invalid key, wrong scope, or origin mismatch | Check key type and origin setting |
| Microphone permission denied | Browser blocked mic access | Start from a user click and show permission guidance |
| DataChannel not open | Sending too early or after disconnect | Wait for onConnected before calling context/actions/uploads |
| Audio autoplay blocked | Browser policy | Start calls from a user gesture and keep audio element playback user-initiated |
Retry Pattern
1import { VaniraClient } from '@vanira/sdk';2 3let client: VaniraClient | null = null;4 5async function startCall() {6 client?.disconnect();7 8 client = new VaniraClient({9 agentId: 'YOUR_AGENT_ID',10 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',11 onConnected: () => setStatus('connected'),12 onDisconnected: () => setStatus('idle'),13 onError: (error) => {14 console.error('Vanira call failed:', error);15 setStatus('error');16 client?.disconnect();17 client = null;18 },19 });20 21 setStatus('connecting');22 await client.connect();23}Best Practices
- Disable your "Start call" button while status is
connectingorconnected. - Call
disconnect()orstop()during React unmount. - Do not call
connect()twice on the same client. - Do not call context, action, or upload methods before the connection is open.
- Keep
sk_live_*keys out of browser code.
Preset Session Continuity
Voice session continuity restores the call identity, but a browser refresh still clears React component state. If a form, calendar, or upload dialog is active when the page refreshes, store the active tool-call payload yourself and restore it on mount.
sessionStorage. It restores the dialog shell after reload; for fully restoring half-filled form inputs, store those form values separately in your app state.React Continuity Implementation
sessionBehavior: 'continue' for the voice session.1import { useEffect, useState } from 'react';2import { VaniraClient, PresetRenderer } from '@vanira/sdk';3 4function App() {5 const [client] = useState(() => new VaniraClient({ 6 agentId: 'YOUR_AGENT_ID',7 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',8 sessionBehavior: 'continue'9 }));10 11 // 1. Initialize activeToolCall from sessionStorage if it exists12 const [activeToolCall, setActiveToolCall] = useState(() => {13 const saved = sessionStorage.getItem('vanira_active_preset');14 return saved ? JSON.parse(saved) : null;15 });16 17 useEffect(() => {18 client.on('tool_call', (toolCall) => {19 // 2. Cache the active tool call in sessionStorage20 sessionStorage.setItem('vanira_active_preset', JSON.stringify(toolCall));21 setActiveToolCall(toolCall);22 });23 24 client.start();25 return () => client.stop();26 }, [client]);27 28 const clearPreset = () => {29 // 3. Clear when your flow is complete, or when the user dismisses your restored UI30 sessionStorage.removeItem('vanira_active_preset');31 setActiveToolCall(null);32 };33 34 return (35 <div>36 <MainDashboard />37 38 {activeToolCall && (39 <button onClick={clearPreset}>Clear restored preset</button>40 )}41 42 {activeToolCall && (43 <PresetRenderer44 client={client}45 toolCall={activeToolCall}46 />47 )}48 </div>49 );50}Full Example (Map)
- Navigate the map via
show_location_maptool call (AI to UI) - Receive click context via action trigger (UI to AI, interrupts)
- Track pan context via context update (UI to AI, silent)
Code Example
1import { VaniraClient } from '@vanira/sdk';2 3let client: VaniraClient | null = null;4 5async function startMapSession(agentId: string) {6 // agentId + apiKey: the SDK handles call creation and WebRTC setup.7 client = new VaniraClient({8 agentId,9 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',10 onConnected: () => setStatus('connected'),11 onDisconnected: () => setStatus('idle'),12 onTranscription: (text, isFinal) => updateTranscript(text, isFinal),13 14 // AI to UI: agent wants to show a location on the map.15 onClientToolCall: (toolCall) => {16 if (toolCall.name === 'show_location_map') {17 geocode(toolCall.arguments.query).then(success => {18 if (toolCall.execution_mode === 'blocking') {19 client?.sendToolResult(toolCall.tool_call_id, { success });20 }21 });22 }23 }24 });25 26 await client.connect(); // pre-flight + WebRTC handled internally27 28 // 3. UI to AI (silent): sync map viewport to agent every second after pan.29 map.on('moveend', debounce(async () => {30 const place = await reverseGeocode(map.getCenter());31 client?.sendContextUpdate({ active_map_location: place, user_action: 'panning' });32 }, 1000));33 34 // 4. UI to AI (interrupt): map click forces immediate AI response.35 map.on('click', async (e) => {36 const place = await reverseGeocode(e.latlng);37 client?.triggerActionInterrupt();38 client?.sendActionTrigger('map_click', {39 location: place,40 prompt: `User clicked ${place}. Tell them 2 facts about it immediately.`41 });42 });43}Agent & Human Transfers
### 1. Human Transfer (SIP Referral)
In telephony calls, the Human Transfer tool triggers a standard SIP REFER to your configured fallback number. The AI agent immediately disconnects once the transfer is initiated.
Switch the user to a different AI agent without ending the session. This is perfect for multi-stage workflows (e.g., qualifying a lead with one agent, then switching to a "Closing" agent).
onDisconnected fires, create a new VaniraClient with the next agent ID returned by your transfer flow and call connect() again.Upload Media (Vision)
Live Multimodal Vision
client.uploadMedia(). The SDK uploads the file to the active media server and then sends a client_media_update event over the WebRTC data channel so the agent can process the new visual context.Parameters
| Argument | Type | Required | Description | |
|---|---|---|---|---|
file | `File | Blob` | Yes | The file object to upload. Supported by the high-level SDK: JPEG, PNG, GIF, WEBP, BMP, and PDF up to 50 MB. |
reason | string | Yes | Category tag (e.g. 'kyc_document', 'error_screenshot'). Tells your backend webhook how to process this upload. | |
message | string | No | Optional text question or message to accompany the file (e.g. "What does this line item mean?"). | |
interruptFirst | boolean | No | Available on VaniraClient.uploadMedia(). Cuts current audio before upload without sending a duplicate action trigger. |
Critical Anti-Patterns to Avoid
> Do NOT trigger manual action interrupts after calling `uploadMedia()`.
>
> The SDK already notifies the AI with
client_media_update. If you manually call client.triggerActionInterrupt() or client.sendActionTrigger() immediately after uploading, you can create duplicate responses.React File Upload Example
1import React, { useRef, useState } from 'react';2import { VaniraClient } from '@vanira/sdk';3 4interface UploadProps {5 client: VaniraClient | null;6}7 8export function VisionUploadButton({ client }: UploadProps) {9 const [isUploading, setIsUploading] = useState(false);10 const fileInputRef = useRef<HTMLInputElement>(null);11 12 const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {13 const file = e.target.files?.[0];14 if (!file || !client) return;15 16 try {17 setIsUploading(true);18 19 // Upload the document and let the media pipeline notify the AI.20 const response = await client.uploadMedia(21 file,22 'kyc_verification', // Routing reason23 'Please review this document and tell me if my name matches.' // Message context24 );25 26 console.log('Media uploaded successfully:', response.url);27 } catch (error) {28 console.error('Failed to upload vision context:', error);29 } finally {30 setIsUploading(false);31 if (fileInputRef.current) fileInputRef.current.value = ''; // Reset input32 }33 };34 35 return (36 <div className="flex items-center gap-2">37 <input38 type="file"39 ref={fileInputRef}40 onChange={handleFileChange}41 accept="image/*,application/pdf"42 className="hidden"43 />44 <button45 disabled={isUploading || !client}46 onClick={() => fileInputRef.current?.click()}47 className="px-4 py-2 text-sm bg-white text-black font-semibold rounded-lg hover:bg-zinc-200 disabled:opacity-50 disabled:cursor-not-allowed"48 >49 {isUploading ? 'Uploading...' : 'Upload Image / PDF'}50 </button>51 </div>52 );53}Body Parameters
fileREQUIREDThe image or document to upload (JPEG, PNG, GIF, WEBP, BMP, PDF).
reasonREQUIREDThe routing category configured in the Dashboard (e.g. kyc_photo, general).
messageOptional text context to send alongside the image.
Media Webhook
Processing Uploaded Media
client.uploadMedia(), Vanira can forward the uploaded file and metadata to your configured Media Webhook for custom processing.Vanira forwards the uploaded file to your webhook as a
POST request with multipart/form-data containing:media: The uploaded binary file (for example, image or PDF).reason: The tag identifier sent by the client (e.g.,'kyc_upload').message: (Optional) User's textual query or message.session_id: The active WebRTCcallIdsession.
Your webhook must return a JSON response matching the following structure:
1{2 "interrupt": true,3 "result_text": "OCR Result: PAN Card verified. Name: Jane Doe. PAN: ABCDE1234F."4}interrupt: Set totrueif the agent should react immediately to the processed media.result_text: The text content that the LLM will receive and verbally respond to.
Backend Integration Example (Express.js)
multer to process the incoming file upload and return the structured result back to Vanira:1const express = require('express');2const multer = require('multer');3const upload = multer({ limits: { fileSize: 50 * 1024 * 1024 } }); // 50MB limit4 5const app = express();6 7app.post('/api/vanira-media-webhook', upload.single('media'), async (req, res) => {8 try {9 const file = req.file; // The uploaded file buffer and metadata10 const { reason, message, session_id } = req.body;11 12 console.log(`Processing media for call ${session_id}. Reason: ${reason}`);13 14 let processedTextResult = '';15 16 if (reason === 'kyc_verification') {17 // 1. Call your KYC verification pipeline or OCR service18 // const kycResult = await verifyDocument(file.buffer);19 processedTextResult = 'Document verified successfully. Name: Jane Doe.';20 } else {21 processedTextResult = 'Generic document received. Please ask the user to clarify.';22 }23 24 // 2. Return the expected payload to Vanira25 return res.status(200).json({26 interrupt: true, // Cut off agent's speech to process this event instantly27 result_text: processedTextResult28 });29 30 } catch (error) {31 console.error('Webhook processing failure:', error);32 return res.status(500).json({33 interrupt: false,34 result_text: 'Failed to process document due to a server error.'35 });36 }37});38 39app.listen(3000, () => console.log('Media Webhook active on port 3000'));1. Go to your Vanira Dashboard.
2. Select your agent under Agents.
3. Navigate to Media Handlers tab.
4. Paste your public webhook URL in the input field and save.
Body Parameters
mediaREQUIREDThe raw multipart/form-data file blob uploaded by the user.
reasonREQUIREDThe routing category.
messageOptional context string.
session_idREQUIREDThe active WebRTC call ID.
About the RN SDK
@vanira/sdk](https://www.npmjs.com/package/@vanira/sdk). This package is React Native only — do not import the web SDK in mobile apps.Package
| npm | @vanira/sdk-react-native |
|---|---|
| Import | import { createReactNativeAI, PresetHostProvider } from '@vanira/sdk-react-native' |
What you get
- Voice calls over WebRTC (
createReactNativeAI) - Built-in preset UI — forms, calendar, upload, camera, navigation, live vision
- Same agent protocol as web (
client_tool_call,uploadMedia, session continuity)
What you need
- Agent ID from the dashboard
- Publishable key
pk_live_*in app code - Native modules for WebRTC (see RN Installation and Native Setup)
Read next (in order)
npm install @vanira/sdk-react-native2. Native Setup — WebRTC globals, permissions, peer deps
3. Quick Start —
PresetHostProvider + createReactNativeAI4. Preset Handler (RN) — route tool calls with
setActiveToolCall()5. RN Events — lifecycle callbacks
6. Session Continuity (RN) — resume calls with AsyncStorage
RN Installation
1npm install @vanira/sdk-react-nativeVoice calls (required)
1npm install react-native-webrtc react-native-incall-manager react-native-permissions2cd ios && pod installregisterGlobals() in index.js — see Native Setup.Presets (install only what you use)
| Feature | Packages |
|---|---|
| Upload / camera | react-native-image-picker, @react-native-documents/picker |
| Screenshot / clip region | react-native-view-shot |
| Live vision | react-native-vision-camera |
Native Setup
1. WebRTC globals (required)
registerGlobals() once in index.js before any SDK import:1import {AppRegistry} from 'react-native';2import {registerGlobals} from 'react-native-webrtc';3 4registerGlobals();5 6import App from './App';7import {name as appName} from './app.json';8 9AppRegistry.registerComponent(appName, () => App);RTCPeerConnection, getUserMedia) are undefined and calls fail.2. iOS permissions
ios/Podfile:1require_relative '../node_modules/react-native-permissions/scripts/setup'2 3setup_permissions([4 'Camera',5 'Microphone',6 'PhotoLibrary',7])1cd ios && pod installInfo.plist (NSMicrophoneUsageDescription, NSCameraUsageDescription, NSPhotoLibraryUsageDescription).3. Android permissions
AndroidManifest.xml:1<uses-permission android:name="android.permission.RECORD_AUDIO" />2<uses-permission android:name="android.permission.CAMERA" />3<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />4. Metro (if resolution fails)
1const path = require('path');2const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');3 4module.exports = mergeConfig(getDefaultConfig(__dirname), {5 resolver: {unstable_enablePackageExports: true},6 watchFolders: [7 path.resolve(__dirname, 'node_modules/@vanira/sdk-react-native'),8 ],9});Quick Start
Step 1 — Wrap the app
PresetHostProvider mounts preset modals (upload, calendar, form, camera, etc.) above your screens.1import {PresetHostProvider} from '@vanira/sdk-react-native';2 3export default function App() {4 return (5 <PresetHostProvider>6 <YourNavigation />7 </PresetHostProvider>8 );9}Step 2 — Start a voice call
1import {useRef} from 'react';2import {3 createReactNativeAI,4 usePresetHost,5 type ClientToolCall,6 type VaniraAI,7} from '@vanira/sdk-react-native';8 9function VoiceScreen() {10 const {setAiClient, setActiveToolCall} = usePresetHost();11 const aiRef = useRef<VaniraAI | null>(null);12 13 async function startCall() {14 const ai = createReactNativeAI({15 agentId: 'YOUR_AGENT_ID',16 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',17 backendUrl: 'https://api.vanira.io',18 });19 20 ai.on('preset', ({toolCall}) => setActiveToolCall(toolCall));21 ai.on('tool_call', (tc: ClientToolCall) => setActiveToolCall(tc));22 23 ai.on('connected', () => console.log('connected'));24 ai.on('disconnected', () => {25 aiRef.current = null;26 setAiClient(null);27 });28 ai.on('error', (msg) => console.error(msg));29 30 aiRef.current = ai;31 setAiClient(ai); // required — presets call uploadMedia / sendToolResult on this client32 await ai.start();33 }34 35 function stopCall() {36 aiRef.current?.stop();37 aiRef.current = null;38 setAiClient(null);39 }40 41 // your start/stop button UI…42}Rules
- Call
setAiClient(ai)when the call starts — preset modals need the live client - Route both
presetandtool_callevents tosetActiveToolCall() - Start calls from a button tap (microphone permission + audio routing)
- Use
ai.stop()on hang-up and clearsetAiClient(null)
Preset Handler (RN)
PresetRenderer mount needed.1ai.on('preset', ({toolCall}) => setActiveToolCall(toolCall));2ai.on('tool_call', (tc) => setActiveToolCall(tc));sendToolResult() when the user completes or cancels.| Preset ID | UI | Mode |
|---|---|---|
vanira_form | Data Collection Form | blocking |
vanira_calendar | Date & Time Picker | blocking |
vanira_upload | File Upload | blocking |
vanira_camera | Camera Capture | fire_and_forget |
vanira_navigate | Navigate to Route — requires vanira:navigate listener on SPAs | blocking |
vanira_highlight_element | Highlight Element | blocking |
vanira_click_element | Click Element | blocking |
vanira_select_option | Select Dropdown Option | blocking |
vanira_set_date | Set Date Field | blocking |
vanira_type_text | DOM Typing Simulation | blocking |
vanira_erase_text | Whiteboard / DOM Erase | blocking |
vanira_erase_draw | Erase Drawing Board | blocking |
vanira_draw | Chalkboard Shape Drawing | blocking |
vanira_live_vision | Live Vision (Streaming Camera) | fire_and_forget |
vanira_close_live_camera | Stop Live Camera | blocking |
vanira_live_screen | Live Screen Share | fire_and_forget |
vanira_close_live_screen | Stop Live Screen Share | blocking |
vanira_clip_region | Page Region Clip | blocking |
vanira_tab_screenshot | Tab Screenshot | blocking |
vanira_screen_ink | Screen Ink | blocking |
vanira_screen_cursor | Screen Cursor | blocking |
vanira_screen_click | Screen Click | blocking |
vanira_clear_screen_overlay | Clear Screen Overlay | blocking |
vanira_page_scan | Page Scan | blocking |
vanira_point_at | Point At | blocking |
vanira_outline_targets | Outline Targets | blocking |
vanira_clear_guide | Clear Guide | blocking |
Native deps by preset
| Preset | Extra packages |
|---|---|
| Voice only | react-native-webrtc |
| Upload | react-native-image-picker, @react-native-documents/picker |
| Camera | react-native-image-picker |
| Live vision | react-native-vision-camera |
| Calendar, form, navigate | SDK only |
Custom tools
tool_call handler before calling setActiveToolCall:1ai.on('tool_call', (tc) => {2 if (tc.name === 'my_custom_tool') {3 showMyModal(tc.arguments);4 if (tc.execution_mode === 'blocking') {5 ai.sendToolResult(tc.tool_call_id, {success: true});6 }7 return;8 }9 setActiveToolCall(tc);10});RN Events
.on(event, handler) on VaniraAI (returned by createReactNativeAI):| Event | When it fires |
|---|---|
connected | WebRTC live — show "connected" UI |
disconnected | Call ended — clean up client ref |
error | Connection or permission failure |
transcription | User speech-to-text ({ text, isFinal }) |
preset | Agent triggered a built-in preset |
tool_call | Agent triggered any client tool (preset or custom) |
Example
1ai.on('connected', () => setStatus('connected'));2ai.on('disconnected', () => {3 setStatus('idle');4 setAiClient(null);5});6ai.on('error', (message) => Alert.alert('Call failed', message));7ai.on('transcription', ({text, isFinal}) => {8 if (isFinal) setLastUtterance(text);9});10ai.on('preset', ({toolCall}) => setActiveToolCall(toolCall));11ai.on('tool_call', (tc) => setActiveToolCall(tc));Sending events to the agent
VaniraClient:| Method | Purpose |
|---|---|
sendToolResult(id, result) | Reply to blocking tools |
sendToolError(id, message) | Report tool failure |
uploadMedia(file, reason, message) | Send image/PDF during call |
sendContextUpdate(data) | Silent UI state sync |
triggerActionInterrupt() | Cut agent speech |
ai.stop() to end the session.Session Continuity (RN)
1import {2 createReactNativeAI,3 createSyncStorageAdapter,4 reactNativeRuntime,5 hasContinueSession,6 loadContinueSession,7} from '@vanira/sdk-react-native';8import AsyncStorage from '@react-native-async-storage/async-storage';9 10const runtime = {11 ...reactNativeRuntime,12 storage: createSyncStorageAdapter(AsyncStorage),13};14 15// Check before showing "Continue" button16const canContinue = hasContinueSession(runtime.storage, agentId);17const stored = loadContinueSession(runtime.storage, agentId);18 19const ai = createReactNativeAI({20 agentId: 'YOUR_AGENT_ID',21 apiKey: 'pk_live_YOUR_PUBLISHABLE_KEY',22 backendUrl: 'https://api.vanira.io',23 sessionBehavior: 'continue', // or 'new'24 prospectId: stored?.prospectId,25 callId: stored?.callId,26 runtime,27});28 29await ai.start();sessionBehavior | Behavior |
|---|---|
'new' (default) | Fresh call every time |
'continue' | Reuse stored prospect_id + call_id |
vanira_prospect_id, vanira_latest_call_id) via your storage adapter.Upload Media (RN)
uploadMedia(). The SDK handles the HTTP upload and sends client_media_update to the agent.vanira_upload) uses this automatically. For manual uploads:1const response = await ai.uploadMedia(2 {3 uri: fileUri,4 type: 'image/jpeg',5 name: 'photo.jpg',6 },7 'damage_photo',8 'What is wrong with this leaf?',9);Supported formats
React Native file shape
{ uri, type, name, size? } — not File / Blob:1await ai.uploadMedia(2 {uri: asset.uri, type: 'image/jpeg', name: 'upload.jpg'},3 'general',4 'User uploaded a photo',5);triggerActionInterrupt() after uploadMedia() — the media update already notifies the agent.RN vs Web SDK
| Voice entry | VaniraCallBox or VaniraClient | createReactNativeAI() |
|---|---|---|
| Preset UI | PresetRenderer or automatic in CallBox | PresetHostProvider + setActiveToolCall() |
| Connect | client.connect() or client.start() | await ai.start() |
| Upload file type | File / Blob | { uri, type, name } |
| Session storage | localStorage / sessionStorage | Your AsyncStorage adapter |
| WebRTC setup | Browser APIs | registerGlobals() + native modules |
Template Agents
How it works
2. Sign in → Import to My Account
3. Customize voice, tools, and presets in the dashboard
4. Embed with widget or SDK using your own
pk_live_* keyMake your agent shareable
1https://vanira.io/import?agentId=YOUR_AGENT_IDFeatured templates
| Agent | Vertical | Platform | Import path |
|---|---|---|---|
| Refund & Returns Agent | E-commerce | web | /import?agentId=fa1e533d-4970-44ad-b184-beda9868a987&utm_source=docs&utm_medium=template |
| Kisan Support Agent | Agriculture | react-native, web | /import?agentId=26aca6ed-0fc9-4342-b2c2-efad87449b32&utm_source=docs&utm_medium=template |
| Maths Tutor Agent | Education | web | /import?agentId=fa1e533d-4970-44ad-b184-beda9868a987&utm_source=docs&utm_medium=template |
| Citizen Services Agent | Citizen access | web | /import?agentId=fa1e533d-4970-44ad-b184-beda9868a987&utm_source=docs&utm_medium=template |
Starter Repositories
vanira-starter-web
- GitHub: https://github.com/VaniraAI/vanira-starter-web
- Deploy: [One-click Vercel deploy](https://vercel.com/new/clone?repository-url=https://github.com/VaniraAI/vanira-starter-web&project-name=vanira-voice-app)
vanira-starter-rn
- GitHub: https://github.com/VaniraAI/vanira-starter-rn
agentId and pk_live_* from the dashboard.Developer Referral
1https://vanira.io/signup?ref=YOUR_CLIENT_ID&utm_source=referral- npm packages: [@vanira/sdk](https://www.npmjs.com/package/@vanira/sdk) · [@vanira/sdk-react-native](https://www.npmjs.com/package/@vanira/sdk-react-native)
- Docs: [vanira.io/docs](https://vanira.io/docs)
- Community: [Discord](https://discord.gg/GB3yJMvf)
Built with Vanira
- Homepage showcase placement
- Backlink from docs
- Social promotion
Preset: Form
- *Dashboard:** Client tool → preset
vanira_form
- *client_fields:**
title,fields(comma-separated labels),reason
PresetRenderer) and React Native (PresetHostProvider) with zero custom UI code.| Preset ID | UI | Mode |
|---|---|---|
vanira_form | Data Collection Form | blocking |
vanira_calendar | Date & Time Picker | blocking |
vanira_upload | File Upload | blocking |
vanira_camera | Camera Capture | fire_and_forget |
vanira_navigate | Navigate to Route — requires vanira:navigate listener on SPAs | blocking |
vanira_highlight_element | Highlight Element | blocking |
vanira_click_element | Click Element | blocking |
vanira_select_option | Select Dropdown Option | blocking |
vanira_set_date | Set Date Field | blocking |
vanira_type_text | DOM Typing Simulation | blocking |
vanira_erase_text | Whiteboard / DOM Erase | blocking |
vanira_erase_draw | Erase Drawing Board | blocking |
vanira_draw | Chalkboard Shape Drawing | blocking |
vanira_live_vision | Live Vision (Streaming Camera) | fire_and_forget |
vanira_close_live_camera | Stop Live Camera | blocking |
vanira_live_screen | Live Screen Share | fire_and_forget |
vanira_close_live_screen | Stop Live Screen Share | blocking |
vanira_clip_region | Page Region Clip | blocking |
vanira_tab_screenshot | Tab Screenshot | blocking |
vanira_screen_ink | Screen Ink | blocking |
vanira_screen_cursor | Screen Cursor | blocking |
vanira_screen_click | Screen Click | blocking |
vanira_clear_screen_overlay | Clear Screen Overlay | blocking |
vanira_page_scan | Page Scan | blocking |
vanira_point_at | Point At | blocking |
vanira_outline_targets | Outline Targets | blocking |
vanira_clear_guide | Clear Guide | blocking |
Preset: Upload
- *Web accept:**
image/*,application/pdf,text/plain,text/csv
- *React Native:** requires
react-native-image-picker+@react-native-documents/pickerpeer deps.
- *Web:** listen for
vanira:navigateor useonNavigateonVaniraCallBox.
- *React Native:** register
registerInternalRouteHandler()for in-app routes.
Preset: Live Vision
- *React Native:** requires
react-native-vision-camera.
client_media_frame (not client_media_update) for continuous vision.https://api.vanira.io/discovery/modelsmodel field. Only status: "active" models are returned.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/discovery/models'Expected Response — 200 OK
1{2 "models": [3 {4 "id": "89e40b9c-...",5 "name": "gpt-4.1-mini",6 "ai_provider": "AZURE",7 "status": "active"8 },9 {10 "id": "7d49e047-...",11 "name": "gpt-4o-mini-realtime-preview",12 "ai_provider": "AZURE_REALTIME",13 "status": "active"14 }15 ]16}Response Schema Details
idREQUIREDInternal model UUID (not needed for API calls).
nameREQUIREDModel name to use in agent model.model field. e.g. gpt-4.1-mini
ai_providerREQUIREDProvider string to use in agent model.provider field. e.g. AZURE, AZURE_REALTIME, GROQ
statusREQUIREDactive | inactive. Only active models are returned.
HTTP Errors
UNAUTHORIZEDNo valid API key provided.
https://api.vanira.io/discovery/voicesvoice field.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/discovery/voices'Expected Response — 200 OK
1{2 "voices": [3 {4 "id": "db9faea1-...",5 "name": "Riya Rao",6 "tts_provider": "ELEVENLABS",7 "language": "ENGLISH",8 "gender": "FEMALE",9 "status": "active"10 },11 {12 "id": "c81a39ce-...",13 "name": "Samay Hinglish Super Premium",14 "tts_provider": "ELEVENLABS",15 "language": "HINDI",16 "gender": "MALE",17 "status": "active"18 }19 ]20}Response Schema Details
idREQUIREDInternal voice UUID (not needed for API calls).
nameREQUIREDVoice name to use in agent voice.name field. e.g. Riya Rao
tts_providerREQUIREDProvider to use in agent voice.provider field. e.g. ELEVENLABS, SARVAM
languagePrimary language of the voice. e.g. ENGLISH, HINDI
genderMALE | FEMALE
statusREQUIREDactive | inactive. Only active voices are returned.
HTTP Errors
UNAUTHORIZEDNo valid API key provided.
https://api.vanira.io/discovery/transcription-modelstranscription field.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/discovery/transcription-models'Expected Response — 200 OK
1{2 "models": [3 { "id": "8d398506-...", "name": "nova-2", "provider": "DEEPGRAM", "status": "active" },4 { "id": "dc641dca-...", "name": "nova-3", "provider": "DEEPGRAM", "status": "active" },5 { "id": "75bfb690-...", "name": "saaras:v3", "provider": "SARVAM", "status": "active" },6 { "id": "30fa4dbe-...", "name": "saaras:v2", "provider": "SARVAM", "status": "active" }7 ]8}Response Schema Details
idREQUIREDInternal model UUID (not needed for API calls).
nameREQUIREDModel name to use in agent transcription.model field. e.g. nova-2, saaras:v3
providerREQUIREDProvider to use in agent transcription.provider field. e.g. DEEPGRAM, SARVAM
statusREQUIREDactive | inactive. Only active models are returned.
HTTP Errors
UNAUTHORIZEDNo valid API key provided.
https://api.vanira.io/discovery/ice-serversRTCPeerConnection({ iceServers: [...] }) or use the SDK's VaniraClient.fetchIceServers(apiKey) helper which calls this endpoint automatically.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/discovery/ice-servers'Expected Response — 200 OK
1{2 "ice_servers": [3 {4 "urls": ["stun:stun.relay.metered.ca:80"],5 "username": null,6 "credential": null7 },8 {9 "urls": [10 "turn:global.relay.metered.ca:80",11 "turn:global.relay.metered.ca:443",12 "turns:global.relay.metered.ca:443?transport=tcp"13 ],14 "username": "<metered_user_id>",15 "credential": "<metered_credential_secret>"16 }17 ]18}Response Schema Details
urlsREQUIREDList of STUN/TURN URLs for this server.
usernameTURN username. null for STUN-only servers.
credentialTURN password/credential. null for STUN-only servers.
HTTP Errors
UNAUTHORIZEDNo valid API key provided.
https://api.vanira.io/phone-numbersThis includes both bought numbers and numbers imported from external providers.
Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/phone-numbers'Expected Response — 200 OK
1{2 "numbers": [3 {4 "id": "09d89078-b9cc-452d-ae06-126d04239b73",5 "number": "+918071387205",6 "country_code": "IN",7 "label": "Primary DID",8 "client_id": "91b5f2de-9e01-4520-837f-58f284e40a4c",9 "trunk_id": "0c014935-8e11-4632-8cfe-9028d01b492c",10 "is_active": true,11 "is_vanira_internal": false,12 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5"13 }14 ]15}Response Schema Details
numberREQUIREDThe phone number in E.164 format (digits only).
country_codeREQUIREDISO 2-letter country code.
labelREQUIREDHuman-readable label for the number.
agent_idID of the agent currently handling calls for this number.
is_activeREQUIREDWhether the number is ready to receive and make calls.
is_vanira_internalREQUIREDIf true, this number belongs to the Vanira shared pool.
HTTP Errors
UNAUTHORIZEDMissing or invalid API key.
BAD_REQUESTMissing client_id.
https://api.vanira.io/phone-numbers/importRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
phone_numberREQUIREDE.164 phone number (e.g. +918071387205).
agent_idREQUIREDID of the agent who will handle calls.
vobiz_auth_idVoBiz X-Auth-ID. Required for first-time import.
vobiz_auth_tokenVoBiz X-Auth-Token. Required for first-time import.
use_existing_credentialsUse previously stored credentials for this client. Default: false.
credential_labelLabel for newly stored credentials.
Implementation Example
1curl -X POST 'https://api.vanira.io/phone-numbers/import' \2 -H "Content-Type: application/json" \3 -d '{4 "phone_number": "+918071387205",5 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",6 "vobiz_auth_id": "<vobiz_auth_id>",7 "vobiz_auth_token": "<vobiz_auth_token>",8 "use_existing_credentials": false,9 "credential_label": "<credential_label>"10}'Expected Response — 200 OK
1{2 "phone_number": "+918071387205",3 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",4 "trunk_endpoint": "endpoint-1387205",5 "outbound_trunk_id": "8747b89c-a5d4-4307-8e12-ccbdabcc2907",6 "assigned": true,7 "service_reloaded": true8}HTTP Errors
UNAUTHORIZEDInvalid API key.
MULTI_STATUSUpstream OK but secondary sync had non-fatal errors.
BAD_REQUESTNo credentials available or missing required fields.
CONFLICTNumber already exists in system — delete it first.
UNPROCESSABLE_ENTITYNumber not found on provider account or assignment failed.
BAD_GATEWAYUpstream failure (Provider unreachable).
https://api.vanira.io/phone-numbers/linkRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
phone_numberREQUIREDThe phone number to update.
agent_idREQUIREDID of the new agent to handle all call traffic.
Implementation Example
1curl -X PUT 'https://api.vanira.io/phone-numbers/link' \2 -H "Content-Type: application/json" \3 -d '{4 "phone_number": "+918071387205",5 "agent_id": "5396166a-f107-4918-b108-ff97b5987178"6}'Expected Response — 200 OK
1{2 "success": true,3 "phone_number": "+918071387205",4 "agent_id": "5396166a-f107-4918-b108-ff97b5987178"5}HTTP Errors
PHONE_NUMBER_NOT_FOUNDPhone number not found.
AGENT_NOT_FOUNDAgent not found.
https://api.vanira.io/phone-numbers/:numberRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
numberREQUIREDThe phone number to remove (E.164 format).
Implementation Example
1curl -X DELETE 'https://api.vanira.io/phone-numbers/%2B918071387205' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "phone_number": "+918071387205",3 "deleted": true,4 "unassigned": true5}HTTP Errors
UNAUTHORIZEDInvalid API key.
PHONE_NUMBER_NOT_FOUNDPhone number not found in system.
BAD_GATEWAYVoBiz unassign failed.
https://api.vanira.io/phone-numbers/vobiz/credentialsRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Query Parameters
client_idREQUIREDUUID of the owning client.
Implementation Example
1curl -X GET 'https://api.vanira.io/phone-numbers/vobiz/credentials?client_id=%3Cclient_id%3E'Expected Response — 200 OK
1{2 "credentials": [3 {4 "id": "436c27d7-f357-4033-8ea0-97de12a989c2",5 "label": "primary",6 "auth_id_hint": "MA_",7 "is_default": false,8 "created_at": "2026-05-08T19:47:47Z",9 "updated_at": "2026-05-08T19:47:47Z"10 }11 ]12}HTTP Errors
UNAUTHORIZEDMissing or invalid API key.
BAD_REQUESTMissing client_id.
https://api.vanira.io/assistantRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant'Expected Response — 200 OK
1{2 "agents": [3 {4 "id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",5 "name": "Sales Rep",6 "active": true,7 "language": "en-US",8 "model": { "provider": "AZURE", "model": "gpt-4.1-mini" },9 "voice": { "provider": "ELEVENLABS", "name": "Riya Rao" },10 "transcription": { "provider": "DEEPGRAM", "model": "nova-2" },11 "enable_lid_detection": true,12 "lid_allowed_languages": ["hi", "en"],13 "created_at": "2026-01-10T08:00:00Z",14 "updated_at": "2026-02-01T12:00:00Z",15 "client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"16 }17 ]18}Response Schema Details
idREQUIREDAgent UUID.
nameREQUIREDDisplay name.
activeREQUIREDWhether the agent is active.
languageREQUIREDLanguage code e.g. en-US.
model{ provider, model } — LLM config. See GET /discovery/models.
voice{ provider, name } — TTS voice config. See GET /discovery/voices.
transcription{ provider, model } — STT config.
enable_lid_detectionWhether LID is enabled.
lid_allowed_languagesAllowed languages for pivoting.
client_idREQUIREDOwner client ID.
HTTP Errors
UNAUTHORIZEDNo valid API key or JWT provided.
DATABASE_ERRORInternal database error.
https://api.vanira.io/assistant/:id- *Ownership enforced** — returns 404 if the agent belongs to a different client.
Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant/caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5'Expected Response — 200 OK
1{2 "id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",3 "name": "Sales Rep",4 "active": true,5 "language": "en-US",6 "model": { "provider": "AZURE", "model": "gpt-4.1-mini" },7 "voice": { "provider": "ELEVENLABS", "name": "Riya Rao" },8 "transcription": { "provider": "DEEPGRAM", "model": "nova-2" },9 "welcome_message": "Hey! How can I help you?",10 "agent_prompt": "You are a helpful sales assistant...",11 "inbound_welcome_message": "Thanks for calling. How can I help?",12 "data_collection": { ... },13 "success_metric": { ... },14 "input_needed_json_format": [ ... ],15 "temperature": 0.7,16 "top_p": 1.0,17 "speed": null,18 "duty": "support",19 "silence_alert_message": "Are you still there?",20 "call_end_duration": 20000,21 "call_user_alert_duration": 7000,22 "initial_disable_mic_duration": 0,23 "enable_lid_detection": true,24 "lid_allowed_languages": ["hi", "en"],25 "created_at": "2026-01-10T08:00:00Z",26 "updated_at": "2026-02-01T12:00:00Z",27 "client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"28}Response Schema Details
idREQUIREDAgent UUID.
nameREQUIREDDisplay name.
activeREQUIREDActive status.
model{ provider, model } — LLM. Use GET /discovery/models for valid values.
voice{ provider, name } — TTS voice. Use GET /discovery/voices for valid values.
transcription{ provider, model } — STT transcription.
agent_promptLLM system prompt.
welcome_messageFirst message spoken by the agent.
temperatureLLM temperature (0–2).
speedTTS speech speed multiplier.
enable_lid_detectionWhether LID is enabled.
lid_allowed_languagesAllowed languages for pivoting.
data_collectionCall outcome and scoring configuration.
HTTP Errors
UNAUTHORIZEDNo valid API key or JWT.
AGENT_NOT_FOUNDAgent not found or not owned by the authenticated client.
VALIDATION_ERRORInvalid UUID format for id.
https://api.vanira.io/assistantRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
nameREQUIREDDisplay name for the agent.
welcome_messageREQUIREDFirst message the agent speaks.
agent_promptREQUIREDLLM system prompt that defines the agent personality.
languageLanguage code. e.g. en-US, hi-IN.
modelLLM config. If omitted, defaults to AZURE / gpt-4.1-mini. See GET /discovery/models for structure.
voiceTTS voice config. If omitted, defaults to ELEVENLABS / Riya Rao. See GET /discovery/voices for structure.
transcriptionSTT transcription config. See GET /discovery/transcription for structure.
data_collectionPost-call extraction config.
dutyAgent role: support | sales | hr etc.
enable_lid_detectionEnable LID system.
lid_allowed_languagesAllowed ISO 639-1 codes.
activeStart active.
Implementation Example
1curl -X POST 'https://api.vanira.io/assistant' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "Support Bot",5 "welcome_message": "Hey! How can I help you?",6 "agent_prompt": "<agent_prompt>",7 "language": "en-US",8 "model": {9 "provider": "AZURE",10 "model": "gpt-4.1-mini"11 },12 "voice": {13 "provider": "ELEVENLABS",14 "name": "Riya Rao"15 },16 "transcription": {17 "provider": "DEEPGRAM",18 "model": "nova-2"19 },20 "data_collection": {21 "call_cut": [],22 "required_values": {}23 },24 "duty": "support",25 "enable_lid_detection": true,26 "lid_allowed_languages": [27 "hi",28 "en"29 ],30 "active": false31}'Expected Response — 200 OK
1{2 "id": "new-agent-uuid",3 "name": "Support Bot",4 "client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",5 "created_at": "2026-03-13T09:00:00Z"6}HTTP Errors
UNAUTHORIZEDNo valid API key or JWT.
VALIDATION_ERRORmodel/voice/transcription provider+name not found in active records. Check /discovery/models and /discovery/voices.
PERSISTENCE_ERRORFailed to persist the new agent.
https://api.vanira.io/assistant/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent to update.
Body Parameters
nameNew display name.
agent_promptUpdated system prompt.
welcome_messageUpdated opening message.
languageLanguage code.
modelUpdate LLM. { provider, model }. See GET /discovery/models.
voiceUpdate TTS voice. { provider, name }. See GET /discovery/voices.
transcriptionUpdate STT config. { provider, model }.
temperatureLLM temperature (0–2).
speedTTS speed multiplier (0.25–4).
enable_lid_detectionToggle LID system.
lid_allowed_languagesUpdate allowed languages.
activeActivate or deactivate.
Implementation Example
1curl -X PATCH 'https://api.vanira.io/assistant/caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "<name>",5 "agent_prompt": "<agent_prompt>",6 "welcome_message": "<welcome_message>",7 "language": "<language>",8 "model": {9 "provider": "AZURE_REALTIME",10 "model": "gpt-4o-mini-realtime-preview"11 },12 "voice": {13 "provider": "ELEVENLABS",14 "name": "Miranda English Voice US"15 },16 "transcription": {17 "provider": "SARVAM",18 "model": "saaras:v3"19 },20 "temperature": null,21 "speed": null,22 "enable_lid_detection": false,23 "lid_allowed_languages": "<lid_allowed_languages>",24 "active": false25}'Expected Response — 200 OK
1{2 "id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",3 "name": "Updated Agent Name",4 "active": true,5 "updated_at": "2026-03-13T09:51:00Z"6}HTTP Errors
UNAUTHORIZEDNo valid API key or JWT.
AGENT_NOT_FOUNDAgent not found or not owned by the authenticated client.
VALIDATION_ERRORInvalid model/voice/transcription config. Check /discovery/models and /discovery/voices for valid values.
https://api.vanira.io/assistant/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent to delete.
Implementation Example
1curl -X DELETE 'https://api.vanira.io/assistant/caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",3 "name": "Deleted Agent"4}HTTP Errors
UNAUTHORIZEDNo valid API key or JWT.
AGENT_NOT_FOUNDAgent not found or not owned by the authenticated client.
VALIDATION_ERRORInvalid UUID format.
https://api.vanira.io/assistant/:id/widgetRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant/caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5/widget'Expected Response — 200 OK
1{2 "id": "widget-uuid",3 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",4 "mode": "voice_only",5 "primary_color": "#6366f1",6 "secondary_color": "#a855f7",7 "created_at": "2026-04-27T12:00:00Z"8}HTTP Errors
AGENT_NOT_FOUNDNo agent with this UUID.
https://api.vanira.io/assistant/widget/:widget_idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
widget_idREQUIREDWidget UUID (from Get Agent Widget response).
Body Parameters
modevoice_only | chat_only | chat_voice | avatar_only | chat_avatar.
primary_colorPrimary hex color. e.g. #6366f1.
secondary_colorSecondary hex color.
iconWidget icon identifier.
Implementation Example
1curl -X PATCH 'https://api.vanira.io/assistant/widget/a4fbac73-3f8c-4e3e-a742-195e1b68d2c3' \2 -H "Content-Type: application/json" \3 -d '{4 "mode": "<mode>",5 "primary_color": "<primary_color>",6 "secondary_color": "<secondary_color>",7 "icon": "<icon>"8}'Expected Response — 200 OK
1{2 "id": "widget-uuid",3 "mode": "chat_voice",4 "primary_color": "#ff0000",5 "updated_at": "2026-04-27T12:05:00Z"6}HTTP Errors
WIDGET_NOT_FOUNDWidget not found.
VALIDATION_ERRORInvalid field value.
https://api.vanira.io/assistant/:id/data-collectionRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant/caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5/data-collection'Expected Response — 200 OK
1{2 "collections": [3 {4 "id": "766c8b9d-5a4e-4f3d-9c8b-7d6e5f4a3b2c",5 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",6 "key": "lead_email",7 "prompt": "Extract the email address mentioned by the user.",8 "data_type": "string",9 "store_to_prospect_data": true,10 "is_active": true11 }12 ]13}HTTP Errors
AGENT_NOT_FOUNDAgent not found.
https://api.vanira.io/assistant/:id/data-collectionRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Body Parameters
keyREQUIREDUnique key for this field in extraction results.
promptREQUIREDInstructions for the AI to extract this value.
data_typestring | boolean | number | enum. Default: string.
enum_valuesList of valid values if data_type is enum.
store_to_prospectWhether to store this value in the main prospect record.
prospect_column_nameThe specific column name in the prospect table to map to.
store_to_prospect_dataWhether to store in the custom prospect_data table (key-value storage).
prospect_data_keyThe key to use when storing in prospect_data.
store_directly_to_prospectFlag for direct storage logic.
is_activeWhether to enable this extraction parameter.
Implementation Example
1curl -X POST 'https://api.vanira.io/assistant/<id>/data-collection' \2 -H "Content-Type: application/json" \3 -d '{4 "key": "interested_in_demo",5 "prompt": "Did the user express interest in a demo? Answer yes or no.",6 "data_type": "enum",7 "enum_values": [8 "Interested",9 "Not Interested",10 "Call Back Later"11 ],12 "store_to_prospect": false,13 "prospect_column_name": "<prospect_column_name>",14 "store_to_prospect_data": false,15 "prospect_data_key": "<prospect_data_key>",16 "store_directly_to_prospect": false,17 "is_active": false18}'Expected Response — 200 OK
1{2 "id": "766c8b9d-5a4e-4f3d-9c8b-7d6e5f4a3b2c",3 "key": "interested_in_demo",4 "prompt": "Did the user express interest in a demo? Answer yes or no.",5 "data_type": "boolean",6 "agent_id": "caaa5b2a-5fd9-4974-a59e-1c9c01c4c6f5",7 "created_at": "2026-05-09T12:00:00Z"8}HTTP Errors
BAD_REQUESTInvalid configuration.
AGENT_NOT_FOUNDAgent not found.
https://api.vanira.io/assistant/data-collection/:collection_idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
collection_idREQUIREDUUID of the collection parameter.
Body Parameters
promptUpdated extraction prompt.
data_typeUpdate the expected data type.
enum_valuesUpdate allowed enum values.
store_to_prospectUpdate main record storage setting.
is_activeEnable/disable this parameter.
Implementation Example
1curl -X PATCH 'https://api.vanira.io/assistant/data-collection/<collection_id>' \2 -H "Content-Type: application/json" \3 -d '{4 "prompt": "<prompt>",5 "data_type": "<data_type>",6 "enum_values": "<enum_values>",7 "store_to_prospect": false,8 "is_active": false9}'Expected Response — 200 OK
1{2 "id": "766c8b9d-5a4e-4f3d-9c8b-7d6e5f4a3b2c",3 "key": "lead_email",4 "is_active": false,5 "updated_at": "2026-05-09T12:05:00Z"6}HTTP Errors
DATA_COLLECTION_NOT_FOUNDParameter not found.
https://api.vanira.io/assistant/data-collection/:collection_idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
collection_idREQUIREDUUID of the collection parameter.
Implementation Example
1curl -X DELETE 'https://api.vanira.io/assistant/data-collection/<collection_id>' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "success": true,3 "id": "766c8b9d-5a4e-4f3d-9c8b-7d6e5f4a3b2c"4}HTTP Errors
DATA_COLLECTION_NOT_FOUNDParameter not found.
https://api.vanira.io/assistant/:id/media-handlersRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant/<id>/media-handlers'Expected Response — 200 OK
1{2 "handlers": [3 {4 "id": "m1",5 "agent_id": "caaa5b2a-...",6 "reason": "kyc_photo",7 "route": "webhook",8 "webhook_url": "https://api.acme.com/kyc",9 "inject_as": "system",10 "interrupt": true11 }12 ]13}HTTP Errors
AGENT_NOT_FOUNDAgent not found.
https://api.vanira.io/assistant/:id/media-handlersRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the agent.
Body Parameters
reasonREQUIREDThe routing category/tag sent by the client SDK (e.g. kyc_photo).
routeREQUIRED"vision" (native LLM vision) or "webhook" (external API).
webhook_urlRequired if route is webhook.
webhook_headersCustom headers for the webhook (e.g., API keys).
inject_asREQUIRED"system" or "user". How the parsed media result is injected into the prompt context.
interruptREQUIREDWhether to interrupt the agent mid-sentence when media is processed.
Implementation Example
1curl -X POST 'https://api.vanira.io/assistant/<id>/media-handlers' \2 -H "Content-Type: application/json" \3 -d '{4 "reason": "kyc_photo",5 "route": "webhook",6 "webhook_url": "https://api.acme.com/kyc",7 "webhook_headers": "<webhook_headers>",8 "inject_as": "system",9 "interrupt": true10}'Expected Response — 200 OK
1{2 "id": "new-handler-uuid",3 "reason": "kyc_photo",4 "route": "webhook",5 "inject_as": "system",6 "interrupt": true7}HTTP Errors
BAD_REQUESTInvalid handler configuration.
AGENT_NOT_FOUNDAgent not found.
https://api.vanira.io/assistant/media-handlers/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the media handler.
Body Parameters
reasonUpdated routing category.
routeUpdated routing mode (vision/webhook).
webhook_urlUpdated webhook URL.
inject_asUpdated prompt injection mode.
interruptUpdate interrupt behavior.
Implementation Example
1curl -X PATCH 'https://api.vanira.io/assistant/media-handlers/<id>' \2 -H "Content-Type: application/json" \3 -d '{4 "reason": "<reason>",5 "route": "<route>",6 "webhook_url": "<webhook_url>",7 "inject_as": "<inject_as>",8 "interrupt": false9}'Expected Response — 200 OK
1{2 "id": "handler-uuid",3 "reason": "updated_kyc_photo",4 "updated_at": "2026-05-09T12:05:00Z"5}HTTP Errors
MEDIA_HANDLER_NOT_FOUNDHandler not found.
https://api.vanira.io/assistant/media-handlers/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the media handler.
Implementation Example
1curl -X DELETE 'https://api.vanira.io/assistant/media-handlers/<id>' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "success": true3}HTTP Errors
MEDIA_HANDLER_NOT_FOUNDHandler not found.
https://api.vanira.io/calls/create- *Authentication**
X-API-Key header:sk_live_*— secret key (server-side). Can create bothwebandsipcalls.pk_live_*— publishable key (browser/widget). Can only createwebcalls. Use*to allow all origins, or set domains to restrict usage.
- *SIP vs Web**
type to "sip" for outbound phone calls or "web" for in-browser WebRTC sessions.For SIP calls,
sip_data (phone number + name) is required.- Dynamic DID Selection: If
sip_data.from_numberis provided, it must be a provisioned number owned by the client. - Automated Fallback: If
sip_data.from_numberis omitted, the backend automatically selects a default number from the Vanira managed pool. - Strict Validation: All phone numbers are strictly validated against E.164 format (7-15 digits).
prospect_id is optional — a new anonymous prospect is created if omitted.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
agent_idREQUIREDUUID of the voice agent that will handle the call.
typeREQUIRED"web" for an in-browser WebRTC session. "sip" for an outbound phone call. Note: pk_live_* keys can only create web calls.
sip_dataRequired when type is "sip". Nested object containing the call destination. See sip_data.to and sip_data.name below.
sip_data.toE.164 formatted destination phone number. Required when type is "sip". Example: +919182517283 (country code + number, no spaces or dashes).
sip_data.nameDisplay name of the person being called. Used for prospect creation and call logging. Defaults to "Unknown" if omitted.
sip_data.from_numberOptional. The provisioned phone number (E.164) to dial from. If omitted, Vanira uses its shared pool default.
prospect_idOptional. Link the call to an existing prospect record. If omitted for web calls, an anonymous prospect is created automatically.
Implementation Example
1curl -X POST 'https://api.vanira.io/calls/create' \2 -H "Content-Type: application/json" \3 -d '{4 "agent_id": "919801d9-f357-4033-8ea0-97de12a989c2",5 "type": "web",6 "sip_data": {7 "to": "+919182517283",8 "name": "John Doe"9 },10 "sip_data.to": "+919182517283",11 "sip_data.name": "John Doe",12 "sip_data.from_number": "+918071387205",13 "prospect_id": "7fdc9111-2b35-4252-a85c-781c37470ac0"14}'Expected Response — 200 OK
1// Web call response2{3 "call_id": "da4ca1e9-e488-4059-b1d2-fdc348d26950",4 "status": "in-progress",5 "worker_url": "https://<worker>.vanira.io/webrtc?agent=919801d9..._da4ca1e9..."6}7 8// SIP call response9{10 "call_id": "6fdc9111-2b35-4252-a85c-781c37470ac0",11 "status": "triggered",12 "worker_url": null13}Response Schema Details
call_idREQUIREDUnique identifier for the created call record.
statusREQUIRED"in-progress" for web calls. "triggered" for SIP calls.
worker_urlWebRTC worker URL to connect to. Only returned for type="web". Pass this to the Vanira SDK.
HTTP Errors
UNAUTHORIZEDNo X-API-Key header provided.
INVALID_API_KEYAPI key is invalid, revoked, or the secret does not match.
INSUFFICIENT_CREDITSClient has no available call credits.
INSUFFICIENT_SCOPEPublishable key (pk_live_*) attempted to create a SIP call.
AGENT_NOT_FOUNDNo agent exists with the provided agent_id.
PROSPECT_NOT_FOUNDThe provided prospect_id does not exist.
VALIDATION_ERRORInvalid E.164 format (7-15 digits) or missing required fields.
UPSTREAM_SERVICE_TIMEOUTSIP gateway is unreachable or returned an error.
DATABASE_ERRORUnexpected server error.
https://api.vanira.io/calls- *Authentication**
X-API-Key: sk_live_* or Authorization: Bearer <token>. Publishable keys cannot access call history.- *Filtering**
Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Query Parameters
agent_idFilter calls by a specific agent UUID.
statusFilter by call status: triggered | in-progress | completed | failed.
limitNumber of results to return. Default 100, max 500.
offsetNumber of results to skip for pagination.
Implementation Example
1curl -X GET 'https://api.vanira.io/calls?agent_id=919801d9-f357-4033-8ea0-97de12a989c2&status=completed&limit=25&offset=0'Expected Response — 200 OK
1{2 "calls": [3 {4 "id": "da4ca1e9-e488-4059-b1d2-fdc348d26950",5 "agent_id": "919801d9-f357-4033-8ea0-97de12a989c2",6 "client_id": "91b5f2de-9e01-4520-837f-58f284e40a4c",7 "phone_to": "+917268030283",8 "phone_from": null,9 "status": "completed",10 "direction": "outbound",11 "type": "sip_call",12 "created_at": "2026-05-01T10:00:00Z",13 "duration": 142,14 "recording_url": null,15 "is_call_successful_according_to_agent_criteria": true,16 "prospect": { "id": "<uuid>", "name": "John Doe", "phone": "+917268030283" },17 "agent": { "id": "919801d9-...", "name": "Support Agent" },18 "call_data": [{ "key": "sentiment", "value": "positive" }]19 }20 ],21 "total": 330822}Response Schema Details
callsREQUIREDArray of call objects.
totalREQUIREDTotal matching calls across all pages (use for pagination UI).
calls[].idREQUIREDCall UUID.
calls[].statusREQUIREDtriggered | in-progress | completed | failed.
calls[].directioninbound (web) or outbound (SIP).
calls[].typeweb_call or sip_call.
calls[].durationCall duration in seconds.
calls[].recording_urlURL to the call recording if available.
calls[].prospectLinked prospect name and phone.
calls[].agentAgent id and name.
calls[].call_dataStructured key/value output from the agent (sentiment, outcome, etc.).
HTTP Errors
UNAUTHORIZEDNo X-API-Key header provided.
INVALID_API_KEYAPI key is invalid or revoked.
INSUFFICIENT_SCOPEPublishable key (pk_live_*) cannot access call history.
DATABASE_ERRORUnexpected server error.
https://api.vanira.io/calls/:id- *Authentication**
X-API-Key: sk_live_* or Authorization: Bearer <token>. Publishable keys (pk_live_*) cannot access call details.The authenticated client must own the call — requests for calls belonging to other clients return 404.
Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the call to retrieve. Returned by POST /calls/create as call_id.
Implementation Example
1curl -X GET 'https://api.vanira.io/calls/6fdc9111-2b35-4252-a85c-781c37470ac0'Expected Response — 200 OK
1{2 "id": "6fdc9111-2b35-4252-a85c-781c37470ac0",3 "agent_id": "919801d9-f357-4033-8ea0-97de12a989c2",4 "client_id": "91b5f2de-9e01-4520-837f-58f284e40a4c",5 "phone_from": "+919182517283",6 "phone_to": "+917268030283",7 "status": "completed",8 "call_triggered_at": "2026-03-13T10:00:00Z",9 "extra_details": { "duration": 142 },10 "provider_call_id": "prov-abc-123",11 "prospect": {12 "id": "<prospect-uuid>",13 "name": "John Doe",14 "phone": "+919182517283",15 "prospect_data": [16 { "key": "company", "value": "Acme Corp" }17 ]18 },19 "agent": {20 "id": "919801d9-f357-4033-8ea0-97de12a989c2",21 "client": {22 "name": "Demo Client",23 "base_prospect_group_id": "<group-uuid>"24 }25 }26}Response Schema Details
idREQUIREDCall UUID.
agent_idREQUIREDUUID of the agent that handled the call.
client_idREQUIREDUUID of the client who owns this call.
phone_fromCaller's phone number.
phone_toDialled phone number.
statusCall status: triggered | in-progress | completed | failed.
call_triggered_atISO 8601 timestamp when the call was initiated.
extra_detailsArbitrary metadata returned by the telephony provider (duration, recording_url, etc.).
provider_call_idProvider-side call identifier.
prospectLinked prospect with name, phone, and prospect_data key/value pairs.
agentAgent info including nested client name and base_prospect_group_id.
HTTP Errors
UNAUTHORIZEDNo X-API-Key header provided.
INVALID_API_KEYAPI key is invalid or revoked.
INSUFFICIENT_SCOPEPublishable key (pk_live_*) cannot access call details.
CALL_NOT_FOUNDCall not found, or the authenticated client does not own this call.
VALIDATION_ERRORid path parameter is not a valid UUID.
DATABASE_ERRORUnexpected server error.
https://api.vanira.io/campaignsfrom_numbers or set use_vanira_managed to true; otherwise, creation will fail.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
nameREQUIREDThe name of the campaign
agent_idREQUIREDID of the voice agent to use
candidatesREQUIREDList of prospects including name and phone number
providerREQUIREDThe voice provider to use (e.g., vonage, twilio)
timezoneREQUIREDTimezone for the campaign scheduling
call_hours_startREQUIREDDaily start time for calls (HH:MM:SS)
call_hours_endREQUIREDDaily end time for calls (HH:MM:SS)
call_daysREQUIREDDays of the week to make calls
max_concurrent_callsREQUIREDMaximum number of simultaneous calls
call_timeout_secondsREQUIREDSeconds to wait before considering a call timed out
start_campaignREQUIREDWhether to start the campaign immediately after upload
from_numbersOptional list of E.164 phone numbers to use as Caller IDs. System will resolve and allocate them automatically.
use_vanira_managedOptional. If true, the campaign will also use Vanira internal managed numbers.
retry_failed_callsREQUIREDRetry calls that failed (e.g. error/network issue)
max_retries_failedREQUIREDMaximum number of retries for failed calls
retry_delay_failed_secondsREQUIREDSeconds to wait before retrying a failed call
retry_busy_callsREQUIREDRetry calls where the line was busy
max_retries_busyREQUIREDMaximum number of retries for busy calls
retry_delay_busy_secondsREQUIREDSeconds to wait before retrying a busy call
retry_no_answer_callsREQUIREDRetry calls where there was no answer
max_retries_no_answerREQUIREDMaximum number of retries for no-answer calls
retry_delay_no_answer_secondsREQUIREDSeconds to wait before retrying a no-answer call
Implementation Example
1curl -X POST 'https://api.vanira.io/campaigns' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "Q1 Feedback Survey",5 "agent_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",6 "candidates": [7 {8 "name": "John Doe",9 "phone": "+1234567890"10 }11 ],12 "provider": "vonage",13 "timezone": "Asia/Kolkata",14 "call_hours_start": "09:00:00",15 "call_hours_end": "18:00:00",16 "call_days": [17 "Monday",18 "Tuesday",19 "Wednesday",20 "Thursday",21 "Friday"22 ],23 "max_concurrent_calls": 5,24 "call_timeout_seconds": 60,25 "start_campaign": true,26 "from_numbers": [27 "+918071387205",28 "+919876543210"29 ],30 "use_vanira_managed": true,31 "retry_failed_calls": true,32 "max_retries_failed": 3,33 "retry_delay_failed_seconds": 300,34 "retry_busy_calls": true,35 "max_retries_busy": 2,36 "retry_delay_busy_seconds": 180,37 "retry_no_answer_calls": true,38 "max_retries_no_answer": 3,39 "retry_delay_no_answer_seconds": 60040}'Expected Response — 200 OK
1{2 "success": true,3 "campaign_id": "c1234567-89ab-cdef-0123-456789abcdef",4 "total_prospects": 2,5 "message": "Campaign created successfully",6 "started": false7}Response Schema Details
successREQUIREDAlways true on success.
campaign_idREQUIREDUUID of the created campaign.
total_prospectsREQUIREDNumber of prospects added.
messageREQUIREDHuman-readable status message.
startedREQUIREDTrue if campaign was auto-started.
HTTP Errors
validation_errorMore than 50 candidates provided.
bad_requestNo Caller IDs provided. You must either provide from_numbers or set use_vanira_managed to true.
BAD_REQUEST_FORMATMissing required fields (agent_id, name, candidates).
AGENT_NOT_FOUNDAgent not found or agent has no associated client.
INTERNAL_SERVER_ERRORFailed to create prospect group or insert prospects.
UPSTREAM_SERVICE_ERRORCampaign API or SIP gateway is unreachable.
https://api.vanira.io/campaigns/:id/startRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to start.
Implementation Example
1curl -X POST 'https://api.vanira.io/campaigns/1a817016-a3f5-41c1-995c-c74a5fb33720/start' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "success": true,3 "campaign_id": "1a817016-a3f5-41c1-995c-c74a5fb33720",4 "status": "active",5 "message": "Campaign started successfully",6 "extra_data": {7 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",8 "status": "active"9 }10}Response Schema Details
successREQUIREDAlways true on success.
campaign_idREQUIREDUUID of the campaign.
statusNew campaign status returned by the Campaign API.
messageREQUIREDHuman-readable result.
extra_dataRaw upstream Campaign API response.
HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found or not owned by the authenticated client.
BAD_REQUEST_FORMATCampaign ID is not a valid UUID.
gateway_errorCampaign API unreachable or returned an error.
https://api.vanira.io/campaigns/:id/pauseRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to pause.
Implementation Example
1curl -X POST 'https://api.vanira.io/campaigns/1a817016-a3f5-41c1-995c-c74a5fb33720/pause' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "success": true,3 "campaign_id": "1a817016-a3f5-41c1-995c-c74a5fb33720",4 "status": "paused",5 "message": "Campaign paused successfully",6 "extra_data": {7 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",8 "status": "paused"9 }10}Response Schema Details
successREQUIREDAlways true on success.
campaign_idREQUIREDUUID of the campaign.
statusNew status (paused).
messageREQUIREDHuman-readable result.
extra_dataRaw upstream Campaign API response.
HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found or not owned by the authenticated client.
BAD_REQUEST_FORMATCampaign ID is not a valid UUID.
gateway_errorCampaign API unreachable or returned an error (e.g. already paused).
https://api.vanira.io/campaigns/:id/resumeRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to resume.
Implementation Example
1curl -X POST 'https://api.vanira.io/campaigns/1a817016-a3f5-41c1-995c-c74a5fb33720/resume' \2 -H "Content-Type: application/json"Expected Response — 200 OK
1{2 "success": true,3 "campaign_id": "1a817016-a3f5-41c1-995c-c74a5fb33720",4 "status": "active",5 "message": "Campaign resumed successfully",6 "extra_data": {7 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",8 "status": "active"9 }10}Response Schema Details
successREQUIREDAlways true on success.
campaign_idREQUIREDUUID of the campaign.
statusNew status (active).
messageREQUIREDHuman-readable result.
extra_dataRaw upstream Campaign API response.
HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found or not owned by the authenticated client.
BAD_REQUEST_FORMATCampaign ID is not a valid UUID.
gateway_errorCampaign API unreachable or returned an error (e.g. not paused).
https://api.vanira.io/campaigns/:id/schedule-startRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to schedule.
Body Parameters
scheduled_start_timeREQUIREDISO 8601 datetime for the auto-start (must be in the future).
Implementation Example
1curl -X POST 'https://api.vanira.io/campaigns/1a817016-a3f5-41c1-995c-c74a5fb33720/schedule-start' \2 -H "Content-Type: application/json" \3 -d '{4 "scheduled_start_time": "2026-04-01T09:00:00Z"5}'Expected Response — 200 OK
1{2 "success": true,3 "campaign_id": "1a817016-a3f5-41c1-995c-c74a5fb33720",4 "scheduled_start_time": "2026-04-01T09:00:00Z",5 "status": "scheduled",6 "message": "Campaign start scheduled successfully",7 "extra_data": {8 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",9 "status": "scheduled"10 }11}Response Schema Details
successREQUIREDAlways true on success.
campaign_idREQUIREDUUID of the campaign.
scheduled_start_timeREQUIREDConfirmed scheduled start time.
statusCampaign status after scheduling.
messageREQUIREDHuman-readable result.
extra_dataRaw upstream Campaign API response.
HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found or not owned by the authenticated client.
BAD_REQUEST_FORMATCampaign ID is not a valid UUID, or scheduled_start_time is blank/missing.
gateway_errorCampaign API unreachable or returned an error (e.g. time in the past).
https://api.vanira.io/campaignsRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/campaigns'Expected Response — 200 OK
1{2 "data": [3 {4 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",5 "name": "Q1 Outreach",6 "status": "active",7 "agent_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",8 "client_id": "c2d3e4f5-1111-2222-3333-444455556666",9 "provider": "vobiz",10 "total_prospects": 150,11 "successful_calls": 45,12 "failed_calls": 12,13 "created_at": "2026-03-29T10:00:00Z",14 "updated_at": "2026-03-29T10:00:00Z"15 }16 ]17}HTTP Errors
BAD_REQUEST_FORMATInvalid client_id format
https://api.vanira.io/campaigns/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to fetch.
Implementation Example
1curl -X GET 'https://api.vanira.io/campaigns/<id>'Expected Response — 200 OK
1{2 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",3 "name": "Q1 Outreach",4 "status": "active",5 "max_concurrent_calls": 3,6 "timezone": "Asia/Kolkata",7 "call_timeout_seconds": 60,8 "allow_reschedule": true,9 "max_reschedules_per_prospect": 3,10 "reschedule_min_delay_hours": 1,11 "total_prospects": 150,12 "active_prospects": 2,13 "pending_prospects": 91,14 "is_hr_campaign": false,15 "created_at": "2026-03-29T10:00:00Z",16 "allocated_dids": [17 {18 "did_id": "09d89078-b9cc-452d-ae06-126d04239b73",19 "number": "918071387205",20 "max_concurrent_calls": 321 }22 ]23}Response Schema Details
idREQUIREDUUID of the campaign.
nameREQUIREDCampaign name.
statusREQUIREDCurrent status (draft, active, paused, scheduled, completed).
allocated_didsList of phone numbers (Caller IDs) assigned to this campaign.
allocated_dids[].numberREQUIREDThe E.164 phone number.
total_prospectsTotal number of contacts in the campaign.
active_prospectsNumber of contacts currently being called.
HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found
https://api.vanira.io/campaigns/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the campaign to update.
Body Parameters
nameNew name for the campaign
max_concurrent_callsMaximum concurrent calls allowed
allow_rescheduleWhether to allow rescheduling calls
max_reschedules_per_prospectMaximum reschedules allowed per prospect
Implementation Example
1curl -X PATCH 'https://api.vanira.io/campaigns/<id>' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "<name>",5 "max_concurrent_calls": null,6 "allow_reschedule": false,7 "max_reschedules_per_prospect": null8}'Expected Response — 200 OK
1{2 "id": "1a817016-a3f5-41c1-995c-c74a5fb33720",3 "name": "Updated Campaign Name",4 "status": "paused",5 "updated_at": "2026-03-29T10:05:00Z"6}HTTP Errors
CAMPAIGN_NOT_FOUNDCampaign not found
BAD_REQUESTNo fields provided
VALIDATION_ERRORInvalid fields format
https://api.vanira.io/inbox/sendRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
inbox_idREQUIREDUUID of the connected WhatsApp inbox.
toREQUIREDRecipient phone number in E.164 format.
messageREQUIREDMessage content to send.
Implementation Example
1curl -X POST 'https://api.vanira.io/inbox/send' \2 -H "Content-Type: application/json" \3 -d '{4 "inbox_id": "<inbox-uuid>",5 "to": "+919182517283",6 "message": "Hello from API!"7}'Expected Response — 200 OK
1{2 "success": true,3 "message_id": "<message-uuid>",4 "status": "sent"5}Response Schema Details
successREQUIREDtrue if the message was queued successfully.
message_idUnique identifier for the sent message.
statusMessage status: sent | queued | failed.
HTTP Errors
missing_fieldinbox_id, to, or message was not provided.
inbox_not_foundNo WhatsApp inbox exists with the provided inbox_id.
inbox_not_authenticatedThe inbox has not been authenticated (QR code not scanned).
whatsapp_unavailableWhatsApp service is unavailable or the number is unreachable.
https://api.vanira.io/leadsRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/leads'Expected Response — 200 OK
1{2 "leads": [3 {4 "id": "e30e70ab-7d43-4a11-b75c-3f2d2948cba4",5 "client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",6 "name": "John Doe",7 "phone_number": "+1234567890",8 "email_id": "john.doe@example.com",9 "alternate_phone_number": null,10 "alternate_email_id": null,11 "lead_source": "Website",12 "status": "New",13 "remarks": "Interested in premium plan",14 "created_at": "2026-04-20T10:30:00Z",15 "updated_at": "2026-04-20T10:30:00Z"16 }17 ]18}Response Schema Details
idREQUIREDUnique identifier for the lead.
client_idREQUIREDOwner organization ID.
nameFull name of the lead.
phone_numberPrimary phone number.
email_idPrimary email address.
lead_sourceSource of the lead (e.g., Website, Import).
statusCurrent status of the lead.
HTTP Errors
UNAUTHORIZEDMissing or invalid API key.
DATABASE_ERRORDatabase connectivity issue.
https://api.vanira.io/leads/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the lead to retrieve.
Implementation Example
1curl -X GET 'https://api.vanira.io/leads/e30e70ab-7d43-4a11-b75c-3f2d2948cba4'Expected Response — 200 OK
1{2 "id": "e30e70ab-7d43-4a11-b75c-3f2d2948cba4",3 "client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",4 "name": "John Doe",5 "phone_number": "+1234567890",6 "email_id": "john.doe@example.com",7 "alternate_phone_number": null,8 "alternate_email_id": null,9 "lead_source": "Website",10 "status": "New",11 "remarks": "Interested in premium plan",12 "created_at": "2026-04-20T10:30:00Z",13 "updated_at": "2026-04-20T10:30:00Z"14}Response Schema Details
idREQUIREDUnique identifier for the lead.
client_idREQUIREDOwner organization ID.
nameFull name of the lead.
phone_numberPrimary phone number.
email_idPrimary email address.
lead_sourceSource of the lead (e.g., Website, Import).
statusCurrent status of the lead.
HTTP Errors
UNAUTHORIZEDMissing or invalid API key.
LEAD_NOT_FOUNDNo lead exists with the provided UUID.
VALIDATION_ERRORInvalid UUID format.
DATABASE_ERRORDatabase connectivity issue.
Overview
- *Two tool types**
- *Server tools** — the AI calls your HTTP webhook with extracted parameters. Your server processes the request and returns a result. The AI uses the result in its next response.
- *Client tool kinds** (documented separately):
| Page | What it covers |
|---|---|
| Preset Tools | Built-in UI — form, calendar, navigate, DOM actions, screen overlay, … |
| Custom Client Tools | Your own handler — popups, API calls, custom logic |
- *Server tools — HTTP webhooks; see Create Tool** for
POST /toolspayload shape.
{{param_name}} in request.body or client_fields for AI-extracted values; plain strings for static fields.Preset Tools
- *Preset tools** are built-in client tools with ready-made UI. The SDK renders them automatically — no
onCustomToolhandler needed.
client_fields.preset_id when creating the tool. With VaniraCallBox or PresetRenderer, preset UI appears on its own.Add a preset (dashboard)
- *Agent → Tools → Create tool → Client** — pick a preset tile (Form, Calendar, Navigate, Upload, …). Attach to your agent.
Add a preset (API)
POST /tools — copy a body below (set client_fields.preset_id)2.
POST /assistant/{agent_id}/tools — attach with { "tool_id": "<uuid>" }1# 1. Create2curl -X POST https://api.vanira.io/tools \3 -H "X-API-Key: sk_live_..." \4 -H "Content-Type: application/json" \5 -d @vanira_form_tool.json6 7# 2. Attach to agent8curl -X POST https://api.vanira.io/assistant/YOUR_AGENT_ID/tools \9 -H "X-API-Key: sk_live_..." \10 -H "Content-Type: application/json" \11 -d '{"tool_id": "TOOL_UUID_FROM_STEP_1"}'All preset IDs
| Preset ID | UI | Mode |
|---|---|---|
vanira_form | Data Collection Form | blocking |
vanira_calendar | Date & Time Picker | blocking |
vanira_upload | File Upload | blocking |
vanira_camera | Camera Capture | fire_and_forget |
vanira_navigate | Navigate to Route — requires vanira:navigate listener on SPAs | blocking |
vanira_highlight_element | Highlight Element | blocking |
vanira_click_element | Click Element | blocking |
vanira_select_option | Select Dropdown Option | blocking |
vanira_set_date | Set Date Field | blocking |
vanira_type_text | DOM Typing Simulation | blocking |
vanira_erase_text | Whiteboard / DOM Erase | blocking |
vanira_erase_draw | Erase Drawing Board | blocking |
vanira_draw | Chalkboard Shape Drawing | blocking |
vanira_live_vision | Live Vision (Streaming Camera) | fire_and_forget |
vanira_close_live_camera | Stop Live Camera | blocking |
vanira_live_screen | Live Screen Share | fire_and_forget |
vanira_close_live_screen | Stop Live Screen Share | blocking |
vanira_clip_region | Page Region Clip | blocking |
vanira_tab_screenshot | Tab Screenshot | blocking |
vanira_screen_ink | Screen Ink | blocking |
vanira_screen_cursor | Screen Cursor | blocking |
vanira_screen_click | Screen Click | blocking |
vanira_clear_screen_overlay | Clear Screen Overlay | blocking |
vanira_page_scan | Page Scan | blocking |
vanira_point_at | Point At | blocking |
vanira_outline_targets | Outline Targets | blocking |
vanira_clear_guide | Clear Guide | blocking |
- *Blocking presets wait for `sendToolResult()` (the SDK sends it when the user completes or dismisses the UI). fire_and_forget** presets do not block the agent.
DOM presets — route in client_fields
vanira_click_element, vanira_select_option, vanira_set_date, vanira_type_text, and vanira_erase_text, set route to the SPA path where the target element lives. The SDK navigates first if needed.Navigate preset — SPA listener
vanira_navigate, the SDK dispatches a browser event instead of forcing a full page reload:| Target | SDK behavior |
|---|---|
Same-origin path (e.g. /pricing, /docs#faq) | Fires vanira:navigate with detail.path — your site must handle it |
| External URL (different origin) | Opens in a new tab automatically — no listener needed |
- *SPA sites (React, Vue, Next.js, etc.) must register a
vanira:navigatelistener** that routes with your framework and setsevent.detail.handled = true. Without it, same-origin navigation fails withstatus: cancelledand the console shows:No SPA listener handled vanira:navigate.
- *Blocking tool:** the AI pauses until the SDK sends
client_tool_result. Success payload:{ status: 'success', navigated_to, target_url }. Server interrupt (clearAudio/client_tool_cancel):{ status: 'interrupted', reason, target_url }.
- *Multi-page sites** can use
window.location.assign(event.detail.path)in the listener, or the same pattern as a fallback.
Copy-paste POST /tools bodies
vanira_form — Data Collection Form
client_tool_result with submitted fields.- *Create tool body** (
POST /tools):
1{2 "name": "collect_user_data",3 "ref_code": "collect_user_data",4 "description": "Call this tool to display a form to collect information from the user.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "reason",11 "type": "string",12 "description": "A short message explaining why you need their info (e.g., \"To look up your order\").",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_form",18 "title": "Enter your details",19 "fields": "Name, Email, Phone"20 }21}vanira_calendar — Date & Time Picker
slots_api_url for live availability. blocking.- *Create tool body** (
POST /tools):
1{2 "name": "display_booking_calendar",3 "ref_code": "display_booking_calendar",4 "description": "Call this tool to display a calendar for the user to select an appointment date and time.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "reason",11 "type": "string",12 "description": "A short message explaining why they need to pick a time (e.g., \"To schedule your consultation\").",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_calendar",18 "title": "Select a Date & Time",19 "timezone": "America/New_York",20 "slots_api_url": "https://api.example.com/slots?date={{date}}&tz={{timezone}}",21 "slots_api_method": "GET",22 "slots_api_headers": "{\"Authorization\": \"Bearer YOUR_TOKEN\"}",23 "slots_api_body": "{}"24 }25}vanira_upload — File Upload
client_tool_result includes media_id when upload succeeds.- *Create tool body** (
POST /tools):
1{2 "name": "request_file_upload",3 "ref_code": "request_file_upload",4 "description": "Call this tool to ask the user to upload a file (image, PDF, document, CSV) so the agent can inspect or process it.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "reason",11 "type": "string",12 "description": "A short message explaining why you need the file (e.g., \"To verify your identity\").",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_upload",18 "title": "Upload a File",19 "description": "Drop or select any file — images, PDFs, documents — up to 3 MB",20 "reason": "upload",21 "accept": "application/pdf,image/*"22 }23}vanira_camera — Camera Capture
- *Create tool body** (
POST /tools):
1{2 "name": "open_camera",3 "ref_code": "open_camera",4 "description": "Call this tool to open the user's camera so they can take a photo for you to inspect (e.g. damage, hardware issue, ID verification).",5 "type": "client",6 "execution_mode": "fire_and_forget",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "reason",11 "type": "string",12 "description": "A short message explaining why you need a photo (e.g., \"To inspect the damage on your device\").",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_camera",18 "title": "Take a Photo",19 "description": "Point your camera at the subject, then tap capture to send it to your agent.",20 "reason": "camera_capture",21 "facing_mode": "environment",22 "liveness_check": false23 }24}vanira_navigate — Navigate to Route
vanira:navigate — register a listener on your site (see SPA setup below). External URLs open in a new tab. blocking — AI waits for client_tool_result; server interrupt returns status: interrupted.- *Create tool body** (
POST /tools):
1{2 "name": "navigate_user",3 "ref_code": "navigate_user",4 "description": "Call this tool to redirect the user to a different route.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_navigate",11 "target_url": "/pricing"12 }13}vanira_navigate, the SDK dispatches a browser event instead of forcing a full page reload:| Target | SDK behavior |
|---|---|
Same-origin path (e.g. /pricing, /docs#faq) | Fires vanira:navigate with detail.path — your site must handle it |
| External URL (different origin) | Opens in a new tab automatically — no listener needed |
- *SPA sites (React, Vue, Next.js, etc.) must register a
vanira:navigatelistener** that routes with your framework and setsevent.detail.handled = true. Without it, same-origin navigation fails withstatus: cancelledand the console shows:No SPA listener handled vanira:navigate.
- *Blocking tool:** the AI pauses until the SDK sends
client_tool_result. Success payload:{ status: 'success', navigated_to, target_url }. Server interrupt (clearAudio/client_tool_cancel):{ status: 'interrupted', reason, target_url }.
- *Multi-page sites** can use
window.location.assign(event.detail.path)in the listener, or the same pattern as a fallback.
- *Listener snippet** (add to your site):
1// Add once on your site (same page as the Vanira widget).2// Required when your agent uses the vanira_navigate preset.3window.addEventListener('vanira:navigate', (event) => {4 const path = event.detail.path; // e.g. "/pricing" or "/docs#section"5 6 // Option A — multi-page site or simple fallback:7 window.location.assign(path);8 9 // Option B — SPA router (pick one that matches your stack):10 // router.push(path); // React Router: useNavigate()11 // navigate(path); // Vue Router12 // router.push(path); // Next.js App Router13 14 event.detail.handled = true; // required — tells the SDK navigation succeeded15});vanira_highlight_element — Highlight Element
- *Create tool body** (
POST /tools):
1{2 "name": "highlight_ui_element",3 "ref_code": "highlight_ui_element",4 "description": "Call this tool to draw the user's attention to a specific button or element on the page.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_highlight_element",11 "css_selector": "#buy-button",12 "color": "#10B981"13 }14}vanira_click_element — Click Element
id (no #). route required — SDK navigates first when the user is on another page. blocking.- *Create tool body** (
POST /tools):
1{2 "name": "click_button",3 "ref_code": "click_button",4 "description": "Call this tool to click a specific button on the user's screen by HTML id.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_click_element",11 "element_id": "buy-button",12 "route": "/checkout"13 }14}vanira_select_option — Select Dropdown Option
<select> or custom dropdown by HTML id. route required — SDK navigates first. blocking.- *Create tool body** (
POST /tools):
1{2 "name": "select_option",3 "ref_code": "select_option",4 "description": "Call this tool to select a dropdown option on the user's page (e.g. country, cabin class).",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "option_value",11 "type": "string",12 "description": "Option value attribute (e.g. economy, IN).",13 "required": false14 },15 {16 "name": "option_label",17 "type": "string",18 "description": "Visible label to match (e.g. Economy, India).",19 "required": false20 }21 ],22 "client_fields": {23 "preset_id": "vanira_select_option",24 "element_id": "country-select",25 "route": "/flights",26 "allowed_options": ["economy", "business", "first_class"]27 }28}vanira_set_date — Set Date Field
id. Agent passes ISO date; SDK formats per text_format. route required. blocking.- *Create tool body** (
POST /tools):
1{2 "name": "set_date_field",3 "ref_code": "set_date_field",4 "description": "Call this tool to set a departure, check-in, or delivery date on the user's form.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "date",11 "type": "string",12 "description": "Date in ISO YYYY-MM-DD (e.g. 2026-06-15).",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_set_date",18 "element_id": "departure-date",19 "route": "/flights",20 "input_kind": "text",21 "text_format": "DD/MM/YYYY"22 }23}vanira_type_text — DOM Typing Simulation
typing_mode: append (boards) or replace (search bars). route only when CSS selector / element id is set. blocking.- *Create tool body** (
POST /tools):
1{2 "name": "type_on_whiteboard",3 "ref_code": "type_on_whiteboard",4 "description": "Call when writing something visible to the student — a formula, solution step, definition, or note. Pass text_to_type with the exact text.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "text_to_type",11 "type": "string",12 "description": "Exact text to write — equations (F=ma), solution steps, definitions, or form values from the conversation.",13 "required": true14 }15 ],16 "client_fields": {17 "preset_id": "vanira_type_text",18 "css_selector": "#answer-input",19 "element_id": "",20 "route": "/lesson",21 "typing_mode": "append",22 "delay_ms": 5023 }24}vanira_erase_text — Whiteboard / DOM Erase
route only when element id is set. blocking — call sendToolResult() when done.- *Create tool body** (
POST /tools):
1{2 "name": "erase_text",3 "ref_code": "erase_text",4 "description": "Call this tool to clear the whiteboard or erase the last few words.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "mode",11 "type": "string",12 "description": "Whether to erase everything (\"all\") or just the last few words (\"words\").",13 "required": false,14 "enum": ["all", "words"]15 },16 {17 "name": "num_words",18 "type": "number",19 "description": "The number of words to erase (only used if mode is \"words\").",20 "required": false21 }22 ],23 "client_fields": {24 "preset_id": "vanira_erase_text",25 "element_id": "#search-input",26 "route": "/search",27 "delay_ms": 5028 }29}vanira_erase_draw — Erase Drawing Board
- *Create tool body** (
POST /tools):
1{2 "name": "erase_drawing_board",3 "ref_code": "erase_drawing_board",4 "description": "Call this tool to clear the diagram/drawing area on the chalkboard. Written notes stay.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_erase_draw"11 }12}vanira_draw — Chalkboard Shape Drawing
- *Create tool body** (
POST /tools):
1{2 "name": "draw_on_board",3 "ref_code": "draw_on_board",4 "description": "Draw one shape on the chalkboard. Call again for each extra shape or label.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "shape_type",11 "type": "enum",12 "description": "line | circle | triangle | rectangle | label",13 "required": false,14 "enum": ["line", "circle", "triangle", "rectangle", "label"]15 },16 {17 "name": "p1_x",18 "type": "number",19 "description": "Triangle apex X (e.g. 400) or line start X",20 "required": false21 },22 {23 "name": "p1_y",24 "type": "number",25 "description": "Triangle apex Y (e.g. 80) or line start Y",26 "required": false27 },28 {29 "name": "p2_x",30 "type": "number",31 "description": "Triangle base corner B X (e.g. 120)",32 "required": false33 },34 {35 "name": "p2_y",36 "type": "number",37 "description": "Triangle base corner B Y (e.g. 420)",38 "required": false39 },40 {41 "name": "p3_x",42 "type": "number",43 "description": "Triangle base corner C X (e.g. 680)",44 "required": false45 },46 {47 "name": "p3_y",48 "type": "number",49 "description": "Triangle base corner C Y (e.g. 420)",50 "required": false51 },52 {53 "name": "center_x",54 "type": "number",55 "description": "Circle center X (e.g. 400)",56 "required": false57 },58 {59 "name": "center_y",60 "type": "number",61 "description": "Circle center Y (e.g. 250)",62 "required": false63 },64 {65 "name": "radius",66 "type": "number",67 "description": "Circle radius (e.g. 90)",68 "required": false69 },70 {71 "name": "label_x",72 "type": "number",73 "description": "Label position X",74 "required": false75 },76 {77 "name": "label_y",78 "type": "number",79 "description": "Label position Y",80 "required": false81 },82 {83 "name": "label_text",84 "type": "string",85 "description": "Label text (e.g. A)",86 "required": false87 },88 {89 "name": "clear_old_diagrams_on_board",90 "type": "boolean",91 "description": "True only when old diagram is not needed — wipes top panel (notes stay). Default false while building.",92 "required": false93 },94 {95 "name": "clear_drawings",96 "type": "boolean",97 "description": "Deprecated — use clear_old_diagrams_on_board",98 "required": false99 }100 ],101 "client_fields": {102 "preset_id": "vanira_draw",103 "shape_duration_ms": 2000,104 "shape_gap_ms": 80105 }106}vanira_live_vision — Live Vision (Streaming Camera)
- *Create tool body** (
POST /tools):
1{2 "name": "open_live_camera",3 "ref_code": "open_live_camera",4 "description": "Call this tool to open the user's camera and start a live video stream so you can continuously see what they're looking at.",5 "type": "client",6 "execution_mode": "fire_and_forget",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "scope",11 "type": "string",12 "description": "How long to stream: until_call_end (default), timed (N seconds), or full_call.",13 "required": false,14 "enum": ["until_call_end", "timed", "full_call"]15 },16 {17 "name": "duration_sec",18 "type": "number",19 "description": "Seconds to stream (only used when scope is \"timed\").",20 "required": false21 },22 {23 "name": "reason",24 "type": "string",25 "description": "Routing key for the media server (e.g. \"damage_inspection\").",26 "required": false27 }28 ],29 "client_fields": {30 "preset_id": "vanira_live_vision",31 "target_fps": 1,32 "max_width": 640,33 "facing_mode": "environment",34 "reason": "camera_capture",35 "show_preview": true36 }37}vanira_close_live_camera — Stop Live Camera
- *Create tool body** (
POST /tools):
1{2 "name": "close_live_camera",3 "ref_code": "close_live_camera",4 "description": "Call this tool to stop the live camera stream and close the camera session.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_close_live_camera"11 }12}vanira_live_screen — Live Screen Share
- *Create tool body** (
POST /tools):
1{2 "name": "open_live_screen",3 "ref_code": "open_live_screen",4 "description": "Call this tool to ask the user to share their screen so you can continuously see what they are working on.",5 "type": "client",6 "execution_mode": "fire_and_forget",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "scope",11 "type": "string",12 "description": "How long to stream: until_call_end (default), timed (N seconds), or full_call.",13 "required": false,14 "enum": ["until_call_end", "timed", "full_call"]15 },16 {17 "name": "duration_sec",18 "type": "number",19 "description": "Seconds to stream (only used when scope is \"timed\").",20 "required": false21 },22 {23 "name": "reason",24 "type": "string",25 "description": "Routing key for the media server (e.g. \"support_ticket\").",26 "required": false27 }28 ],29 "client_fields": {30 "preset_id": "vanira_live_screen",31 "target_fps": 1,32 "max_width": 1280,33 "reason": "screen_capture",34 "prefer_current_tab": true,35 "show_preview": true36 }37}vanira_close_live_screen — Stop Live Screen Share
- *Create tool body** (
POST /tools):
1{2 "name": "close_live_screen",3 "ref_code": "close_live_screen",4 "description": "Call this tool to stop the live screen share and end the screen session.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_close_live_screen"11 }12}vanira_clip_region — Page Region Clip
- *Create tool body** (
POST /tools):
1{2 "name": "clip_page_region",3 "ref_code": "clip_page_region",4 "description": "Call this tool so the user can clip a region of the page and ask a question about it.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "prompt",11 "type": "string",12 "description": "The question about the selected region.",13 "required": true14 },15 {16 "name": "reason",17 "type": "string",18 "description": "Media routing key (e.g. page_clip).",19 "required": false20 }21 ],22 "client_fields": {23 "preset_id": "vanira_clip_region",24 "hint": "Drag to select an area — release to clip.",25 "reason": "page_clip",26 "min_region_px": 2427 }28}vanira_tab_screenshot — Tab Screenshot
- *Create tool body** (
POST /tools):
1{2 "name": "capture_tab_screenshot",3 "ref_code": "capture_tab_screenshot",4 "description": "Capture the visible tab; returns image + elements with center_x/center_y (0–1) and css_selector for screen_ink.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "prompt",11 "type": "string",12 "description": "Optional context for why the screenshot is needed.",13 "required": false14 },15 {16 "name": "reason",17 "type": "string",18 "description": "Media routing key (e.g. tab_screenshot).",19 "required": false20 },21 {22 "name": "max_width",23 "type": "number",24 "description": "Max JPEG width in pixels (default 1280).",25 "required": false26 },27 {28 "name": "max_elements",29 "type": "number",30 "description": "Max UI elements with positions to return (default 80).",31 "required": false32 }33 ],34 "client_fields": {35 "preset_id": "vanira_tab_screenshot",36 "reason": "tab_screenshot",37 "max_width": 1280,38 "max_elements": 8039 }40}vanira_screen_ink — Screen Ink
- *Create tool body** (
POST /tools):
1{2 "name": "screen_ink",3 "ref_code": "screen_ink",4 "description": "Draw freeform on screen. Prefer css_selector for exact placement, or stroke_points from tab screenshot (0–1 viewport coords).",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "strokes",11 "type": "array",12 "description": "Ordered freeform strokes: [{ points: [[0.4,0.4],[0.4,0.2],[0.7,0.4]], close: true }].",13 "required": false14 },15 {16 "name": "points",17 "type": "array",18 "description": "Single-stroke shorthand [[x,y], ...] (0–1 or px).",19 "required": false20 },21 {22 "name": "path_d",23 "type": "string",24 "description": "Single-stroke SVG path d (viewport px) for curves.",25 "required": false26 },27 {28 "name": "css_selector",29 "type": "string",30 "description": "Target element — live DOM lookup for exact polygon/bbox (best accuracy).",31 "required": false32 },33 {34 "name": "close",35 "type": "boolean",36 "description": "Close point path (triangle, rectangle outline, etc.).",37 "required": false38 },39 {40 "name": "animate",41 "type": "boolean",42 "description": "Stroke animation (default true).",43 "required": false44 },45 {46 "name": "interactive",47 "type": "boolean",48 "description": "Let user freehand draw on screen.",49 "required": false50 },51 {52 "name": "color",53 "type": "string",54 "description": "Stroke color (default #f97316).",55 "required": false56 },57 {58 "name": "clear_before",59 "type": "boolean",60 "description": "Clear existing ink first.",61 "required": false62 }63 ],64 "client_fields": {65 "preset_id": "vanira_screen_ink",66 "color": "#f97316"67 }68}vanira_screen_cursor — Screen Cursor
- *Create tool body** (
POST /tools):
1{2 "name": "screen_cursor",3 "ref_code": "screen_cursor",4 "description": "Call this tool to show a cursor at a screen position to guide the user.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "x",11 "type": "number",12 "description": "X position (0–1 normalized or px).",13 "required": false14 },15 {16 "name": "y",17 "type": "number",18 "description": "Y position (0–1 normalized or px).",19 "required": false20 },21 {22 "name": "css_selector",23 "type": "string",24 "description": "Show cursor at center of this element.",25 "required": false26 },27 {28 "name": "label",29 "type": "string",30 "description": "Optional label next to cursor.",31 "required": false32 }33 ],34 "client_fields": {35 "preset_id": "vanira_screen_cursor",36 "color": "#f97316",37 "duration_ms": 250038 }39}vanira_screen_click — Screen Click
- *Create tool body** (
POST /tools):
1{2 "name": "screen_click",3 "ref_code": "screen_click",4 "description": "Call this tool to click at screen coordinates with a visible ripple.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 {10 "name": "x",11 "type": "number",12 "description": "X position (0–1 normalized or px).",13 "required": false14 },15 {16 "name": "y",17 "type": "number",18 "description": "Y position (0–1 normalized or px).",19 "required": false20 },21 {22 "name": "css_selector",23 "type": "string",24 "description": "Click center of this element.",25 "required": false26 },27 {28 "name": "perform_click",29 "type": "boolean",30 "description": "Dispatch click to element at point (default true).",31 "required": false32 }33 ],34 "client_fields": {35 "preset_id": "vanira_screen_click",36 "perform_click": true,37 "show_ripple": true,38 "color": "#f97316"39 }40}vanira_clear_screen_overlay — Clear Screen Overlay
- *Create tool body** (
POST /tools):
1{2 "name": "clear_screen_overlay",3 "ref_code": "clear_screen_overlay",4 "description": "Call this tool to clear all screen annotations when done guiding the user.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_clear_screen_overlay"11 }12}vanira_page_scan — Page Scan
- *Create tool body** (
POST /tools):
1{2 "name": "page_scan",3 "ref_code": "page_scan",4 "description": "Scan visible page DOM. Returns catalog of element ids. Call before point_at.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 { "name": "prompt", "type": "string", "description": "Optional scan context.", "required": false },10 { "name": "max_elements", "type": "number", "description": "Max elements (default 64).", "required": false }11 ],12 "client_fields": {13 "preset_id": "vanira_page_scan",14 "max_elements": 64,15 "include_image": false16 }17}vanira_point_at — Point At
- *Create tool body** (
POST /tools):
1{2 "name": "point_at",3 "ref_code": "point_at",4 "description": "Fly cursor to element_id from page_scan (e.g. e3) with optional label.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 { "name": "element_id", "type": "string", "description": "Id from page_scan.", "required": false },10 { "name": "label", "type": "string", "description": "Cursor label.", "required": false }11 ],12 "client_fields": {13 "preset_id": "vanira_point_at",14 "fly": true,15 "outline": true,16 "color": "#f97316"17 }18}vanira_outline_targets — Outline Targets
- *Create tool body** (
POST /tools):
1{2 "name": "outline_targets",3 "ref_code": "outline_targets",4 "description": "Outline elements by targets: [e1, e3] from page_scan.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [9 { "name": "targets", "type": "string", "description": "JSON array of element ids.", "required": false }10 ],11 "client_fields": {12 "preset_id": "vanira_outline_targets",13 "color": "#f97316",14 "animate": true15 }16}vanira_clear_guide — Clear Guide
- *Create tool body** (
POST /tools):
1{2 "name": "clear_guide",3 "ref_code": "clear_guide",4 "description": "Clear all on-page guide annotations when done.",5 "type": "client",6 "execution_mode": "blocking",7 "channels": ["voice_web", "voice_telephony"],8 "parameters": [],9 "client_fields": {10 "preset_id": "vanira_clear_guide"11 }12}Custom Client Tools
Step 1 — Agent parameters
customer_name(string, required) — "Person's name from the conversation"
Step 2 — Frontend payload
{{param_name}}— substituted with the AI-extracted agent parameter- a static string — always the same value
client_fields in the API and resolves to arguments at runtime.| Payload key | Value |
|---|---|
name | {{customer_name}} |
source | website |
{ "name": "Teja", "source": "website" }Step 3 — Execution mode
| Dashboard label | API value | When to use |
|---|---|---|
| Blocking | blocking | AI should wait (form submit, user confirmation) — call sendToolResult() |
| Async | fire_and_forget | Fire-and-forget UI (popup, toast, map pan) |
Step 4 — Wire in the SDK
VaniraCallBox, handle custom tools in onCustomTool (presets are automatic):1onCustomTool={(call, client) => {2 if (call.name === 'say_hi') {3 showHiPopup();4 if (call.execution_mode !== 'fire_and_forget' && call.tool_call_id) {5 client.sendToolResult(call.tool_call_id, { status: 'success' });6 }7 }8}}POST /tools payload.end_callThe AI will invoke this tool when:
1. It senses the conversation has reached a natural conclusion (e.g., "Goodbye", "Thank you for your help").
2. The user explicitly asks to hang up.
In the API response, it appears with the following properties:
1{2 "name": "end_call",3 "ref_code": "end_call",4 "description": "End the call when the conversation is finished.",5 "type": "client",6 "execution_mode": "fire_and_forget",7 "parameters": []8}Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1const response = await fetch('end_call', {2 method: 'SDK',3 headers: { 'Content-Type': 'application/json' },4 body: JSON.stringify({}),5});6const data = await response.json();https://api.vanira.io/toolsIn voice calls, calling this tool triggers an immediate SIP Transfer to your configured fallback number or the
to_number parameter.Creation Payload
1{2 "name": "human_transfer",3 "ref_code": "human_transfer",4 "description": "Transfers the caller to a live human agent.",5 "type": "server",6 "channels": ["voice_telephony"],7 "parameters": [8 {9 "name": "to_number",10 "type": "string",11 "description": "The destination phone number.",12 "required": true13 }14 ],15 "server": {16 "url": "https://api.vanira.io/webhook/human-transfer",17 "method": "POST"18 },19 "request": {20 "body": { "to_number": "919182517283" },21 "headers": {},22 "query": {}23 }24}Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X POST 'https://api.vanira.io/tools' \2 -H "Content-Type: application/json"https://api.vanira.io/toolsTransferring a user from a "Lead Qualification" agent to a "Support" agent once their identity is verified.
Creation Payload
1{2 "name": "agent_transfer",3 "ref_code": "agent_transfer",4 "description": "Transfers the call to another AI agent configuration.",5 "type": "server",6 "channels": ["voice_web", "voice_telephony"],7 "parameters": [8 {9 "name": "agent_id",10 "type": "string",11 "description": "UUID of the target agent.",12 "required": true13 }14 ],15 "server": {16 "url": "https://api.vanira.io/webhook/agent-transfer",17 "method": "POST"18 },19 "request": {20 "body": { "agent_id": "dcf2b11c-81c2-4619-8483-580c8e25cb23" },21 "headers": {},22 "query": {}23 }24}Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X POST 'https://api.vanira.io/tools' \2 -H "Content-Type: application/json"https://api.vanira.io/toolsRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Implementation Example
1curl -X GET 'https://api.vanira.io/tools'Expected Response — 200 OK
1{2 "tools": [3 {4 "id": "e2705199-...",5 "name": "show_location_map",6 "description": "Show an interactive map for a location the user asks about.",7 "ref_code": "show_location_map",8 "type": "client",9 "execution_mode": "fire_and_forget",10 "channels": ["voice_web"],11 "parameters": [12 { "name": "location_query", "type": "string", "description": "City or landmark", "required": true }13 ],14 "client_fields": { "query": "{{location_query}}" }15 },16 {17 "id": "a1b2c3d4-...",18 "name": "check_order_status",19 "description": "Check the status of a customer order.",20 "ref_code": "check_order_status",21 "type": "server",22 "execution_mode": "fire_and_forget",23 "channels": ["voice_web", "voice_telephony"],24 "parameters": [25 { "name": "order_id", "type": "string", "description": "Order ID", "required": true }26 ],27 "server": { "url": "https://api.acme.com/orders", "method": "POST" },28 "request": {29 "body": { "order_id": "{{order_id}}", "source": "vanira" },30 "headers": { "X-API-Key": "sk-abc123" },31 "query": {}32 }33 }34 ],35 "total": 236}Response Schema Details
idREQUIREDTool UUID.
nameREQUIREDTool name — used as the function name the AI calls.
descriptionREQUIREDWhat the tool does — AI uses this to decide when to call it.
typeREQUIRED"server" | "client".
execution_modeREQUIRED"blocking" | "fire_and_forget". For client tools only.
channelsREQUIREDWhich channels this tool is active on.
parametersREQUIREDParameter schema — what the AI extracts from the conversation.
server{ url, method } — present for server tools only.
request{ body, headers, query } with {{param}} notation.
client_fieldsFields sent to the client-side action with {{param}} notation.
HTTP Errors
UNAUTHORIZEDNo valid API key.
https://api.vanira.io/tools/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDThe unique ID of the tool.
Implementation Example
1curl -X GET 'https://api.vanira.io/tools/e2705199-b431-4091-ad7c-ca1110b8e025'Expected Response — 200 OK
1{2 "id": "e2705199-...",3 "name": "check_order_status",4 "description": "Check the status of a customer order.",5 "ref_code": "check_order_status",6 "type": "server",7 "execution_mode": "blocking",8 "channels": ["voice_web", "voice_telephony"],9 "parameters": [10 { "name": "order_id", "type": "string", "description": "Order ID", "required": true }11 ],12 "server": { "url": "https://api.acme.com/orders", "method": "POST" },13 "request": {14 "body": { "order_id": "{{order_id}}", "source": "vanira" },15 "headers": { "X-API-Key": "sk-abc123" }16 }17}HTTP Errors
UNAUTHORIZEDNo valid API key.
TOOL_NOT_FOUNDTool not found or not owned by the authenticated client.
https://api.vanira.io/toolsPOST /assistant/{id}/tools.- *Server tools** — describe what the AI extracts (
parameters) and map to your webhook (request.body,headers,query). Use{{param_name}}for dynamic values, plain strings for static.
- *Client tools — custom** — use two layers:
parameters — agent parameters (what the AI collects from chat)- *Client tools — two kinds:**
- Preset — see Preset Tools for every
preset_idand copy-pastePOST /toolsbody - Custom — see Custom Client Tools for agent parameters + frontend payload mapping
client_fields is omitted for a custom client tool, each parameter auto-maps to the same key in arguments.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Body Parameters
nameREQUIREDTool name — becomes the function name the AI calls.
descriptionREQUIREDWhat the tool does. The AI reads this to decide when to call it.
ref_codeOptional reference code (slug). If omitted, one is generated from the name.
typeREQUIRED"server" — HTTP webhook. "client" — UI action in the browser.
execution_mode"blocking" = AI waits for result. "fire_and_forget" = AI continues. Default: blocking for server, fire_and_forget for client.
channelsvoice_web | voice_telephony | chat | whatsapp. Defaults to [voice_web, voice_telephony].
parametersWhat the AI extracts from the conversation. Each item: { name, type, description, required, enum? }.
serverRequired when type is "server". { url, method: POST|GET|PUT|DELETE }
requestHTTP fields. If omitted, parameters auto-map to body by name. Use {{param}} for dynamic values.
client_fieldsFrontend payload for client tools. Use {{param}} for agent values or static strings. Presets use preset_id and preset config keys.
Implementation Example
1curl -X POST 'https://api.vanira.io/tools' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "check_order_status",5 "description": "Check the status of a customer order by order ID",6 "ref_code": "check_order_status",7 "type": "server",8 "execution_mode": "blocking",9 "channels": [10 "voice_web",11 "voice_telephony"12 ],13 "parameters": [14 {15 "name": "order_id",16 "type": "string",17 "description": "Order ID to check",18 "required": true19 }20 ],21 "server": {22 "url": "https://api.acme.com/orders",23 "method": "POST"24 },25 "request": {26 "body": {27 "order_id": "{{order_id}}",28 "source": "vanira"29 },30 "headers": {31 "X-API-Key": "sk-abc"32 },33 "query": {}34 },35 "client_fields": {36 "name": "{{customer_name}}",37 "source": "website"38 }39}'Expected Response — 200 OK
1// Server tool example2{3 "name": "check_order_status",4 "description": "Check the status of a customer order",5 "ref_code": "check_order_status",6 "type": "server",7 "execution_mode": "blocking",8 "channels": ["voice_web", "voice_telephony"],9 "server": { "url": "https://api.acme.com/orders", "method": "POST" },10 "parameters": [11 {12 "name": "order_id",13 "type": "string",14 "description": "The order ID the customer mentioned",15 "required": true16 }17 ],18 "request": {19 "body": { "order_id": "{{order_id}}", "source": "vanira" },20 "headers": { "X-API-Key": "sk-your-key" },21 "query": {}22 }23}24 25// Client tool example26{27 "name": "show_location_map",28 "description": "Show an interactive map to the user for a location they asked about",29 "ref_code": "show_location_map",30 "type": "client",31 "execution_mode": "fire_and_forget",32 "channels": ["voice_web"],33 "parameters": [34 {35 "name": "location",36 "type": "string",37 "description": "The city or landmark to show on the map",38 "required": true39 }40 ],41 "client_fields": { "query": "{{location}}", "zoom": 12 }42}43 44// Custom client tool — agent params + frontend payload mapping45{46 "name": "say_hi",47 "description": "Show a greeting popup when the user says hello",48 "ref_code": "say_hi",49 "type": "client",50 "execution_mode": "fire_and_forget",51 "channels": ["voice_web"],52 "parameters": [],53 "client_fields": {}54}55 56// Custom client tool with mapped payload57{58 "name": "greet_user",59 "description": "Show a personalized greeting popup",60 "ref_code": "greet_user",61 "type": "client",62 "execution_mode": "blocking",63 "channels": ["voice_web"],64 "parameters": [65 {66 "name": "customer_name",67 "type": "string",68 "description": "The person's name from the conversation",69 "required": true70 }71 ],72 "client_fields": {73 "name": "{{customer_name}}",74 "source": "website"75 }76}HTTP Errors
UNAUTHORIZEDNo valid API key.
VALIDATION_ERRORMissing required fields, or server.url not provided for type="server".
https://api.vanira.io/tools/:idrequest fields, the full body/headers/query object is replaced. Parameters are preserved from the existing tool unless explicitly re-sent.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the tool to update.
Body Parameters
nameNew tool name.
descriptionUpdated description.
ref_codeUpdated reference code (slug).
serverUpdated server config { url, method }.
requestUpdated request body/headers/query mapping. {{param}} notation supported.
client_fieldsUpdated client-side fields.
channelsUpdated channel list.
parametersUpdated parameters list. Replaces existing ones.
Implementation Example
1curl -X PATCH 'https://api.vanira.io/tools/e2705199-b431-4091-ad7c-ca1110b8e025' \2 -H "Content-Type: application/json" \3 -d '{4 "name": "<name>",5 "description": "<description>",6 "ref_code": "<ref_code>",7 "server": "<server>",8 "request": "<request>",9 "client_fields": "<client_fields>",10 "channels": "<channels>",11 "parameters": [12 {13 "name": "order_id",14 "type": "string",15 "description": "Order ID",16 "required": true17 }18 ]19}'HTTP Errors
UNAUTHORIZEDNo valid API key.
TOOL_NOT_FOUNDTool not found or not owned by the authenticated client.
https://api.vanira.io/tools/:idRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDUUID of the tool to delete.
Implementation Example
1curl -X DELETE 'https://api.vanira.io/tools/e2705199-b431-4091-ad7c-ca1110b8e025' \2 -H "Content-Type: application/json"HTTP Errors
TOOL_NOT_FOUNDTool not found or not owned by the authenticated client.
https://api.vanira.io/assistant/:id/toolsRequired Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDAgent UUID.
Implementation Example
1curl -X GET 'https://api.vanira.io/assistant/28c591f1-f17c-4c46-82ac-4054a843007a/tools'Expected Response — 200 OK
1{2 "tools": [3 {4 "id": "7ccfd8ea-...",5 "tool_id": "e2705199-...",6 "is_active": true,7 "name": "show_location_map",8 "ref_code": "show_location_map",9 "type": "client",10 "execution_mode": "fire_and_forget",11 "channels": ["voice_web"],12 "parameters": [13 { "name": "location_query", "type": "string", "required": true }14 ],15 "client_fields": { "query": "{{location_query}}" }16 }17 ],18 "total": 119}Response Schema Details
idREQUIREDagent_actions join record ID — use this to detach the tool.
tool_idREQUIREDbase_actions ID — use this to reference the tool definition.
is_activeREQUIREDWhether the tool is active for this agent.
HTTP Errors
UNAUTHORIZEDNo valid API key.
AGENT_NOT_FOUNDAgent not found or not owned by the authenticated client.
https://api.vanira.io/assistant/:id/toolsPOST /tools first.Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDAgent UUID.
Body Parameters
tool_idREQUIREDUUID of the tool to attach (from GET /tools).
Implementation Example
1curl -X POST 'https://api.vanira.io/assistant/28c591f1-f17c-4c46-82ac-4054a843007a/tools' \2 -H "Content-Type: application/json" \3 -d '{4 "tool_id": "e2705199-b431-4091-ad7c-ca1110b8e025"5}'Expected Response — 200 OK
1{2 "id": "7ccfd8ea-8c99-4022-82e3-7c68bdb8d02b",3 "is_active": true4}HTTP Errors
UNAUTHORIZEDNo valid API key.
AGENT_NOT_FOUNDAgent not found or not owned by the authenticated client.
TOOL_NOT_FOUNDTool not found or not owned by the authenticated client.
https://api.vanira.io/assistant/:id/tools/:tool_idid from GET /assistant/{id}/tools (the agent_actions ID, not the tool_id).Required Headers
X-API-KeyREQUIREDYour Sovereign API key. Securely authorizes all requests.
Content-TypeREQUIREDMust be application/json
Path Parameters
idREQUIREDAgent UUID.
tool_idREQUIREDThe agent_actions.id from GET /assistant/{id}/tools — NOT the base tool ID.
Implementation Example
1curl -X DELETE 'https://api.vanira.io/assistant/28c591f1-f17c-4c46-82ac-4054a843007a/tools/7ccfd8ea-8c99-4022-82e3-7c68bdb8d02b' \2 -H "Content-Type: application/json"HTTP Errors
UNAUTHORIZEDNo valid API key.
AGENT_NOT_FOUNDAgent or attachment not found.