Go to Rilla

Data Export API

Export your organization's conversation, team, and user analytics data programmatically.

Overview

Authenticate with your API key and POST a date range to any export endpoint. Rilla returns a structured payload of analytics data you can load into a database, spreadsheet, or BI tool.

Base URL

https://customer.rillavoice.com

How it works

Admins and Team Managers can create API keys in the Rilla web app. Follow Get an API key for the Settings location, team access, and one-time key reveal. If you don’t have access, ask your organization’s admin or your Rilla account manager for a key.

Include your API key in the Authorization header of every request: Authorization: YOUR_API_KEY.

POST a date range to /export/conversations, /export/teams, or /export/users.

The conversations endpoint is paginated. Use totalPages in the response to loop through all results.

Authentication

All requests to the Data Export API must include a valid API key passed in the Authorization header.

POST /export/conversations HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY
Content-Type: application/json

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.
Content-TypestringYesMust be application/json.

Obtaining an API Key

Open Settings → Developer and select Create API key in the API keys tab, or ask your organization’s admin or your Rilla account manager for a key. Follow the Quickstart instructions for the creation and one-time reveal steps. Each key belongs to a single Rilla organization. Admins can select organization-wide access or specific teams; Team Managers are limited to teams they manage. Data Export includes the selected teams and their subteams.

Rilla validates the API key and its organization mapping; successful authentication can be cached for up to five minutes. If the key is missing or unrecognized, the API returns 401 Unauthorized.

Keep your key secure

API keys grant access to your organization's data and can also be used with the Custom CRM API. Do not expose them in client-side code, public repositories, or logs. Contact support@rilla.com immediately if a key is ever compromised.

GET /export/conversations/{conversationId}

Fetches a single conversation by its ID. Returns the same conversation object as the list endpoint below, but as a bare object rather than inside a paginated wrapper.

Use this when you already know a conversation's ID — for example, a conversation_id received from a webhook — and want to pull its full export record without specifying a date range.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Path Parameters

ParameterTypeRequiredDescription
conversationIdstring (UUID)YesID of the conversation to fetch. Must be a valid UUID.

Response

Returns a single ConversationsExport object. Unlike the list endpoint, there is no pagination wrapper.

Returns 404 Not Found if the conversation does not exist, or if it falls outside the scope of your API key. Team-scoped keys receive a 404 (rather than 403) for conversations they cannot access, so existence is never leaked.

Example Request

GET /export/conversations/f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns ConversationsExport. This example includes every documented field.

ConversationsExport · complete example
{
  "conversationId": "11111111-1111-4111-8111-111111111111",
  "recordingId": "22222222-2222-4222-8222-222222222222",
  "date": "2026-09-01T14:00:00Z",
  "processedDate": "2026-09-01T15:12:00Z",
  "title": "Home estimate - Jordan Lee",
  "duration": 3240,
  "crmEventID": "evt-90817",
  "user": {
    "id": "33333333-3333-4333-8333-333333333333",
    "name": "Alex Morgan",
    "email": "alex@example.com"
  },
  "transcriptUrl": "https://example.com/temporary-transcript.json?signature=EXAMPLE",
  "jobNumber": "JOB-4471",
  "stLink": "https://go.servicetitan.com/jobs/4471",
  "totalSold": 12500,
  "outcome": "Sold",
  "jobSummary": "Rep walked the customer through the premium package and scheduled install.",
  "customSummary": "Customer expressed interest in premium package...",
  "repSpeedWPM": 148,
  "repTalkRatio": 0.54,
  "longestRepMonologue": 120,
  "longestCustomerMonologue": 64,
  "totalComments": 3,
  "rillaUrl": "https://app.rilla.com/conversations/single?id=11111111-1111-4111-8111-111111111111",
  "audioUrl": "https://example.com/temporary-audio.mp3?signature=EXAMPLE",
  "viewers": [
    {
      "userId": "user-014",
      "name": "Manager Mike",
      "viewCount": 2,
      "totalViewTimeMs": 540000
    }
  ],
  "checklists": [
    {
      "name": "Discovery",
      "checklistName": "Discovery",
      "score": 1,
      "checklistScore": 1,
      "denominator": 1,
      "checklistDenominator": 1,
      "trackerData": [
        {
          "trackerId": "1042",
          "name": "Asked about budget",
          "trackerName": "Asked about budget",
          "isHit": true,
          "trackerIsHit": true,
          "aiScore": 0.92,
          "trackerAiScore": 0.92
        }
      ]
    }
  ],
  "aiTrackers": [
    {
      "checklistName": "Discovery",
      "trackerId": "1043",
      "trackerName": "Mentioned financing",
      "isHit": true,
      "aiScore": 0.92
    }
  ],
  "customFields": {
    "leadSource": "Website"
  },
  "customer": {
    "name": "Jordan Lee",
    "email": "jordan@example.com",
    "phone": "+1-202-555-0142",
    "address": {
      "street": "123 Example Street",
      "unit": null,
      "city": "New York",
      "state": "NY",
      "zip": "10001",
      "country": "US"
    }
  },
  "surveyResults": [
    {
      "surveyId": "55555555-5555-4555-8555-555555555555",
      "surveyName": "Discovery quality",
      "data": {
        "next_step_confirmed": true
      }
    }
  ]
}

