Session Data & Metrics APIs
Access comprehensive data about your VoiceRun agents including conversation sessions, recordings, transcripts, and analytics. Retrieve session metadata, download audio recordings, export transcripts, and analyze performance metrics including conversion rates, session handling, and customer interactions.
Authentication
To use the Session Data API, you'll need an API key. You can generate one from your account settings page here.
Base URL
All session data endpoints are accessed through the following base URL:
https://api.primvoices.com/v1/agents/{agentId}/sessionsList Sessions
Retrieve a list of sessions for your agent. The following query parameters are available for filtering and pagination:
| Parameter | Type | Description |
|---|---|---|
| filters[agentId] | string | Filter sessions by agent ID |
| filters[agentEnvironmentId] | string | Filter sessions by environment ID |
| filters[status] | string | Filter by session status (e.g., "completed", "in_progress") |
| filters[createdAt][$gte] | string | Filter sessions created after this date (ISO 8601 format) |
| filters[createdAt][$lte] | string | Filter sessions created before this date (ISO 8601 format) |
| page | number | Page number for pagination (default: 1) |
| limit | number | Number of results per page (default: 100, max: 1000) |
Example Usage
Here's an example of how to fetch session data using Python:
import requests
base_url = "https://api.primvoices.com/v1/agents/{agent_id}/sessions"
headers = {
"Authorization": f"Bearer {api_key}"
}
query_params = {
"filters[agentId]": "{agent_id}",
"filters[agentEnvironmentId]": "{agent_environment_id}",
"filters[status]": "completed",
"filters[createdAt][$gte]": "2024-05-07T00:00:00.000Z",
"filters[createdAt][$lte]": "2024-05-08T00:00:00.000Z",
"page": 1,
"limit": 100
}
response = requests.get(base_url, headers=headers, params=query_params)
sessions = response.json()Response Format
The API response includes pagination metadata and an array of session objects:
{
"data": [
{
"id": "string",
"agentId": "string",
"agentEnvironmentId": "string",
"status": "string",
"createdAt": "string",
"updatedAt": "string",
"events": [
{
"name": "string",
"data": object,
}
]
}
],
"meta": {
"page": number,
"limit": number,
"total": number,
}
}Best Practices
- Use appropriate date ranges to limit the number of results
- Implement pagination to handle large result sets
- Cache frequently accessed session data
- Use specific filters to narrow down results
- Handle rate limits appropriately
Get Recording
Retrieve the audio recording file for a specific session. The recording format depends on the session type:
- Telephony sessions: Returns audio/mp3 file (binary stream)
- Web sessions: Returns audio/wav file (binary stream) or JSON object with URL
GET /v1/agents/{agentId}/sessions/{sessionId}/recordingPath Parameters
| Parameter | Type | Description |
|---|---|---|
| agentId | string | The ID of the agent |
| sessionId | string | The ID of the session |
Example Usage
import requests
agent_id = "agent-123"
session_id = "session-456"
api_key = "your-api-key"
url = f"https://api.primvoices.com/v1/agents/{agent_id}/sessions/{session_id}/recording"
headers = {
"Authorization": f"Bearer {api_key}"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
# Check content type
content_type = response.headers.get("Content-Type", "")
if "application/json" in content_type:
# Web recording with URL
data = response.json()
recording_url = data.get("url")
print(f"Recording URL: {recording_url}")
else:
# Binary audio file
filename = f"recording_{session_id}.mp3" if "mp3" in content_type else f"recording_{session_id}.wav"
with open(filename, "wb") as f:
f.write(response.content)
print(f"Recording saved to {filename}")
elif response.status_code == 404:
print("Recording not found")
else:
print(f"Error: {response.status_code}")Response
- 200 OK: Audio file (binary) or JSON with URL
- 401 Unauthorized: Invalid or missing API key
- 404 Not Found: Session or recording not found
Get Transcript (Single Session)
Retrieve formatted events or transcript for a specific session. Returns conversation events with role (user/assistant/system), content, and metadata.
GET /v1/agents/{agentId}/sessions/{sessionId}/formattedEventsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| format | string | Response format: "json" or "csv" (default: "csv") |
| filter | string | Optional: "transcript" to filter only transcript events (events with name "transcript_part") |
Example Usage
import requests
agent_id = "agent-123"
session_id = "session-456"
api_key = "your-api-key"
url = f"https://api.primvoices.com/v1/agents/{agent_id}/sessions/{session_id}/formattedEvents"
headers = {
"Authorization": f"Bearer {api_key}"
}
# Get transcript as JSON (filtered to transcript events only)
params = {
"format": "json",
"filter": "transcript"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
events = data.get("events", [])
for event in events:
role = event.get("role") # "user", "assistant", or "system"
content = event.get("content")
metadata = event.get("metadata", {})
print(f"[{role}]: {content}")
else:
print(f"Error: {response.status_code}")Response Format (JSON)
{
"events": [
{
"role": "user",
"content": "Hello, I'd like to make a reservation",
"metadata": {
"timestamp": "2024-05-07T10:30:00.000Z"
}
},
{
"role": "assistant",
"content": "I'd be happy to help you make a reservation. What date and time would you like?",
"metadata": {
"voice": "nova",
"timestamp": "2024-05-07T10:30:05.000Z"
}
}
]
}Response
- 200 OK: JSON object with events array or CSV string
- 401 Unauthorized: Invalid or missing API key
- 404 Not Found: Session not found
- 500 Internal Server Error: Server error
Note: The "role" field can be "user" (for text events), "assistant" (for text_to_speech events), or "system" (for other events).
Bulk Export Transcripts
Export transcripts for multiple sessions within a date range. Useful for bulk analysis, reporting, or data export. Returns transcripts for all sessions matching the criteria.
GET /v1/agents/{agentId}/sessions/export-transcriptsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| startDate | string | Required. Start date in ISO 8601 format (e.g., "2024-05-07T00:00:00.000Z") |
| endDate | string | Required. End date in ISO 8601 format (e.g., "2024-05-08T23:59:59.999Z") |
| format | string | Response format: "json" or "csv" (default: "csv") |
| limit | number | Maximum number of sessions to export (default: 100, max: 100) |
Example Usage
import requests
from datetime import datetime, timedelta
agent_id = "agent-123"
api_key = "your-api-key"
url = f"https://api.primvoices.com/v1/agents/{agent_id}/sessions/export-transcripts"
headers = {
"Authorization": f"Bearer {api_key}"
}
# Export transcripts for the last 7 days
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=7)
params = {
"startDate": start_date.isoformat() + "Z",
"endDate": end_date.isoformat() + "Z",
"format": "json",
"limit": 100
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
sessions = data.get("sessions", [])
meta = data.get("meta", {})
print(f"Exported {meta.get('exportedSessions', 0)} sessions")
print(f"Total sessions: {meta.get('totalSessions', 0)}")
for session in sessions:
session_id = session.get("sessionId")
transcript = session.get("transcript", [])
print(f"\nSession {session_id}: {len(transcript)} events")
for event in transcript:
print(f" [{event.get('role')}]: {event.get('content')}")
else:
print(f"Error: {response.status_code}")
print(response.text)Response Format (JSON)
{
"sessions": [
{
"sessionId": "session-456",
"transcript": [
{
"role": "user",
"content": "Hello, I'd like to make a reservation",
"metadata": {
"timestamp": "2024-05-07T10:30:00.000Z"
}
},
{
"role": "assistant",
"content": "I'd be happy to help you make a reservation.",
"metadata": {
"voice": "nova",
"timestamp": "2024-05-07T10:30:05.000Z"
}
}
]
},
{
"sessionId": "session-789",
"transcript": [...]
}
],
"meta": {
"totalSessions": 10,
"exportedSessions": 10,
"startDate": "2024-05-07T00:00:00.000Z",
"endDate": "2024-05-08T23:59:59.999Z"
}
}Response
- 200 OK: JSON object with sessions array and metadata, or CSV string
- 400 Bad Request: Missing required parameters (startDate or endDate)
- 401 Unauthorized: Invalid or missing API key
- 500 Internal Server Error: Server error
Note: The limit parameter is capped at 100 sessions per request. For larger exports, make multiple requests with different date ranges.
Vertical-Specific Analytics
The following endpoints provide analytics for specific business verticals. The examples below demonstrate reservation analytics, but similar patterns and metrics apply to other domains supported by your agents (customer service, sales, etc.).
Daily Reservation Analytics
Retrieve daily breakdown of reservation analytics metrics including bookings, modifications, cancellations, and session statistics. Returns metrics aggregated by date within the specified period.
GET /v1/analytics/reservation/dailyQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| startDate | string | Required. Start date in YYYY-MM-DD format |
| endDate | string | Required. End date in YYYY-MM-DD format |
| agentId | string | Filter by agent ID (required if restaurantId not provided) |
| restaurantId | string | Filter by restaurant ID (required if agentId not provided) |
| groupByRestaurant | boolean | When true, returns separate metrics per restaurant per day |
| environment | string | Environment name (default: "production") |
Example Usage
import requests
agent_id = "agent-123"
api_key = "your-api-key"
url = "https://api.primvoices.com/v1/analytics/reservation/daily"
headers = {
"Authorization": f"Bearer {api_key}"
}
params = {
"agentId": agent_id,
"startDate": "2025-12-01",
"endDate": "2025-12-15",
"environment": "production"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
metrics = data.get("metrics", [])
for daily_metric in metrics:
date = daily_metric.get("date")
booking_rate = daily_metric.get("bookingConversionRate", 0)
print(f"{date}: {booking_rate:.2%} booking conversion")
else:
print(f"Error: {response.status_code}")Response Format (JSON)
{
"agentId": "agent-123",
"restaurantId": null,
"groupByRestaurant": false,
"period": {
"startDate": "2025-12-01",
"endDate": "2025-12-15"
},
"metrics": [
{
"date": "2025-12-15",
"sessionCount": 45,
"sessionsHandled": 40,
"sessionsTransferred": 5,
"avgSessionDurationSeconds": 125.50,
"bookingAttempts": 30,
"bookingSuccesses": 27,
"bookingConversionRate": 0.9000,
"modificationAttempts": 10,
"modificationSuccesses": 8,
"modificationConversionRate": 0.8000,
"cancellationAttempts": 5,
"cancellationSuccesses": 3,
"cancellationConversionRate": 0.6000,
"messageAttempts": 15,
"messageSuccesses": 14,
"messageConversionRate": 0.9333,
"questionsAnswered": 42
}
]
}Response
- 200 OK: JSON object with daily metrics array
- 400 Bad Request: Missing required parameters or invalid filter combination
- 403 Forbidden: User lacks admin/owner privileges
- 500 Internal Server Error: Server error
Note: Either agentId or restaurantId must be provided. Conversion rates are calculated as successes/attempts and return null if attempts = 0.
Reservation Analytics Summary
Retrieve aggregated summary of reservation analytics metrics for a date range. Returns a single summary object with totals and averages across the entire period.
GET /v1/analytics/reservation/summaryQuery Parameters
| Parameter | Type | Description |
|---|---|---|
| startDate | string | Required. Start date in YYYY-MM-DD format |
| endDate | string | Required. End date in YYYY-MM-DD format |
| agentId | string | Filter by agent ID (required if restaurantId not provided) |
| restaurantId | string | Filter by restaurant ID (required if agentId not provided) |
| environment | string | Environment name (default: "production") |
Example Usage
import requests
agent_id = "agent-123"
api_key = "your-api-key"
url = "https://api.primvoices.com/v1/analytics/reservation/summary"
headers = {
"Authorization": f"Bearer {api_key}"
}
params = {
"agentId": agent_id,
"startDate": "2025-12-01",
"endDate": "2025-12-15"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
metrics = data.get("metrics", {})
total_sessions = metrics.get("totalSessions", 0)
booking_rate = metrics.get("bookingConversionRate", 0)
print(f"Total Sessions: {total_sessions}")
print(f"Booking Conversion Rate: {booking_rate:.2%}")
else:
print(f"Error: {response.status_code}")Response Format (JSON)
{
"period": {
"startDate": "2025-12-01",
"endDate": "2025-12-15"
},
"agentId": "agent-123",
"restaurantId": null,
"metrics": {
"totalSessions": 500,
"sessionsHandled": 480,
"sessionsTransferred": 20,
"avgSessionDurationSeconds": 122.15,
"bookingAttempts": 350,
"bookingSuccesses": 320,
"bookingConversionRate": 0.9143,
"modificationAttempts": 120,
"modificationSuccesses": 100,
"modificationConversionRate": 0.8333,
"cancellationAttempts": 80,
"cancellationSuccesses": 45,
"cancellationConversionRate": 0.5625,
"messageAttempts": 200,
"messageSuccesses": 185,
"messageConversionRate": 0.9250,
"questionsAnswered": 495
}
}Response
- 200 OK: JSON object with aggregated summary metrics
- 400 Bad Request: Missing required parameters or invalid filter combination
- 403 Forbidden: User lacks admin/owner privileges
- 500 Internal Server Error: Server error
Note: Returns a single summary aggregating all metrics across the entire date range. Session duration is a weighted average across all days.