diff --git a/docs/integrations/telephony/twilio.mdx b/docs/integrations/telephony/twilio.mdx
index f6926bb..de08448 100644
--- a/docs/integrations/telephony/twilio.mdx
+++ b/docs/integrations/telephony/twilio.mdx
@@ -39,37 +39,14 @@ Watch this step-by-step guide to set up Twilio with Dograh AI:
### Step 2: Configure in Dograh AI
-
-
- 1. Navigate to **Settings** → **Integrations** → **Telephony**
- 2. Select **Twilio** as your provider
- 3. Enter your credentials:
- - Account SID
- - Auth Token
- - Phone Numbers (comma-separated if multiple)
- 4. Click **Test Connection**
- 5. Save configuration
-
-
-
- Add these variables to your `.env` file:
-
- ```bash
- # Telephony Configuration
- TELEPHONY_PROVIDER=twilio # Specifies Twilio as the telephony provider
- TWILIO_ACCOUNT_SID="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- TWILIO_AUTH_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- TWILIO_FROM_NUMBER="+1234567890"
- # For multiple numbers, use comma separation:
- # TWILIO_FROM_NUMBER="+1234567890,+0987654321"
- ```
-
- Restart your Dograh AI services:
- ```bash
- docker-compose restart api
- ```
-
-
+1. Navigate to **Settings** → **Integrations** → **Telephony**
+2. Select **Twilio** as your provider
+3. Enter your credentials:
+ - Account SID
+ - Auth Token
+ - Phone Numbers (comma-separated if multiple)
+4. Click **Test Connection**
+5. Save configuration
### Step 3: Test Your Configuration
@@ -122,6 +99,6 @@ When using Twilio with campaigns:
## Best Practices
-- Store credentials securely in environment variables (OSS) or database (SaaS)
+- Store credentials securely in the database
- Test your configuration with a single call before running campaigns
- Monitor Twilio Console for usage and billing
\ No newline at end of file
diff --git a/docs/integrations/telephony/vonage.mdx b/docs/integrations/telephony/vonage.mdx
new file mode 100644
index 0000000..80f0db7
--- /dev/null
+++ b/docs/integrations/telephony/vonage.mdx
@@ -0,0 +1,202 @@
+---
+title: "Vonage Integration"
+description: "Configure Vonage (Nexmo) for voice communication in Dograh AI"
+---
+
+## Overview
+
+Vonage (formerly Nexmo) is a cloud communications platform that provides global voice, messaging, and video capabilities. Dograh AI's Vonage integration enables high-quality voice interactions with your agents using Vonage's robust infrastructure.
+
+## Prerequisites
+
+Before setting up Vonage integration, you'll need:
+
+- A [Vonage account](https://www.vonage.com/communications-apis/)
+- Vonage Application with Voice capability enabled
+- Application ID and Private Key from your Vonage Dashboard
+- At least one Vonage phone number
+- Dograh AI instance running and accessible
+
+## Configuration
+
+### Step 1: Create Vonage Application
+
+1. Log in to your [Vonage Dashboard](https://dashboard.nexmo.com/)
+2. Navigate to **Applications** → **Create a new application**
+3. Enable **Voice** capability
+4. Generate a private key (save this securely - you'll need it)
+5. Note your **Application ID**
+
+### Step 2: Get API Credentials
+
+1. Find your **API Key** and **API Secret** in the dashboard
+2. Navigate to **Numbers** → **Your Numbers**
+3. Copy your phone number(s)
+4. Link your numbers to your application
+
+### Step 3: Configure in Dograh AI
+
+1. Navigate to **Settings** → **Integrations** → **Telephony**
+2. Select **Vonage** as your provider
+3. Enter your credentials:
+ - Application ID
+ - Private Key (entire key including BEGIN/END lines)
+ - API Key
+ - API Secret
+ - Phone Numbers (comma-separated if multiple)
+4. Click **Test Connection**
+5. Save configuration
+
+### Step 4: Test Your Configuration
+
+1. Create a test workflow
+2. Click "Test Call" to verify connection
+3. Check call logs for successful connection
+
+## How It Works
+
+### Technical Details
+
+Vonage integration differs from other providers in key ways:
+
+- **Audio Format**: Uses 16kHz Linear PCM (vs Twilio's 8kHz μ-law)
+- **Protocol**: NCCO (Nexmo Call Control Objects) instead of TwiML
+- **Authentication**: JWT-based authentication using private keys
+- **WebSocket**: Binary audio frames instead of base64-encoded
+
+### Call Flow
+
+1. Dograh AI generates a JWT token using your private key
+2. Call is initiated via Vonage Voice API
+3. Vonage requests NCCO instructions at the webhook URL
+4. Dograh returns WebSocket connection details
+5. Audio streams as 16kHz PCM over WebSocket
+6. Real-time voice interaction occurs with your agent
+
+### NCCO Response Example
+
+```json
+[
+ {
+ "action": "connect",
+ "endpoint": [{
+ "type": "websocket",
+ "uri": "wss://your-domain/api/v1/telephony/ws/123/456/789",
+ "content-type": "audio/l16;rate=16000",
+ "headers": {}
+ }]
+ }
+]
+```
+
+## Campaign Features
+
+When using Vonage with campaigns:
+- **Global Reach**: Excellent international call quality and coverage
+- **Number Pool Management**: Automatic rotation of configured numbers
+- **Call Analytics**: Detailed metrics via Vonage Dashboard
+- **Cost Tracking**: Per-call cost calculation for billing
+
+## Audio Quality Optimization
+
+Vonage uses higher quality audio (16kHz) which provides:
+- Clearer voice reproduction
+- Better speech recognition accuracy
+- More natural-sounding TTS output
+- Reduced transcription errors
+
+## Troubleshooting
+
+
+
+ - Ensure "Voice" is enabled in your Vonage application
+ - Verify the application ID matches your configuration
+ - Check that your phone numbers are linked to the application
+
+
+
+ - Verify your private key is complete (including BEGIN/END lines)
+ - Check the Application ID is correct
+ - Ensure the private key hasn't been regenerated in Vonage Dashboard
+
+
+
+ - Remove the '+' prefix for Vonage (use `1234567890` not `+1234567890`)
+ - Ensure numbers are in E.164 format without the '+'
+ - Verify numbers are active in your Vonage account
+
+
+
+ - Verify WebSocket connection is established
+ - Check audio pipeline is configured for 16kHz PCM
+ - Monitor WebSocket for binary audio frames
+ - Review VAD (Voice Activity Detection) settings
+
+
+
+ - Check WebSocket heartbeat/ping-pong frames
+ - Verify no timeout in load balancer/proxy
+ - Monitor for audio pipeline errors
+ - Review max call duration settings
+
+
+
+## Best Practices
+
+- **Security**: Private keys are stored securely in the database
+- **Testing**: Use Vonage Voice Inspector for debugging call issues
+- **Numbers**: Configure multiple numbers for redundancy
+- **Monitoring**: Set up alerts in Vonage Dashboard for failures
+- **Cost Management**: Monitor usage to control costs
+
+## Cost Considerations
+
+Vonage pricing includes:
+- Per-minute charges for calls
+- Phone number rental fees
+- Optional features (recording, transcription)
+
+Check [Vonage pricing](https://www.vonage.com/communications-apis/voice/pricing/) for current rates.
+
+## Advanced Configuration
+
+### Custom Headers
+
+Add custom headers to WebSocket connections:
+
+```python
+# In your webhook response
+"headers": {
+ "X-Custom-Header": "value",
+ "Authorization": "Bearer token"
+}
+```
+
+### Call Recording
+
+Enable call recording via NCCO:
+
+```json
+{
+ "action": "record",
+ "eventUrl": ["https://your-domain/recording-webhook"],
+ "format": "mp3"
+}
+```
+
+## API Differences from Twilio
+
+| Feature | Twilio | Vonage |
+|---------|---------|---------|
+| Audio Format | 8kHz μ-law | 16kHz Linear PCM |
+| Control Format | TwiML (XML) | NCCO (JSON) |
+| Authentication | Basic Auth | JWT |
+| WebSocket Data | Base64 text | Binary frames |
+| Phone Format | With '+' | Without '+' |
+
+## Next Steps
+
+- Test your Vonage integration with a simple workflow
+- Configure VAD settings for optimal voice detection
+- Set up monitoring and alerts
+- Explore advanced features like call recording
\ No newline at end of file
diff --git a/docs/integrations/telephony/webhooks.mdx b/docs/integrations/telephony/webhooks.mdx
index 78e2ec9..f20c740 100644
--- a/docs/integrations/telephony/webhooks.mdx
+++ b/docs/integrations/telephony/webhooks.mdx
@@ -13,19 +13,36 @@ Dograh AI uses webhooks to communicate with telephony providers for call events
When a call is initiated, the telephony provider requests instructions.
-**Endpoint**: `/api/v1/telephony/twiml`
+**Endpoint**: `/api/v1/telephony/webhook/{workflow_id}/{user_id}/{workflow_run_id}`
-**Purpose**: Returns provider-specific instructions (TwiML for Twilio)
+**Purpose**: Returns provider-specific instructions
-**Example Response**:
-```xml
-
-
-
-
-
-
-```
+
+
+ ```xml
+
+
+
+
+
+
+ ```
+
+
+ ```json
+ [
+ {
+ "action": "connect",
+ "endpoint": [{
+ "type": "websocket",
+ "uri": "wss://your-domain/api/v1/telephony/ws/123/456/789",
+ "content-type": "audio/l16;rate=16000"
+ }]
+ }
+ ]
+ ```
+
+
### 2. Status Callback
@@ -48,14 +65,21 @@ Real-time audio streaming for voice interaction.
**Endpoint**: `/api/v1/telephony/ws/{workflow_id}/{user_id}/{workflow_run_id}`
+**Audio Formats**:
+- **Twilio**: 8kHz μ-law (MULAW), Base64-encoded in JSON messages
+- **Vonage**: 16kHz Linear PCM, Binary frames
+
## How It Works
Dograh AI automatically:
1. Constructs webhook URLs based on your deployment
2. Passes them to the telephony provider when initiating calls
-3. Verifies webhook signatures for security
+3. Verifies webhook signatures for security:
+ - **Twilio**: HMAC-SHA1 signature validation
+ - **Vonage**: JWT token verification
4. Processes status updates to track call lifecycle
5. Manages WebSocket connections for audio streaming
+6. Handles provider-specific audio formats and protocols
## Local Development
diff --git a/pipecat b/pipecat
index f88c8a0..278248a 160000
--- a/pipecat
+++ b/pipecat
@@ -1 +1 @@
-Subproject commit f88c8a00de00beb93429c86d6353dc2673b6eb77
+Subproject commit 278248a40cf7a8cb11d32534016ffec099408f8c
diff --git a/ui/src/app/configure-telephony/page.tsx b/ui/src/app/configure-telephony/page.tsx
index 7ab3b39..830bc4e 100644
--- a/ui/src/app/configure-telephony/page.tsx
+++ b/ui/src/app/configure-telephony/page.tsx
@@ -28,8 +28,15 @@ import { useAuth } from "@/lib/auth";
// TODO: Make UI provider-agnostic
interface TelephonyConfigForm {
provider: string;
- account_sid: string;
- auth_token: string;
+ // Twilio fields
+ account_sid?: string;
+ auth_token?: string;
+ // Vonage fields
+ application_id?: string;
+ private_key?: string;
+ api_key?: string;
+ api_secret?: string;
+ // Common field
from_number: string;
}
@@ -71,13 +78,26 @@ export default function ConfigureTelephonyPage() {
headers: { Authorization: `Bearer ${accessToken}` },
});
- if (!response.error && response.data?.twilio) {
- setHasExistingConfig(true);
- // Masked values like "****************def0" from backend
- setValue("account_sid", response.data.twilio.account_sid);
- setValue("auth_token", response.data.twilio.auth_token);
- if (response.data.twilio.from_numbers?.length > 0) {
- setValue("from_number", response.data.twilio.from_numbers[0]);
+ if (!response.error) {
+ // Simple single provider config
+ if (response.data?.twilio) {
+ setHasExistingConfig(true);
+ setValue("provider", "twilio");
+ setValue("account_sid", response.data.twilio.account_sid);
+ setValue("auth_token", response.data.twilio.auth_token);
+ if (response.data.twilio.from_numbers?.length > 0) {
+ setValue("from_number", response.data.twilio.from_numbers[0]);
+ }
+ } else if (response.data?.vonage) {
+ setHasExistingConfig(true);
+ setValue("provider", "vonage");
+ setValue("application_id", response.data.vonage.application_id);
+ setValue("private_key", response.data.vonage.private_key);
+ setValue("api_key", response.data.vonage.api_key || "");
+ setValue("api_secret", response.data.vonage.api_secret || "");
+ if (response.data.vonage.from_numbers?.length > 0) {
+ setValue("from_number", response.data.vonage.from_numbers[0]);
+ }
}
}
} catch (error) {
@@ -93,14 +113,26 @@ export default function ConfigureTelephonyPage() {
try {
const accessToken = await getAccessToken();
+
+ // Build the request body based on provider
+ let requestBody: any = {
+ provider: data.provider,
+ from_numbers: [data.from_number],
+ };
+
+ if (data.provider === "twilio") {
+ requestBody.account_sid = data.account_sid;
+ requestBody.auth_token = data.auth_token;
+ } else if (data.provider === "vonage") {
+ requestBody.application_id = data.application_id;
+ requestBody.private_key = data.private_key;
+ requestBody.api_key = data.api_key;
+ requestBody.api_secret = data.api_secret;
+ }
+
const response = await saveTelephonyConfigurationApiV1OrganizationsTelephonyConfigPost({
headers: { Authorization: `Bearer ${accessToken}` },
- body: {
- provider: data.provider,
- account_sid: data.account_sid,
- auth_token: data.auth_token,
- from_numbers: [data.from_number],
- },
+ body: requestBody,
});
if (response.error) {
@@ -178,8 +210,14 @@ export default function ConfigureTelephonyPage() {
Twilio
+ Vonage
+ {hasExistingConfig && (
+
+ ⚠️ Switching providers will require entering new credentials
+
+ )}
{/* Twilio-specific fields */}
@@ -250,6 +288,87 @@ export default function ConfigureTelephonyPage() {
>
)}
+ {/* Vonage-specific fields */}
+ {selectedProvider === "vonage" && (
+ <>
+
+
+
+ {errors.application_id && (
+
+ {errors.application_id.message}
+
+ )}
+
+
+
+
+
+ {errors.private_key && (
+
+ {errors.private_key.message}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {errors.from_number && (
+
+ {errors.from_number.message}
+
+ )}
+
+ >
+ )}
+