POST /export/conversations

Exports data for all conversations recorded during the provided time range. Results are paginated — use page and limit to iterate.

The response also includes recordings from the time range that have not (or not yet) produced a conversation: awaitingUpload for recordings still on the rep's device, and errored for recordings that were uploaded but did not produce a conversation. Both carry the same recording and job data as conversations, minus fields that only exist once a conversation has been processed (talk metrics, trackers, summaries, audio/transcript URLs).

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.
Content-TypestringYesMust be application/json.

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range; use a UTC timestamp ending in Z.
toDatestringYesEnd of the time range; use a UTC timestamp ending in Z. Conversation bounds are inclusive. Most user/team metrics are inclusive too, except scorecards/live coaching which exclude the end. Choose an end after the start.
dateTypestringNotimeOfRecording (default) or processedDate.
pagenumberNo1-based page index. Defaults to 1.
limitnumberNoConversations per page. Max 50. Defaults to 50.
usersstring[]NoExact, case-sensitive user emails. Omit or send [] for all users. Team-scoped filters with no allowed matches currently fall back to all allowed users; verify returned emails.

Response

FieldTypeDescription
currentPagenumberThe current page number.
totalPagesnumberTotal number of pages, across the conversations, awaitingUpload, and errored arrays.
totalConversationsnumberTotal conversations for the date range.
totalAwaitingUploadnumberTotal recordings awaiting upload for the date range. Omitted when dateType is processedDate.
totalErrorednumberTotal errored recordings for the date range.
conversationsarrayConversation objects. See ConversationsExport.
awaitingUploadarrayRecordings not yet uploaded from the rep's device. Omitted when dateType is processedDate, since these recordings have not been processed. See RecordingsExport.
erroredarrayRecordings that were uploaded but did not produce a conversation. See ErroredRecordingsExport.

All three arrays are paginated independently by the same page and limit — page 2 returns the second page of conversations and the second page of each recordings array. totalPages covers whichever array has the most pages, so pages near the end may return empty arrays for the sets that are already exhausted.

Example Request

{
  "fromDate": "2026-09-01T00:00:00Z",
  "toDate": "2026-09-02T00:00:00Z",
  "dateType": "timeOfRecording",
  "page": 1,
  "limit": 50
}

Example Response

Returns ConversationsExportResponse. This example includes every documented field.

