Overview
Moda tracks your Vapi voice AI calls by processing end-of-call report webhooks. Each call is captured with full detail, including conversation turns, tool calls, squad transfers, call analysis, and cost breakdowns.Setup
Usage
Point your Vapi webhook URL to your server and pass the payload to Moda:Supported Features
| Feature | Captured |
|---|---|
| Conversation turns | Yes |
| Tool calls | Yes |
| Squad transfers | Yes |
| Call analysis / summary | Yes |
| Structured data | Yes |
| Cost breakdown | Yes |
| Turn latency metrics | Yes |
| Recording URLs | Yes |
Configuration
UseProcessVapiOptions to customize the conversation and user identifiers:
conversationId defaults to call.id and userId defaults to call.customer.number.
What Moda Captures
For each Vapi call, Moda captures a structured hierarchy of data:Call-Level Data
| Field | Description |
|---|---|
| Conversation ID | Call ID or your custom conversation ID |
| User ID | Customer number or your custom user ID |
| Duration | Call duration in seconds |
| Total cost | Total call cost |
| Ended reason | Reason the call ended |
| Assistant ID | Vapi assistant identifier |
| Status | Call status (e.g., “ended”) |
| Start / end time | Timestamps for the call |
| Summary | AI-generated call summary |
| Structured data | Custom structured data from Vapi |
| Success evaluation | Success evaluation result |
| Cost breakdown | Separate costs for LLM, speech-to-text, and text-to-speech |
Turn-Level Data
| Field | Description |
|---|---|
| User message | What the caller said |
| Assistant response | What the assistant replied |
| Model latency | Time for the LLM to respond (ms) |
| Voice latency | Time for voice synthesis (ms) |
| Total latency | End-to-end turn latency (ms) |
Troubleshooting
No data appearing?- Ensure
Moda.init()is called before processing webhooks - Call
Moda.flush()before your process exits to ensure all data is sent - Verify your Vapi webhook is configured to send
end-of-call-reportevents
- Moda handles both the
message-wrapped format (real Vapi webhooks) and the legacy flat format - If you see a call with no turns, check that your payload contains conversation data in
call.artifact.messagesor atranscriptarray
- Vapi uses
[{role, message}]format for transcripts. Moda automatically normalizes this for display.
For full SDK documentation, see the Python SDK or Node.js SDK guides.