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}/sessions

List Sessions

Retrieve a list of sessions for your agent. The following query parameters are available for filtering and pagination:

ParameterTypeDescription
filters[agentId]stringFilter sessions by agent ID
filters[agentEnvironmentId]stringFilter sessions by environment ID
filters[status]stringFilter by session status (e.g., "completed", "in_progress")
filters[createdAt][$gte]stringFilter sessions created after this date (ISO 8601 format)
filters[createdAt][$lte]stringFilter sessions created before this date (ISO 8601 format)
pagenumberPage number for pagination (default: 1)
limitnumberNumber 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}/recording

Path Parameters

ParameterTypeDescription
agentIdstringThe ID of the agent
sessionIdstringThe 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}/formattedEvents

Query Parameters

ParameterTypeDescription
formatstringResponse format: "json" or "csv" (default: "csv")
filterstringOptional: "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-transcripts

Query Parameters

ParameterTypeDescription
startDatestringRequired. Start date in ISO 8601 format (e.g., "2024-05-07T00:00:00.000Z")
endDatestringRequired. End date in ISO 8601 format (e.g., "2024-05-08T23:59:59.999Z")
formatstringResponse format: "json" or "csv" (default: "csv")
limitnumberMaximum 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/daily

Query Parameters

ParameterTypeDescription
startDatestringRequired. Start date in YYYY-MM-DD format
endDatestringRequired. End date in YYYY-MM-DD format
agentIdstringFilter by agent ID (required if restaurantId not provided)
restaurantIdstringFilter by restaurant ID (required if agentId not provided)
groupByRestaurantbooleanWhen true, returns separate metrics per restaurant per day
environmentstringEnvironment 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/summary

Query Parameters

ParameterTypeDescription
startDatestringRequired. Start date in YYYY-MM-DD format
endDatestringRequired. End date in YYYY-MM-DD format
agentIdstringFilter by agent ID (required if restaurantId not provided)
restaurantIdstringFilter by restaurant ID (required if agentId not provided)
environmentstringEnvironment 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.