ConversationsExportResponse · complete example
{
  "currentPage": 1,
  "totalPages": 1,
  "totalConversations": 1,
  "totalAwaitingUpload": 1,
  "totalErrored": 1,
  "conversations": [
    {
      "conversationId": "11111111-1111-4111-8111-111111111111",
      "recordingId": "22222222-2222-4222-8222-222222222222",
      "date": "2026-09-01T14:00:00Z",
      "processedDate": "2026-09-01T15:12:00Z",
      "title": "Home estimate - Jordan Lee",
      "duration": 3240,
      "crmEventID": "evt-90817",
      "user": {
        "id": "33333333-3333-4333-8333-333333333333",
        "name": "Alex Morgan",
        "email": "alex@example.com"
      },
      "transcriptUrl": "https://example.com/temporary-transcript.json?signature=EXAMPLE",
      "jobNumber": "JOB-4471",
      "stLink": "https://go.servicetitan.com/jobs/4471",
      "totalSold": 12500,
      "outcome": "Sold",
      "jobSummary": "Rep walked the customer through the premium package and scheduled install.",
      "customSummary": "Customer expressed interest in premium package...",
      "repSpeedWPM": 148,
      "repTalkRatio": 0.54,
      "longestRepMonologue": 120,
      "longestCustomerMonologue": 64,
      "totalComments": 3,
      "rillaUrl": "https://app.rilla.com/conversations/single?id=11111111-1111-4111-8111-111111111111",
      "audioUrl": "https://example.com/temporary-audio.mp3?signature=EXAMPLE",
      "viewers": [
        {
          "userId": "user-014",
          "name": "Manager Mike",
          "viewCount": 2,
          "totalViewTimeMs": 540000
        }
      ],
      "checklists": [
        {
          "name": "Discovery",
          "checklistName": "Discovery",
          "score": 1,
          "checklistScore": 1,
          "denominator": 1,
          "checklistDenominator": 1,
          "trackerData": [
            {
              "trackerId": "1042",
              "name": "Asked about budget",
              "trackerName": "Asked about budget",
              "isHit": true,
              "trackerIsHit": true,
              "aiScore": 0.92,
              "trackerAiScore": 0.92
            }
          ]
        }
      ],
      "aiTrackers": [
        {
          "checklistName": "Discovery",
          "trackerId": "1043",
          "trackerName": "Mentioned financing",
          "isHit": true,
          "aiScore": 0.92
        }
      ],
      "customFields": {
        "leadSource": "Website"
      },
      "customer": {
        "name": "Jordan Lee",
        "email": "jordan@example.com",
        "phone": "+1-202-555-0142",
        "address": {
          "street": "123 Example Street",
          "unit": null,
          "city": "New York",
          "state": "NY",
          "zip": "10001",
          "country": "US"
        }
      },
      "surveyResults": [
        {
          "surveyId": "55555555-5555-4555-8555-555555555555",
          "surveyName": "Discovery quality",
          "data": {
            "next_step_confirmed": true
          }
        }
      ]
    }
  ],
  "awaitingUpload": [
    {
      "recordingId": "rec-2b91d3aa",
      "date": "2026-09-01T17:45:00Z",
      "title": "Panel Upgrade - Sarah Lee",
      "duration": 1860,
      "crmEventID": "evt-90932",
      "user": {
        "id": "33333333-3333-4333-8333-333333333333",
        "name": "Alex Morgan",
        "email": "alex@example.com"
      },
      "jobNumber": "JOB-4519",
      "stLink": "https://go.servicetitan.com/jobs/4519",
      "totalSold": null,
      "outcome": null,
      "customFields": {
        "leadSource": "Website"
      }
    }
  ],
  "errored": [
    {
      "recordingId": "rec-2b91d3aa",
      "date": "2026-09-01T17:45:00Z",
      "title": "Panel Upgrade - Sarah Lee",
      "duration": 1860,
      "crmEventID": "evt-90932",
      "user": {
        "id": "33333333-3333-4333-8333-333333333333",
        "name": "Alex Morgan",
        "email": "alex@example.com"
      },
      "jobNumber": "JOB-4519",
      "stLink": "https://go.servicetitan.com/jobs/4519",
      "totalSold": null,
      "outcome": null,
      "customFields": {
        "leadSource": "Website"
      },
      "processedDate": "2026-09-01T10:02:00Z",
      "error": "AUDIO_TOO_SHORT"
    }
  ]
}

POST /export/teams

Returns a TeamsExportResponse containing teams: TeamsExport[]. The response is not paginated.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.
Content-TypestringYesMust be application/json.

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range; use a UTC timestamp ending in Z.
toDatestringYesEnd of the time range; use a UTC timestamp ending in Z. Conversation bounds are inclusive. Most user/team metrics are inclusive too, except scorecards/live coaching which exclude the end. Choose an end after the start.
includeSubteamsbooleanNoWhether to roll descendant-team members into each team’s metrics. Defaults to false; does not remove descendant team rows.

Response

FieldTypeDescription
teamsarrayArray of TeamsExport objects.

Example Request

{
  "fromDate": "2026-09-01T00:00:00Z",
  "toDate": "2026-09-02T00:00:00Z",
  "includeSubteams": true
}

Example Response

Returns TeamsExportResponse. This example includes every documented field.

TeamsExportResponse · complete example
{
  "teams": [
    {
      "name": "West Region",
      "teamId": "team-42",
      "externalTeamId": "ST-WEST",
      "parentTeamId": null,
      "parentTeamName": null,
      "analyticsViewed": 12,
      "appointmentsRecorded": 88,
      "averageConversationDuration": 2980,
      "averageConversationLength": 3120,
      "clipCommentsGiven": 7,
      "clipsCreated": 14,
      "clipViewDuration": 86400,
      "commentsGiven": 41,
      "commentsRead": 33,
      "commentsReceived": 52,
      "conversationViewDuration": 172800,
      "conversationsCommentedOn": 29,
      "conversationsRecorded": 95,
      "conversationsViewed": 140,
      "longestCustomerMonologueAverage": 58,
      "longestMonologueAverage": 102,
      "patienceAverage": 0.71,
      "recordingCompliance": 0.92,
      "ridealongsReceived": 4,
      "scorecardsGiven": 18,
      "scorecardsReceived": 22,
      "talkRatioAverage": 0.52,
      "totalAppointments": 96,
      "totalUsersWhoRecorded": 9,
      "totalUsers": 11
    }
  ]
}

POST /export/users

Returns a UsersExportResponse containing users: UsersExport[]. Each user has all documented fields, including nested live coaching metrics. The response is not paginated.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.
Content-TypestringYesMust be application/json.

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range; use a UTC timestamp ending in Z.
toDatestringYesEnd of the time range; use a UTC timestamp ending in Z. Conversation bounds are inclusive. Most user/team metrics are inclusive too, except scorecards/live coaching which exclude the end. Choose an end after the start.
usersstring[]NoExact, case-sensitive user emails. Omit or send [] for all users. Team-scoped filters with no allowed matches currently fall back to all allowed users; verify returned emails.

