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.

To ask questions about the same data in Claude, ChatGPT or Cursor instead, connect Rilla MCP.

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.

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"
      },
      "rewindsCompleted": 3,
      "rewindAverageScore": 78.5,
      "trainingLessonsCompleted": 5,
      "trainingAverageScore": 82.25
    }
  ]
}

GET /export/users

Lists the users your API key can access, sorted by name, without metrics. Use it to find a userId.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Query Parameters

ParameterTypeRequiredDescription
querystringNoPart of a full name or email, case-insensitive, up to 200 characters.
teamIdstring (UUID)NoOnly this team's direct members.
rolestringNoPart of a role name, case-insensitive, up to 100 characters, such as Sales Rep, Team Manager or Admin, plus any role your organization added.
removedbooleanNotrue for removed users only, false for active users only. Omit for both.
pageintegerNoPage to return, from 1. Requires limit.
limitintegerNoUsers per page, up to 10,000. Without it, every user in scope comes back on one page.

Response

Returns a UserListResponse: users (UserListEntry[]), currentPage, totalPages and totalUsers.

Example Request

GET /export/users?query=alex HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns UserListResponse. This example includes every documented field.

UserListResponse · complete example
{
  "users": [
    {
      "userId": "33333333-3333-4333-8333-333333333333",
      "email": "alex@example.com",
      "isRemoved": false,
      "role": "Sales Rep",
      "name": "Alex Morgan"
    }
  ],
  "currentPage": 1,
  "totalPages": 1,
  "totalUsers": 1
}

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.

Returns 403 Forbidden when your key is limited to teams that no longer exist.

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,
      "rewindsCompleted": 3,
      "rewindAverageScore": 78.5,
      "trainingLessonsCompleted": 5,
      "trainingAverageScore": 82.25
    }
  ]
}

GET /export/teams

Lists the teams your API key can access, sorted by name, without metrics. Use it to find a teamId.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Query Parameters

ParameterTypeRequiredDescription
querystringNoPart of a team name, case-insensitive, up to 200 characters.
parentTeamIdstring (UUID)NoOnly this team's direct subteams.
pageintegerNoPage to return, from 1. Requires limit.
limitintegerNoTeams per page, up to 10,000. Without it, every team in scope comes back on one page.

Response

Returns a TeamListResponse: teams (TeamListEntry[]), currentPage, totalPages and totalTeams. Returns 403 Forbidden when your key is limited to teams that no longer exist.

Example Request

GET /export/teams?query=West HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns TeamListResponse. This example includes every documented field.

TeamListResponse · complete example
{
  "teams": [
    {
      "teamId": "44444444-4444-4444-8444-444444444444",
      "name": "West Region",
      "parentTeamId": null,
      "parentTeamName": null,
      "numberOfUsers": 12
    }
  ],
  "currentPage": 1,
  "totalPages": 1,
  "totalTeams": 1
}

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": 1,
          "totalViewTimeMs": 270000,
          "views": [
            {
              "viewId": "66666666-6666-4666-8666-666666666666",
              "viewedAt": "2026-09-02T14:30:00.000Z",
              "durationMs": 270000
            }
          ]
        }
      ],
      "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
          }
        }
      ],
      "comments": [
        {
          "commentId": "77777777-7777-4777-8777-777777777777",
          "parentId": null,
          "userId": "user-014",
          "userName": "Manager Mike",
          "content": "@Rep Rachel great discovery questions here",
          "createdAt": "2026-09-02T14:30:00.000Z",
          "attachment": {
            "type": "AUDIO",
            "mimeType": "audio/mp4",
            "transcript": "Slow down when you get to price.",
            "downloadUrl": "https://example.com/temporary-comment.m4a?signature=EXAMPLE"
          },
          "startTime": 12.5,
          "endTime": 20.25
        }
      ]
    }
  ],
  "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"
    }
  ]
}

GET /export/conversations

Lists the conversations in a date range that your API key can access, newest first. Each row is light: ID, dates, title, duration, rep and outcome. Use GET /export/conversations/{conversationId} for a conversation in full.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Query Parameters

