|
|
@@ -0,0 +1,331 @@
|
|
|
+# VAPI Integration Documentation
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+ShopCall.ai integrates with VAPI (Voice AI Platform) to receive and store call data from AI-powered phone conversations. This integration allows the system to track call logs, transcripts, recordings, and analytics from VAPI calls.
|
|
|
+
|
|
|
+## Architecture
|
|
|
+
|
|
|
+### Components
|
|
|
+
|
|
|
+1. **VAPI Webhook Endpoint** (`/functions/v1/vapi-webhook`)
|
|
|
+ - Receives POST requests from VAPI
|
|
|
+ - Validates and processes end-of-call reports
|
|
|
+ - Stores call data in the database
|
|
|
+
|
|
|
+2. **Database Schema** (`call_logs` table)
|
|
|
+ - Stores call metadata, transcripts, and analytics
|
|
|
+ - Includes VAPI-specific fields for messages, analysis, and recording URLs
|
|
|
+
|
|
|
+3. **API Endpoint** (`/api/call-logs`)
|
|
|
+ - Retrieves call logs for authenticated users
|
|
|
+ - Transforms data for frontend display
|
|
|
+
|
|
|
+4. **WebUI** (`/call-logs` page)
|
|
|
+ - Displays call logs in a table format
|
|
|
+ - Shows detailed call information including transcripts and recordings
|
|
|
+
|
|
|
+## Database Schema
|
|
|
+
|
|
|
+### New Fields in `call_logs` Table
|
|
|
+
|
|
|
+| Field | Type | Description |
|
|
|
+|-------|------|-------------|
|
|
|
+| `vapi_call_id` | TEXT | Unique identifier from VAPI for this call |
|
|
|
+| `messages` | JSONB | Array of conversation messages (bot/user/system/tool_calls) |
|
|
|
+| `analysis` | JSONB | VAPI analysis object (summary, successEvaluation) |
|
|
|
+| `stereo_recording_url` | TEXT | URL to stereo recording from VAPI |
|
|
|
+| `pcap_url` | TEXT | URL to SIP packet capture file |
|
|
|
+| `log_url` | TEXT | URL to VAPI call logs |
|
|
|
+| `vapi_timestamp` | BIGINT | VAPI event timestamp in milliseconds |
|
|
|
+
|
|
|
+### Indexes
|
|
|
+
|
|
|
+- `idx_call_logs_vapi_call_id` - Fast lookups by VAPI call ID
|
|
|
+- `idx_call_logs_vapi_timestamp` - Time-based queries
|
|
|
+
|
|
|
+## VAPI Webhook Configuration
|
|
|
+
|
|
|
+### Webhook URL
|
|
|
+
|
|
|
+```
|
|
|
+https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/vapi-webhook
|
|
|
+```
|
|
|
+
|
|
|
+### Webhook Events
|
|
|
+
|
|
|
+The integration listens for `end-of-call-report` events from VAPI.
|
|
|
+
|
|
|
+### Expected Payload Structure
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "message": {
|
|
|
+ "timestamp": 1763633517714,
|
|
|
+ "type": "end-of-call-report",
|
|
|
+ "analysis": {
|
|
|
+ "summary": "Call summary text",
|
|
|
+ "successEvaluation": "true"
|
|
|
+ },
|
|
|
+ "artifact": {
|
|
|
+ "messages": [
|
|
|
+ {
|
|
|
+ "role": "bot|user|system|tool_calls|tool_call_result",
|
|
|
+ "message": "Message text",
|
|
|
+ "time": 1763633305414,
|
|
|
+ "endTime": 1763633327672,
|
|
|
+ "secondsFromStart": 0.486,
|
|
|
+ "duration": 270
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "transcript": "Full conversation transcript",
|
|
|
+ "recordingUrl": "https://storage.vapi.ai/...",
|
|
|
+ "stereoRecordingUrl": "https://storage.vapi.ai/...",
|
|
|
+ "pcapUrl": "https://storage.vapi.ai/...",
|
|
|
+ "logUrl": "https://calllogs.vapi.ai/..."
|
|
|
+ },
|
|
|
+ "call": {
|
|
|
+ "id": "unique-call-id",
|
|
|
+ "assistantId": "assistant-id",
|
|
|
+ "phoneNumberId": "phone-number-id",
|
|
|
+ "customerId": "customer-phone-number",
|
|
|
+ "costBreakdown": {
|
|
|
+ "stt": 0.0012,
|
|
|
+ "llm": 0.0034,
|
|
|
+ "tts": 0.0023,
|
|
|
+ "twilio": 0.0050,
|
|
|
+ "total": 0.0119
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## Data Mapping
|
|
|
+
|
|
|
+### VAPI → call_logs
|
|
|
+
|
|
|
+| VAPI Field | call_logs Field |
|
|
|
+|------------|-----------------|
|
|
|
+| `message.call.id` | `vapi_call_id` |
|
|
|
+| `message.timestamp` | `vapi_timestamp`, `started_at`, `ended_at` |
|
|
|
+| `message.artifact.messages` | `messages` |
|
|
|
+| `message.analysis` | `analysis` |
|
|
|
+| `message.analysis.summary` | `summary` |
|
|
|
+| `message.artifact.transcript` | `transcript` |
|
|
|
+| `message.artifact.recordingUrl` | `recording_url` |
|
|
|
+| `message.artifact.stereoRecordingUrl` | `stereo_recording_url` |
|
|
|
+| `message.artifact.pcapUrl` | `pcap_url` |
|
|
|
+| `message.artifact.logUrl` | `log_url` |
|
|
|
+| `message.call.assistantId` | `assistant_id` |
|
|
|
+| `message.call.phoneNumberId` | `phone_number_id` |
|
|
|
+| `message.call.customerId` | `customer_number` |
|
|
|
+| `message.call.costBreakdown.*` | `cost_stt`, `cost_llm`, `cost_tts`, `cost_twilio`, `cost_total` |
|
|
|
+
|
|
|
+### Call Outcome Mapping
|
|
|
+
|
|
|
+- `analysis.successEvaluation = "true"` → `call_outcome = "resolved"`
|
|
|
+- `analysis.successEvaluation = "false"` → `call_outcome = "not_interested"`
|
|
|
+- No evaluation → `call_outcome = "pending"`
|
|
|
+
|
|
|
+### Duration Calculation
|
|
|
+
|
|
|
+Duration is calculated from the last message's `secondsFromStart` field.
|
|
|
+
|
|
|
+## WebUI Features
|
|
|
+
|
|
|
+### Call Logs Table
|
|
|
+
|
|
|
+Displays:
|
|
|
+- Call time
|
|
|
+- Customer phone number (masked for privacy)
|
|
|
+- Intent/Summary
|
|
|
+- Outcome (color-coded)
|
|
|
+- Duration
|
|
|
+- Sentiment (based on successEvaluation)
|
|
|
+- Cost
|
|
|
+
|
|
|
+### Call Details Modal
|
|
|
+
|
|
|
+Shows:
|
|
|
+- Full conversation transcript with timestamps
|
|
|
+- Individual messages (customer/assistant)
|
|
|
+- Call summary and success evaluation
|
|
|
+- Recording playback links (mono and stereo)
|
|
|
+- Call analytics and metadata
|
|
|
+- Link to VAPI call logs
|
|
|
+
|
|
|
+## API Endpoints
|
|
|
+
|
|
|
+### POST /functions/v1/vapi-webhook
|
|
|
+
|
|
|
+**Purpose**: Receive VAPI webhooks
|
|
|
+
|
|
|
+**Authentication**: None (service-level endpoint)
|
|
|
+
|
|
|
+**Request Body**: VAPI webhook payload (JSON)
|
|
|
+
|
|
|
+**Response**:
|
|
|
+```json
|
|
|
+{
|
|
|
+ "status": "success",
|
|
|
+ "call_log_id": "uuid",
|
|
|
+ "message": "Call log stored successfully"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### GET /api/call-logs
|
|
|
+
|
|
|
+**Purpose**: Retrieve call logs for authenticated user
|
|
|
+
|
|
|
+**Authentication**: Bearer token (required)
|
|
|
+
|
|
|
+**Response**:
|
|
|
+```json
|
|
|
+{
|
|
|
+ "success": true,
|
|
|
+ "call_logs": [
|
|
|
+ {
|
|
|
+ "id": "uuid",
|
|
|
+ "time": "2025-11-20 10:30:45",
|
|
|
+ "customer": "...xxx-1234",
|
|
|
+ "intent": "Customer inquiry",
|
|
|
+ "outcome": "resolved",
|
|
|
+ "duration": "3:25",
|
|
|
+ "sentiment": "Positive",
|
|
|
+ "cost": "$0.0119",
|
|
|
+ "outcomeColor": "text-green-500",
|
|
|
+ "sentimentColor": "text-green-500",
|
|
|
+ "fullData": { /* complete call log object */ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## Security
|
|
|
+
|
|
|
+### Webhook Security
|
|
|
+
|
|
|
+Currently, the webhook endpoint accepts all POST requests. For production, consider:
|
|
|
+
|
|
|
+1. **VAPI Signature Verification**: Validate VAPI webhook signatures
|
|
|
+2. **IP Allowlisting**: Restrict to VAPI IP addresses
|
|
|
+3. **Rate Limiting**: Prevent abuse
|
|
|
+
|
|
|
+### Data Privacy
|
|
|
+
|
|
|
+- Customer phone numbers are masked in the UI (`...xxx-1234`)
|
|
|
+- Full phone numbers stored in database for analytics
|
|
|
+- Call recordings stored externally (VAPI)
|
|
|
+- Transcripts contain PII - handle according to GDPR
|
|
|
+
|
|
|
+## Deployment
|
|
|
+
|
|
|
+### Database Migration
|
|
|
+
|
|
|
+```bash
|
|
|
+# Migration is already applied
|
|
|
+# File: /supabase/migrations/20251120_vapi_integration.sql
|
|
|
+```
|
|
|
+
|
|
|
+### Edge Functions
|
|
|
+
|
|
|
+```bash
|
|
|
+# Deploy VAPI webhook handler
|
|
|
+supabase functions deploy vapi-webhook --project-ref ztklqodcdjeqpsvhlpud
|
|
|
+
|
|
|
+# Deploy updated API endpoint
|
|
|
+supabase functions deploy api --project-ref ztklqodcdjeqpsvhlpud
|
|
|
+```
|
|
|
+
|
|
|
+### Environment Variables
|
|
|
+
|
|
|
+Required in Supabase Edge Functions:
|
|
|
+- `SUPABASE_URL` - Supabase project URL
|
|
|
+- `SUPABASE_SERVICE_ROLE_KEY` - Service role key for database access
|
|
|
+
|
|
|
+## Testing
|
|
|
+
|
|
|
+### Manual Testing
|
|
|
+
|
|
|
+1. **Test Webhook Endpoint**:
|
|
|
+```bash
|
|
|
+curl -X POST https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/vapi-webhook \
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
+ -d @test-payload.json
|
|
|
+```
|
|
|
+
|
|
|
+2. **Test API Endpoint**:
|
|
|
+```bash
|
|
|
+curl https://ztklqodcdjeqpsvhlpud.supabase.co/functions/v1/api/call-logs \
|
|
|
+ -H "Authorization: Bearer YOUR_TOKEN"
|
|
|
+```
|
|
|
+
|
|
|
+3. **Test WebUI**:
|
|
|
+ - Navigate to `/call-logs`
|
|
|
+ - Verify calls are displayed
|
|
|
+ - Click "Details" to view full call information
|
|
|
+
|
|
|
+### Sample Test Payload
|
|
|
+
|
|
|
+See `message` object in the VAPI webhook payload example above.
|
|
|
+
|
|
|
+## Troubleshooting
|
|
|
+
|
|
|
+### Common Issues
|
|
|
+
|
|
|
+1. **Webhook not receiving data**
|
|
|
+ - Verify VAPI webhook URL configuration
|
|
|
+ - Check Supabase Edge Function logs
|
|
|
+ - Ensure `end-of-call-report` event is enabled
|
|
|
+
|
|
|
+2. **Call logs not appearing in UI**
|
|
|
+ - Check browser console for errors
|
|
|
+ - Verify API endpoint returns data
|
|
|
+ - Ensure user authentication is valid
|
|
|
+
|
|
|
+3. **Missing transcript or messages**
|
|
|
+ - Check VAPI payload structure
|
|
|
+ - Verify `artifact.messages` array exists
|
|
|
+ - Confirm transcript generation in VAPI
|
|
|
+
|
|
|
+### Logs
|
|
|
+
|
|
|
+View Edge Function logs:
|
|
|
+```bash
|
|
|
+# Via Supabase Dashboard
|
|
|
+https://supabase.com/dashboard/project/ztklqodcdjeqpsvhlpud/functions
|
|
|
+
|
|
|
+# Via CLI
|
|
|
+supabase functions logs vapi-webhook
|
|
|
+```
|
|
|
+
|
|
|
+## Future Enhancements
|
|
|
+
|
|
|
+### Planned Features
|
|
|
+
|
|
|
+1. **Real-time Updates**: WebSocket integration for live call updates
|
|
|
+2. **Search and Filtering**: Advanced search by customer, outcome, date range
|
|
|
+3. **Analytics Dashboard**: Call statistics, sentiment analysis, trends
|
|
|
+4. **Export Functionality**: CSV/PDF export of call logs
|
|
|
+5. **Webhook Signature Verification**: Enhanced security
|
|
|
+6. **User Assignment**: Link calls to specific user_id
|
|
|
+7. **Call Tagging**: Custom tags for call categorization
|
|
|
+
|
|
|
+### Optional Improvements
|
|
|
+
|
|
|
+1. **Audio Playback**: In-browser audio player for recordings
|
|
|
+2. **Sentiment Analysis**: AI-powered sentiment detection
|
|
|
+3. **Call Scoring**: Automated quality scoring
|
|
|
+4. **Integration with CRM**: Sync call data to external systems
|
|
|
+5. **Notification System**: Alerts for important calls
|
|
|
+
|
|
|
+## Related Issues
|
|
|
+
|
|
|
+- Issue #104: Initial VAPI integration implementation
|
|
|
+
|
|
|
+## References
|
|
|
+
|
|
|
+- [VAPI Documentation](https://vapi.ai/docs)
|
|
|
+- [Supabase Edge Functions](https://supabase.com/docs/guides/functions)
|
|
|
+- [Supabase Database](https://supabase.com/docs/guides/database)
|