Response

FieldTypeDescription
usersarrayArray of UsersExport objects.

Example Request

{
  "fromDate": "2026-09-01T00:00:00Z",
  "toDate": "2026-09-02T00:00:00Z",
  "users": ["alex@example.com"]
}

Example Response

Returns UsersExportResponse. This example includes every documented field.

UsersExportResponse · complete example
{
  "users": [
    {
      "userId": "33333333-3333-4333-8333-333333333333",
      "name": "Alex Morgan",
      "email": "alex@example.com",
      "accountSetUp": true,
      "isRemoved": false,
      "role": "Sales Rep",
      "teams": [
        {
          "teamId": "44444444-4444-4444-8444-444444444444",
          "name": "West region"
        }
      ],
      "timeOfFirstRecording": "2023-11-02T16:20:00Z",
      "lastActive": "2026-09-01T09:45:00Z",
      "hasVoiceId": true,
      "analyticsViewed": 5,
      "appointmentsRecorded": 46,
      "averageConversationDuration": 3150,
      "averageConversationLength": 3260,
      "averageScriptCompliance": 0.81,
      "averageTimePerRidealong": 1800,
      "clipCommentsGiven": 3,
      "clipsCreated": 6,
      "clipViewDuration": 43200,
      "commentsReceived": 28,
      "commentsRead": 21,
      "commentsGiven": 12,
      "conversationsCommentedOn": 15,
      "conversationsRecorded": 48,
      "conversationsViewed": 70,
      "conversationViewDuration": 86400,
      "lastRidealongAt": "2026-09-01T13:00:00Z",
      "longestMonologueAverage": 115,
      "longestCustomerMonologueAverage": 52,
      "patienceAverage": 0.68,
      "percentageOfRepsWithCommentsGiven": null,
      "recordingCompliance": 0.9,
      "ridealongsReceived": 2,
      "scorecardsReceived": 9,
      "scorecardsGiven": 4,
      "talkRatioAverage": 0.53,
      "totalAppointments": 51,
      "totalEndOfRidealongsReached": 1,
      "totalRidealongsCompleted": 3,
      "viewedRecordedRatio": 0.5,
      "liveCoaching": {
        "sessionsHosted": 2,
        "viewEventsReceived": 18,
        "uniqueViewers": 5,
        "viewDurationMinutes": 64,
        "commentsReceived": 7,
        "uniqueCommenters": 3,
        "moneySaved": 1200,
        "lastCoachedAt": "2026-09-01T10:30:00Z"
      }
    }
  ]
}

Data Models

ConversationsExport

One processed conversation, including linked CRM data, customer, coaching results and temporary download URLs. Also returned directly by GET /export/conversations/{conversationId}. Open ConversationsExport →

FieldTypeDescription
conversationIdstringID of the conversation.
recordingIdstringID of the underlying recording.
datestringRecording start timestamp in ISO 8601 UTC. List selection uses inclusive date bounds.
processedDatestringDate/time the conversation finished processing (ISO 8601).
titlestring | nullTitle of the conversation / appointment.
durationnumberProcessed conversation duration in seconds.
crmEventIDstring | nullID of the associated CRM / calendar event.
userRecordingUserThe rep who recorded the conversation: { id, name, email }.
transcriptUrlstringTemporary presigned S3 URL for the conversation's transcript. Expires 6 hours after the response is issued — download or persist the file rather than storing the URL. Temporary signing credentials may cause earlier expiry.
jobNumberstring | nullJob number from the CRM / calendar event.
stLinkstring | nullServiceTitan job link when the linked appointment uses that integration; null otherwise. Not a generic CRM URL.
totalSoldnumber | nullPrice on the linked appointment in its source currency, or null. This field alone does not establish a sold outcome; no currency code is returned.
outcomestring | nullOutcome of the appointment.
jobSummarystring | nullAI-generated summary of the job.
customSummarystring | nullAdmin summary / custom insights in your organization's format.
repSpeedWPMnumber | nullRep speaking speed, in words per minute.
repTalkRationumber | nullFraction of time the rep was talking (0–1).
longestRepMonologuenumber | nullLongest uninterrupted rep monologue, in seconds.
longestCustomerMonologuenumber | nullLongest uninterrupted customer monologue, in seconds.
totalCommentsnumberAll-time comments on this conversation, not bounded by the request window.
rillaUrlstringLink to view the conversation in the Rilla web app.
audioUrlstringTemporary presigned S3 URL for the conversation's audio recording. Expires 6 hours after the response is issued — download or persist the file rather than storing the URL. Temporary signing credentials may cause earlier expiry.
viewersViewer[]Users who viewed the conversation. See Viewer.
checklistsChecklist[]Coaching checklists scored for the conversation. Each checklist contains its trackers. See Checklist.
aiTrackersAiTracker[]Trackers outside the checklist, from the latest completed evaluations. Not a flattened copy of checklists.trackerData.
customFieldsobject | nullCustom fields from the calendar event. Keys and values are customer-defined. null if none are set.
customerConversationCustomer | nullLinked customer contact and structured address; null when no customer fields exist.
surveyResultsSurveyConversationResult[]Survey results. Each result includes a survey ID, name and customer-defined data; the upstream service may include additional metadata.