ParameterTypeRequiredDescription
fromDatestringYesStart of the period; a UTC timestamp ending in Z. Included.
toDatestringYesEnd of the period; a UTC timestamp ending in Z, on or after fromDate. Included.
dateTypestringNotimeOfRecording (default) selects and sorts by when the conversation was recorded; processedDate by when it finished processing.
userIdsstring[]NoOnly these users' conversations, up to 100 user IDs, comma-separated or repeated. Send this or teamId, not both.
teamIdstring (UUID)NoOnly this team's users' conversations. Send this or userIds, not both.
includeSubteamsbooleanNoWith teamId, also include the users of the team's subteams. true without teamId is rejected.
querystringNoPart of the title or job number, case-insensitive, up to 200 characters. Titles usually hold the customer name.
outcomestringNoOnly conversations with this outcome as the rows show it, case-insensitive, up to 100 characters: sold matches Sold but not Not Sold.
minDurationintegerNoOnly conversations at least this many seconds long, up to 86400.
orderstringNodesc (default) for newest first, asc for oldest first.
pageintegerNoPage to return, from 1, up to 10,000. Defaults to 1.
limitintegerNoConversations per page, up to 100. Defaults to 100.

Response

Returns a ConversationListResponse: conversations (ConversationListEntry[]), currentPage, totalPages and totalConversations. This list is always paginated. Removed users' conversations are included. With teamId, returns 403 Forbidden when your key is limited to teams that no longer exist.

Example Request

GET /export/conversations?fromDate=2026-09-01T00:00:00Z&toDate=2026-09-02T00:00:00Z&query=Lee HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns ConversationListResponse. This example includes every documented field.

ConversationListResponse · complete example
{
  "conversations": [
    {
      "conversationId": "11111111-1111-4111-8111-111111111111",
      "date": "2026-09-01T14:00:00Z",
      "processedDate": "2026-09-01T15:12:00Z",
      "title": "Home estimate - Jordan Lee",
      "duration": 3240,
      "user": {
        "id": "33333333-3333-4333-8333-333333333333",
        "name": "Alex Morgan"
      },
      "outcome": "Sold"
    }
  ],
  "currentPage": 1,
  "totalPages": 1,
  "totalConversations": 1
}

GET /export/conversations/{conversationId}

Fetches a single conversation by its ID. Returns the same conversation object as POST /export/conversations above, 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 POST /export/conversations, 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": 1,
      "totalViewTimeMs": 270000,
      "views": [
        {
          "viewId": "66666666-6666-4666-8666-666666666666",
          "viewedAt": "2026-09-02T14:30:00.000Z",
          "durationMs": 270000
        }
      ]
    }
  ],
  "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
      }
    }
  ],
  "comments": [
    {
      "commentId": "77777777-7777-4777-8777-777777777777",
      "parentId": null,
      "userId": "user-014",
      "userName": "Manager Mike",
      "content": "@Rep Rachel great discovery questions here",
      "createdAt": "2026-09-02T14:30:00.000Z",
      "attachment": {
        "type": "AUDIO",
        "mimeType": "audio/mp4",
        "transcript": "Slow down when you get to price.",
        "downloadUrl": "https://example.com/temporary-comment.m4a?signature=EXAMPLE"
      },
      "startTime": 12.5,
      "endTime": 20.25
    }
  ]
}

GET /export/conversations/{conversationId}/transcript

Returns a conversation's transcript as speaker turns, in the order they were spoken.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Path Parameters

ParameterTypeRequiredDescription
conversationIdstring (UUID)YesID of the conversation.

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoPage to return, from 1. Requires limit.
limitintegerNoTurns per page, up to 10,000. Without it, the whole transcript comes back on one page.

Response

Returns a ConversationTranscriptResponse: conversationId, turns (TranscriptTurn[]), currentPage, totalPages and totalTurns. A long call can run to thousands of turns, so page with limit. A conversation with no transcript returns an empty first page. Returns 404 Not Found for a conversation that does not exist or falls outside your key's scope.