Viewer

One viewer of the conversation; totals include all-time views, not just views in the export window. Open Viewer →

FieldTypeDescription
userIdstringRilla user ID of the viewer.
namestringName of the viewer.
viewCountnumberNumber of times this user viewed the conversation.
totalViewTimeMsnumberTotal time this user spent viewing, in milliseconds.

Checklist

Latest completed evaluation per checklist for this conversation. Includes checklist trackers and compatibility aliases. Open Checklist →

FieldTypeDescription
namestringAlias of checklistName.
checklistNamestringName of the checklist.
scorenumberAlias of checklistScore.
checklistScorenumberNumber of trackers hit on this checklist.
denominatornumberAlias of checklistDenominator.
checklistDenominatornumberTotal number of trackers in the checklist.
trackerDataTracker[]The individual trackers evaluated for this checklist. See Tracker.

Tracker

An in-checklist tracker. Prefer the tracker-prefixed fields; unprefixed fields are compatibility aliases with the same values. Open Tracker →

FieldTypeDescription
trackerIdstringUnique identifier of the tracker. Stable across conversations, so it can be used to group or join tracker results.
namestringAlias of trackerName.
trackerNamestringName of the tracker.
isHitboolean | nullAlias of trackerIsHit.
trackerIsHitboolean | nullWhether the tracker was hit during the conversation.
aiScorenumber | nullAlias of trackerAiScore.
trackerAiScorenumber | nullAI-generated score for the tracker.

AiTracker

A tracker evaluated outside a checklist (is_in_checklist = false). This array is not a flattened duplicate of checklists.trackerData. Open AiTracker →

FieldTypeDescription
checklistNamestringName of the checklist this tracker belongs to.
trackerIdstringUnique identifier of the tracker. Stable across conversations, so it can be used to group or join tracker results.
trackerNamestringName of the tracker.
isHitboolean | nullWhether the tracker was hit during the conversation.
aiScorenumber | nullAI-generated score for the tracker.

RecordingsExport

A recording awaiting upload. No conversation, transcript or coaching results exist yet. Open RecordingsExport →

FieldTypeDescription
recordingIdstringID of the recording.
datestringDate/time the recording was made (ISO 8601).
titlestring | nullTitle of the recording / appointment.
durationnumberDuration in seconds.
crmEventIDstring | nullID of the associated CRM / calendar event.
userRecordingUserThe rep who made the recording: { id, name, email }.
jobNumberstring | nullJob number from the CRM / calendar event.
stLinkstring | nullServiceTitan job link when the linked appointment uses that integration; null otherwise. Not a generic CRM URL.
totalSoldnumber | nullPrice on the linked appointment in its source currency, or null. This field alone does not establish a sold outcome; no currency code is returned.
outcomestring | nullOutcome of the appointment. null if no outcome is recorded.
customFieldsobject | nullCustom fields from the calendar event. Keys and values are customer-defined. null if none are set.

ErroredRecordingsExport

A recording that did not produce a conversation. Includes recording fields plus its processing timestamp and error. Open ErroredRecordingsExport →

FieldTypeDescription
recordingIdstringID of the recording.
datestringDate/time the recording was made (ISO 8601).
titlestring | nullTitle of the recording / appointment.
durationnumberDuration in seconds.
crmEventIDstring | nullID of the associated CRM / calendar event.
userRecordingUserThe rep who made the recording: { id, name, email }.
jobNumberstring | nullJob number from the CRM / calendar event.
stLinkstring | nullServiceTitan job link when the linked appointment uses that integration; null otherwise. Not a generic CRM URL.
totalSoldnumber | nullPrice on the linked appointment in its source currency, or null. This field alone does not establish a sold outcome; no currency code is returned.
outcomestring | nullOutcome of the appointment. null if no outcome is recorded.
customFieldsobject | nullCustom fields from the calendar event. Keys and values are customer-defined. null if none are set.
processedDatestring | nullDate/time processing finished (ISO 8601).
errorstringWhy the recording did not produce a conversation, e.g. AUDIO_TOO_SHORT or NO_TRANSCRIPT.

Team

One team and its analytics. Membership uses current active, non-hidden users. includeSubteams controls descendant roll-up, not which team rows appear. Users can contribute to multiple teams; do not sum teams as an organization total. Open TeamsExport →

FieldTypeDescription
namestringName of the team.
teamIdstringRilla team ID.
externalTeamIdstring | nullID of the team in the connected CRM. null if not linked.
parentTeamIdstring | nullID of the parent team. null for top-level teams.
parentTeamNamestring | nullName of the parent team. null for top-level teams.
analyticsViewednumberNumber of analytics views by team members.
appointmentsRecordednumberAppointments that were recorded.
averageConversationDurationnumber | nullMean of each member’s mean recording duration, in seconds. Each member with data has equal weight; null if no member has data.
averageConversationLengthnumber | nullMean of each member’s mean rep + customer talk time, in seconds; excludes silence. Null without data.
clipCommentsGivennumberComments given on clips.
clipsCreatednumberClips created.
clipViewDurationnumberTotal clip view duration, in seconds.
commentsGivennumberComments given by team members.
commentsReadnumberComments read by team members.
commentsReceivednumberComments received by team members.
conversationViewDurationnumberTotal conversation view duration, in seconds.
conversationsCommentedOnnumberConversations that received at least one comment.
conversationsRecordednumberDistinct recordings made in the window, including recordings that have not produced a processed conversation.
conversationsViewednumberConversations viewed by team members.
longestCustomerMonologueAveragenumber | nullMean of members’ median longest customer monologues, in seconds; null without data.
longestMonologueAveragenumber | nullMean of members’ median longest rep monologues, in seconds. Each member with data has equal weight; null without data.
patienceAveragenumber | nullMean stored patience metric for conversations recorded in the window; null if no measurement exists. Do not treat it as a percentage.
recordingCompliancenumber | nullEligible recorded appointments divided by eligible appointments, rounded to two decimals. Fraction, not a percentage: 0.92 means 92%. Null when there is no eligible denominator.
ridealongsReceivednumberRide-alongs received.
scorecardsGivennumberScorecards given.
scorecardsReceivednumberScorecards received.
talkRatioAveragenumber | nullMean rep talk ratio, rounded to two decimals. Fraction: 0.53 means 53%; null without measurements.
totalAppointmentsnumberEligible appointment-attendee rows with appointment end_time in the window and more than 3 hours ago. Compliance-disabled appointments/outcomes are excluded; calendar-only sources are excluded when a CRM integration exists.
totalUsersWhoRecordednumberNumber of team members who recorded at least one conversation.
totalUsersnumberTotal number of users in the team.

User

One user and their activity metrics. Returned inside users, not as the top-level response. Hidden users are excluded; removed users can still be returned. Identity, role, teams, first recording and lastActive reflect current/all-time data, not the export window. Open UsersExport →

FieldTypeDescription
userIdstringRilla user ID.
namestring | nullFull name. May be null when a source name component is missing.
emailstringEmail address.
accountSetUpbooleanWhether the user has completed account setup.
isRemovedbooleanWhether the user has been removed/deactivated.
rolestring | nullRole display name, not a fixed enum. May be null if there is no matching role.
teamsTeamMembership[] | nullCurrent team memberships, sorted by team name. Null (not an empty array) when the user has no team membership.
timeOfFirstRecordingstring | nullTimestamp of the user's first recording (ISO 8601), or null.
lastActivestring | nullTimestamp of the user's last activity (ISO 8601), or null. For reps this is their most recent recording; for other roles, their most recent product activity. Not bounded by the requested date range.
hasVoiceIdbooleanWhether the user has an enrolled voice ID.
analyticsViewednumberNumber of analytics views.
appointmentsRecordednumber | nullAppointments recorded.
averageConversationDurationnumber | nullMean recording duration in seconds, including recordings without a processed conversation. Null when no duration is available.
averageConversationLengthnumber | nullMean rep talk time plus customer talk time in seconds for processed conversations. Excludes silence; null without measurements.
averageScriptCompliancenumber | nullMean checklist score/denominator over completed checklist evaluations on recordings in the window, rounded to two decimals. Fraction; null without usable results. Multiple evaluations can contribute.
averageTimePerRidealongnumber | nullAverage time per ride-along, in seconds.
clipCommentsGivennumberComments given on clips.
clipsCreatednumberClips created.
clipViewDurationnumberTotal clip view duration, in seconds.
commentsReceivednumberComments received.
commentsReadnumberComments read.
commentsGivennumberComments given.
conversationsCommentedOnnumberConversations the user commented on.
conversationsRecordednumberDistinct recordings made in the window, including recordings that have not produced a processed conversation.
conversationsViewednumberConversations viewed.
conversationViewDurationnumberTotal conversation view duration, in seconds.
lastRidealongAtstring | nullMost recent completed ride-along in the requested window; null if none.
longestMonologueAveragenumber | nullMedian (not arithmetic mean) of the longest rep monologue per conversation, in seconds. The field name is retained for compatibility.
longestCustomerMonologueAveragenumber | nullMedian of the longest customer monologue per conversation, in seconds. Null without measurements.
patienceAveragenumber | nullMean stored patience metric for conversations recorded in the window; null if no measurement exists. Do not treat it as a percentage.
percentageOfRepsWithCommentsGivennumber | nullManager/admin comment reach divided by the relevant rep count, rounded to two decimals. Uses the conversation recording window, not comment creation time. Fraction (not multiplied by 100); null without an applicable denominator.
recordingCompliancenumber | nullEligible recorded appointments divided by eligible appointments, rounded to two decimals. Fraction, not a percentage: 0.92 means 92%. Null when there is no eligible denominator.
ridealongsReceivednumberRide-alongs received.
scorecardsReceivednumberScorecards received.
scorecardsGivennumberScorecards given.
talkRatioAveragenumber | nullMean rep talk ratio, rounded to two decimals. Fraction: 0.53 means 53%; null without measurements.
totalAppointmentsnumberEligible appointment-attendee rows with appointment end_time in the window and more than 3 hours ago. Compliance-disabled appointments/outcomes are excluded; calendar-only sources are excluded when a CRM integration exists.
totalEndOfRidealongsReachednumberRide-alongs completed through to the end.
totalRidealongsCompletednumberRide-alongs completed.
viewedRecordedRationumber | nullSelf-viewed recorded conversations divided by distinct recordings made in the window, rounded to two decimals. Both recording and view must fall in the window. Can be null even when recordings exist but none were self-viewed; not conversationsViewed / conversationsRecorded.
liveCoachingLiveCoachingMetricsLive coaching metrics. See LiveCoaching.