Example Request

GET /export/conversations/11111111-1111-4111-8111-111111111111/transcript?page=1&limit=100 HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns ConversationTranscriptResponse. This example includes every documented field.

ConversationTranscriptResponse · complete example
{
  "conversationId": "11111111-1111-4111-8111-111111111111",
  "turns": [
    {
      "speaker": "rep",
      "start": 12,
      "text": "Thanks for having me out today."
    }
  ],
  "currentPage": 1,
  "totalPages": 1,
  "totalTurns": 1
}

GET /export/conversations/{conversationId}/survey-results

Returns the results of chosen surveys on one conversation. Pick the surveyIds from the conversation's surveyResults.

Request Headers

HeaderTypeRequiredDescription
AuthorizationstringYesAPI key. Format: YOUR_API_KEY.

Path Parameters

ParameterTypeRequiredDescription
conversationIdstring (UUID)YesID of the conversation.

Query Parameters

ParameterTypeRequiredDescription
surveyIdsstring[]Yes1 to 10 survey IDs, comma-separated or repeated.

Response

Returns a ConversationSurveyResultsResponse: conversationId, surveyResults (SurveyConversationResult[]) and notFoundSurveyIds, the requested surveys the conversation has no results for. Returns 404 Not Found for a conversation that does not exist or falls outside your key's scope.

Example Request

GET /export/conversations/11111111-1111-4111-8111-111111111111/survey-results?surveyIds=55555555-5555-4555-8555-555555555555 HTTP/1.1
Host: customer.rillavoice.com
Authorization: YOUR_API_KEY

Example Response

Returns ConversationSurveyResultsResponse. This example includes every documented field.

ConversationSurveyResultsResponse · complete example
{
  "conversationId": "11111111-1111-4111-8111-111111111111",
  "surveyResults": [
    {
      "surveyId": "55555555-5555-4555-8555-555555555555",
      "surveyName": "Discovery quality",
      "data": {
        "next_step_confirmed": true
      }
    }
  ],
  "notFoundSurveyIds": []
}

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.
commentsComment[]All comments and replies left on the conversation, ordered by createdAt then commentId, not bounded by the request window. Private comments are left out, so it can be shorter than totalComments. See Comment.

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.
viewsViewEvent[]All recorded views by this viewer, ordered by viewedAt then viewId. Export date filters select recording or processing dates, not these events. See ViewEvent.

ViewEvent

One recorded view by the parent viewer, not a verified completed ride-along or unique viewing session. Deduplicate repeated exports by viewId. Open ViewEvent →

FieldTypeDescription
viewIdstringStable ID of the recorded view event; use to deduplicate repeated exports.
viewedAtstringWhen the view event was recorded, in ISO 8601 UTC. This is not necessarily when the viewing session started.
durationMsnumberRecorded viewing duration in milliseconds.

Comment

A comment or reply on the conversation. Private comments are not exported. Open Comment →

FieldTypeDescription
commentIdstringStable ID of the comment; use to deduplicate repeated exports.
parentIdstring | nullID of the comment this one replies to; null for a top-level comment.
userIdstring | nullRilla user ID of the author. Can belong to another organization when the conversation's rep moved organizations after the comment was posted.
userNamestring | nullAuthor's name; null when the author has no name.
contentstring | nullComment text. Tagged users and teams appear as @ and their name, or @Unknown user / @Unknown team when the user or team no longer exists. null when the comment has no text, such as a voice, video or GIF comment.
createdAtstringWhen the comment was posted, in ISO 8601 UTC.
attachmentCommentAttachment | nullThe voice or video recording on this comment; null for a comment without one, including GIF comments, whose GIF is not exported. See CommentAttachment.
startTimenumber | nullStart of the commented moment, in seconds from the start of the recording; null when the comment is not on a moment.
endTimenumber | nullEnd of the commented moment, in seconds; null when startTime is null.

CommentAttachment

The voice or video recording on a comment. Open CommentAttachment →