LiveCoaching

Metrics for the user as the host being coached. View/comment counts require an Admin or Team Manager coach. Without qualifying coaching activity the object contains zero counts and lastCoachedAt: null. Open LiveCoachingMetrics →

FieldTypeDescription
sessionsHostednumberRooms created in the window for hosts with qualifying coach views or comments in the window. Not all rooms for all hosts.
viewEventsReceivednumberView events received on hosted sessions.
uniqueViewersnumberUnique viewers across hosted sessions.
viewDurationMinutesnumberSum of viewer participant durations for qualifying hosts, in minutes. Participants are selected by join time; duration can extend beyond the export end time.
commentsReceivednumberComments received during live coaching.
uniqueCommentersnumberUnique commenters during live coaching.
moneySavednumberSum of positive appointment prices attributed by the live-coaching rule: a qualifying sold outcome and a coach view within 7 calendar days before or after the appointment date. Not a proven causal savings amount; no currency code is returned.
lastCoachedAtstring | nullTimestamp of the last live coaching session (ISO 8601), or null.

Code Examples

Fetch all conversations (paginated)

import requests

def fetch_all_conversations(from_date, to_date, api_key):
    url = "https://customer.rillavoice.com/export/conversations"
    headers = {
        "Authorization": api_key,
        "Content-Type": "application/json"
    }
    conversations = []
    page = 1
    total_pages = 1

    while page <= total_pages:
        payload = {"fromDate": from_date, "toDate": to_date, "page": page, "limit": 50}
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        data = response.json()
        conversations.extend(data["conversations"])
        total_pages = data["totalPages"]
        page += 1

    return conversations
async function fetchAllConversations(fromDate, toDate, apiKey) {
  const conversations = []
  let page = 1
  let totalPages = 1

  do {
    const res = await fetch('https://customer.rillavoice.com/export/conversations', {
      method: 'POST',
      headers: {
        Authorization: apiKey,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ fromDate, toDate, page, limit: 50 }),
    })
    if (!res.ok) throw new Error(`Export failed: ${res.status}`)
    const data = await res.json()
    conversations.push(...data.conversations)
    totalPages = data.totalPages
    page++
  } while (page <= totalPages)

  return conversations
}
curl -X POST https://customer.rillavoice.com/export/conversations \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fromDate": "2026-09-01T00:00:00Z", "toDate": "2026-09-02T00:00:00Z", "page": 1, "limit": 50}'

Fetch a single conversation by ID

import requests

def fetch_conversation(conversation_id, api_key):
    url = f"https://customer.rillavoice.com/export/conversations/{conversation_id}"
    headers = {"Authorization": api_key}
    response = requests.get(url, headers=headers)
    if response.status_code == 404:
        return None
    response.raise_for_status()
    return response.json()
async function fetchConversation(conversationId, apiKey) {
  const res = await fetch(
    `https://customer.rillavoice.com/export/conversations/${conversationId}`,
    { headers: { Authorization: apiKey } },
  )
  if (res.status === 404) return null
  if (!res.ok) throw new Error(`Request failed: ${res.status}`)
  return res.json()
}
curl https://customer.rillavoice.com/export/conversations/f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f \
  -H "Authorization: YOUR_API_KEY"

Fetch teams

import requests