FieldTypeDescription
typestringAUDIO for a voice comment, VIDEO for a video.
mimeTypestring | nullMIME type of the recorded file.
transcriptstring | nullTranscript of the recording; null when it hasn't been transcribed or is silent.
downloadUrlstring | nullTemporary presigned S3 URL for the 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.

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.
rewindsCompletednumberCompleted rewind sessions created in the inclusive date window; zero when none.
rewindAverageScorenumber | nullMean feedback score of completed rewind sessions created in the inclusive date window, rounded to two decimals on a 0-100 scale; null without scores.
trainingLessonsCompletednumberCompleted training lesson sessions created in the inclusive date window, including repeats of a lesson; zero when none.
trainingAverageScorenumber | nullMean score of each team member's latest completed session per lesson created in the inclusive date window, with each user and lesson counted equally, rounded to two decimals on a 0-100 scale; null without scores.

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.
rewindsCompletednumberCompleted rewind sessions created in the inclusive date window; zero when none.
rewindAverageScorenumber | nullMean feedback score of completed rewind sessions created in the inclusive date window, rounded to two decimals on a 0-100 scale; null without scores.
trainingLessonsCompletednumberCompleted training lesson sessions created in the inclusive date window, including repeats of a lesson; zero when none.
trainingAverageScorenumber | nullMean score of each user's latest completed session per lesson created in the inclusive date window, rounded to two decimals on a 0-100 scale; null without scores.

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.

ConversationListEntry

One conversation, without its transcript, coaching results or customer. Returned inside conversations by GET /export/conversations; use GET /export/conversations/{conversationId} for the full record. Open ConversationListEntry →

FieldTypeDescription
conversationIdstringID of the conversation.
datestring | nullRecording start timestamp in ISO 8601 UTC. List selection uses inclusive date bounds.
processedDatestring | nullDate/time the conversation finished processing (ISO 8601).
titlestring | nullTitle of the conversation / appointment.
durationnumber | nullProcessed conversation duration in seconds.
userConversationListUserThe rep who recorded the conversation: { id, name }.
outcomestring | nullOutcome of the appointment.

TranscriptTurn

One speaker turn in a transcript. Open TranscriptTurn →

FieldTypeDescription
speakerstringWho spoke: the rep or the customer.
startnumberWhen the turn starts, in whole seconds from the start of the recording.
textstringWhat was said.

TeamListEntry

One team, without metrics. Returned inside teams by GET /export/teams. Open TeamListEntry →

FieldTypeDescription
teamIdstringRilla team ID.
namestring | nullName of the team.
parentTeamIdstring | nullID of the parent team. null for top-level teams.
parentTeamNamestring | nullName of the parent team. null for top-level teams.
numberOfUsersnumberActive users in this team and all its subteams, each counted once. Removed and hidden users are not counted.

UserListEntry

One user, without metrics. Returned inside users by GET /export/users. Open UserListEntry →

FieldTypeDescription
userIdstringRilla user ID.
emailstring | nullEmail address.
isRemovedboolean | nullWhether the user has been removed/deactivated.
rolestring | nullRole display name, not a fixed enum. May be null if there is no matching role.
namestring | nullFirst and last name joined by one space, with repeated spaces collapsed. Null when both are empty.

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. On the GET /export/... routes, the message is Request body failed validation even for query parameters: for example page without limit, both userIds and teamId, includeSubteams=true without teamId, fromDate after toDate, limit above 100 on GET /export/conversations, or more than 10 surveyIds.
401UnauthorizedAuthorization header missing or API key not recognized.
403ForbiddenCaller has no accessible export scope: the key is limited to teams that no longer exist. Returned by POST /export/teams, GET /export/teams, and GET /export/conversations with teamId. Create a key with current teams.
404Not FoundThe requested conversation does not exist, or is outside the scope of your API key. Returned by GET /export/conversations/{conversationId} and by the GET /export/conversations/{conversationId}/transcript and /survey-results routes.
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
}

Among the POST exports, only POST /export/conversations is paginated. POST /export/teams and POST /export/users return all results in a single response. The GET list routes page with page and limit; see each route above.

On this page