url = "https://customer.rillavoice.com/export/teams"
headers = {
    "Authorization": "YOUR_API_KEY",
    "Content-Type": "application/json"
}
payload = {
    "fromDate": "2026-09-01T00:00:00Z",
    "toDate": "2026-09-02T00:00:00Z",
    "includeSubteams": True
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
const response = await fetch('https://customer.rillavoice.com/export/teams', {
  method: 'POST',
  headers: {
    Authorization: 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    fromDate: '2026-09-01T00:00:00Z',
    toDate: '2026-09-02T00:00:00Z',
    includeSubteams: true,
  }),
})
curl -X POST https://customer.rillavoice.com/export/teams \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fromDate": "2026-09-01T00:00:00Z", "toDate": "2026-09-02T00:00:00Z", "includeSubteams": true}'

Fetch users

import requests

url = "https://customer.rillavoice.com/export/users"
headers = {
    "Authorization": "YOUR_API_KEY",
    "Content-Type": "application/json"
}
payload = {
    "fromDate": "2026-09-01T00:00:00Z",
    "toDate": "2026-09-02T00:00:00Z"
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
const response = await fetch('https://customer.rillavoice.com/export/users', {
  method: 'POST',
  headers: {
    Authorization: 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    fromDate: '2026-09-01T00:00:00Z',
    toDate: '2026-09-02T00:00:00Z',
  }),
})
curl -X POST https://customer.rillavoice.com/export/users \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fromDate": "2026-09-01T00:00:00Z", "toDate": "2026-09-02T00:00:00Z"}'

Error Codes

Data Export errors are JSON objects with a message field. Validation errors also include an errors array with field paths. This differs from Custom CRM’s normally plain-text responses.

{"message":"Invalid JSON in request body"}

Use straight double quotes in JSON, not smart quotes, and remove trailing commas. Check syntax locally with python3 -m json.tool request.json, or use the browser-only JSON checker on each endpoint page.

CodeStatusDescription
200OKThe request was processed successfully.
400Bad RequestMalformed request or missing required fields. Common causes: fromDate or toDate missing; invalid date format; page or limit not a positive integer; limit exceeds 50; users array contains an invalid email; body is not valid JSON.
401UnauthorizedAuthorization header missing or API key not recognized.
404Not FoundThe requested conversation does not exist, or is outside the scope of your API key. Returned by GET /export/conversations/{conversationId}.
500Internal Server ErrorUnexpected server error.

400 and 404 errors are permanent — retrying the same request will not help. 401 errors indicate auth problems — verify the Authorization header is set to your raw API key (no prefix). 500 errors may be transient — retry with exponential backoff.

Rate Limits

The Data Export API does not enforce application-level rate limits. There is no per-key or per-IP throttling built into the API itself.

Effective limits depend on the deployed infrastructure and key configuration. AWS regional defaults are not a per-customer quota or throughput guarantee. Confirm your intended volume with Rilla.

High-volume Usage

If your integration requires high-throughput or bulk export operations, reach out to support@rilla.com before going live.

Best Practices

  • Retry with exponential backoff on 429 or 5xx responses.
  • Page through results incrementally rather than requesting all data at once.
  • Narrow your date ranges to reduce response size and processing time.

Pagination

The /export/conversations endpoint returns results one page at a time. Use page and limit to control which slice of results you receive, and totalPages to know when to stop.

Request Parameters

ParameterDefaultMaxDescription
page1—1-based page index.
limit5050Conversations per page.

Response Fields

FieldDescription
currentPageThe page number of the current response.
totalPagesTotal number of pages for the date range, across the conversations, awaitingUpload, and errored arrays.
totalConversationsTotal conversations across all pages.
totalAwaitingUploadTotal recordings awaiting upload across all pages. Omitted when dateType is processedDate.
totalErroredTotal errored recordings across all pages.
conversationsArray of conversation objects on this page.
awaitingUploadArray of recordings awaiting upload on this page. Omitted when dateType is processedDate.
erroredArray of errored recordings on this page.

The three arrays are paginated independently by the same page and limit. totalPages covers whichever array has the most pages, so pages near the end may return empty arrays for sets that are already exhausted.

Fetching all pages

Loop from page 1 to totalPages, incrementing page each iteration.

async function fetchAllConversations(fromDate, toDate, apiKey) {
  const conversations = []
  let page = 1
  let totalPages = 1

  do {
    const res = await fetch('https://customer.rillavoice.com/export/conversations', {
      method: 'POST',
      headers: {
        Authorization: apiKey,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ fromDate, toDate, page, limit: 50 }),
    })
    if (!res.ok) throw new Error(`Export failed: ${res.status}`)
    const data = await res.json()
    conversations.push(...data.conversations)
    totalPages = data.totalPages
    page++
  } while (page <= totalPages)

  return conversations
}

Only /export/conversations is paginated. /export/teams and /export/users return all results in a single response.

On this page