Rilla
Custom CRM APIData Export APIWebhooksDeep Links

Data Export API (exporting from Rilla)

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

Obtain your API key from your Rilla account manager or customer success manager and store it securely.

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

Reach out to your Rilla account manager or customer success manager to get an API key provisioned for your organization. Each key is scoped to a single Rilla organization.

On every request, Rilla validates that the API key exists and maps to an active organization. If the key is missing or unrecognized, the API returns 401 Unauthorized.

Keep your key secure

API keys grant read access to your organization's analytics data. 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

{
  "conversationId": "f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f",
  "recordingId": "rec-7c2f4a90",
  "date": "2024-03-05T14:00:00Z",
  "processedDate": "2024-03-05T15:12:00Z",
  "title": "Home Estimate - John Doe",
  "duration": 3240,
  "crmEventID": "evt-90817",
  "user": {
    "id": "user-001",
    "name": "Jane Smith",
    "email": "rep@yourcompany.com"
  },
  "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.rillavoice.com/conversations/single?id=f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f",
  "viewers": [
    {
      "userId": "user-014",
      "name": "Manager Mike",
      "viewCount": 2,
      "totalViewTimeMs": 540000
    }
  ],
  "checklists": [
    {
      "name": "Discovery",
      "checklistName": "Discovery",
      "score": 3,
      "checklistScore": 3,
      "denominator": 5,
      "checklistDenominator": 5,
      "trackerData": [
        {
          "name": "Asked about budget",
          "trackerName": "Asked about budget",
          "isHit": true,
          "trackerIsHit": true,
          "aiScore": 0.92,
          "trackerAiScore": 0.92
        }
      ]
    }
  ],
  "aiTrackers": [
    {
      "checklistName": "Discovery",
      "trackerName": "Asked about budget",
      "isHit": true,
      "aiScore": 0.92
    }
  ],
  "customFields": { "leadSource": "Facebook" },
  "surveyResults": [],
  "audioUrl": "<presigned-s3-url>",
  "transcriptUrl": "<presigned-s3-url>"
}

POST /export/conversations

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

Request Headers

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

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range (ISO 8601).
toDatestringYesEnd of the time range (ISO 8601).
dateTypestringNotimeOfRecording (default) or processedDate.
pagenumberNo1-based page index. Defaults to 1.
limitnumberNoConversations per page. Max 50. Defaults to 50.
usersstring[]NoFilter by user emails. If omitted, all users are returned.

Response

FieldTypeDescription
currentPagenumberThe current page number.
totalPagesnumberTotal number of pages.
totalConversationsnumberTotal conversations for the date range.
conversationsarrayConversation objects. See Data Models.

Example Request

{
  "fromDate": "2024-03-01T00:00:00Z",
  "toDate": "2024-04-01T00:00:00Z",
  "dateType": "timeOfRecording",
  "page": 1,
  "limit": 50
}

Example Response

{
  "currentPage": 1,
  "totalPages": 4,
  "totalConversations": 187,
  "conversations": [
    {
      "conversationId": "f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f",
      "recordingId": "rec-7c2f4a90",
      "date": "2024-03-05T14:00:00Z",
      "processedDate": "2024-03-05T15:12:00Z",
      "title": "Home Estimate - John Doe",
      "duration": 3240,
      "crmEventID": "evt-90817",
      "user": {
        "id": "user-001",
        "name": "Jane Smith",
        "email": "rep@yourcompany.com"
      },
      "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.rillavoice.com/conversations/single?id=f1a3e9d8-2b46-4c1a-9c7e-7e4a18d2c93f",
      "viewers": [
        {
          "userId": "user-014",
          "name": "Manager Mike",
          "viewCount": 2,
          "totalViewTimeMs": 540000
        }
      ],
      "checklists": [
        {
          "name": "Discovery",
          "checklistName": "Discovery",
          "score": 3,
          "checklistScore": 3,
          "denominator": 5,
          "checklistDenominator": 5,
          "trackerData": [
            {
              "name": "Asked about budget",
              "trackerName": "Asked about budget",
              "isHit": true,
              "trackerIsHit": true,
              "aiScore": 0.92,
              "trackerAiScore": 0.92
            }
          ]
        }
      ],
      "aiTrackers": [
        {
          "checklistName": "Discovery",
          "trackerName": "Asked about budget",
          "isHit": true,
          "aiScore": 0.92
        }
      ],
      "customFields": { "leadSource": "Facebook" },
      "surveyResults": [],
      "audioUrl": "<presigned-s3-url>",
      "transcriptUrl": "<presigned-s3-url>"
    }
  ]
}

POST /export/teams

Returns all teams in your organization along with their analytics data.

Request Headers

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

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range (ISO 8601).
toDatestringYesEnd of the time range (ISO 8601).
includeSubteamsbooleanNoWhether to include sub-teams. Defaults to false.

Response

FieldTypeDescription
teamsarrayArray of team objects. See Data Models.

Example Request

{
  "fromDate": "2024-03-01T00:00:00Z",
  "toDate": "2024-04-01T00:00:00Z",
  "includeSubteams": true
}

Example Response

{
  "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 all users in your organization along with their analytics data.

Request Headers

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

Request Body

FieldTypeRequiredDescription
fromDatestringYesBeginning of the time range (ISO 8601).
toDatestringYesEnd of the time range (ISO 8601).
usersstring[]NoFilter by user emails. If omitted, all users are returned.

Response

FieldTypeDescription
usersarrayArray of user objects. See Data Models.

Example Request

{
  "fromDate": "2024-03-01T00:00:00Z",
  "toDate": "2024-04-01T00:00:00Z",
  "users": ["rep1@yourcompany.com", "rep2@yourcompany.com"]
}

Example Response

{
  "users": [
    {
      "userId": "user-001",
      "name": "Jane Smith",
      "email": "rep1@yourcompany.com",
      "accountSetUp": true,
      "isRemoved": false,
      "role": "rep",
      "teams": [{ "teamId": "team-42", "name": "West Region" }],
      "timeOfFirstRecording": "2023-11-02T16:20: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": "2024-03-20T13: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": 1.46,
      "liveCoaching": {
        "sessionsHosted": 2,
        "viewEventsReceived": 18,
        "uniqueViewers": 5,
        "viewDurationMinutes": 64,
        "commentsReceived": 7,
        "uniqueCommenters": 3,
        "moneySaved": 1200,
        "lastCoachedAt": "2024-03-18T10:30:00Z"
      }
    }
  ]
}

Data Models

ConversationsExport

FieldTypeDescription
conversationIdstringID of the conversation.
recordingIdstringID of the underlying recording.
datestringDate/time the conversation was recorded (ISO 8601).
processedDatestringDate/time the conversation finished processing (ISO 8601).
titlestringTitle of the conversation / appointment.
durationnumberDuration in seconds.
crmEventIDstringID of the associated CRM / calendar event.
userobjectThe rep who recorded the conversation: { id, name, email }.
jobNumberstringJob number from the CRM / calendar event.
stLinkstringDeep link to the job in the connected CRM (e.g. ServiceTitan).
totalSoldnumberTotal amount sold on the job.
outcomestringOutcome of the appointment.
jobSummarystringAI-generated summary of the job.
customSummarystringAdmin summary / custom insights in your organization's format.
repSpeedWPMnumberRep speaking speed, in words per minute.
repTalkRationumberFraction of time the rep was talking (01).
longestRepMonologuenumberLongest uninterrupted rep monologue, in seconds.
longestCustomerMonologuenumberLongest uninterrupted customer monologue, in seconds.
totalCommentsnumberNumber of comments left on the conversation.
rillaUrlstringLink to view the conversation in the Rilla web app.
viewersarrayUsers who viewed the conversation. See Viewer.
checklistsarrayCoaching checklists scored for the conversation. Each checklist contains its trackers. See Checklist.
aiTrackersarrayFlattened list of every tracker across all checklists. See AiTracker.
customFieldsobject | nullCustom fields from the calendar event. Keys and values are customer-defined. null if none are set.
surveyResultsarraySurvey results associated with the conversation. Empty array if the conversation has none.
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.
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.

Viewer

A user who viewed the conversation. Returned in the viewers array of each ConversationsExport.

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

A coaching checklist scored against the conversation. Returned in the checklists array of each ConversationsExport.

FieldTypeDescription
checklistNamestringName of the checklist.
checklistScorenumberNumber of trackers hit on this checklist.
checklistDenominatornumberTotal number of trackers in the checklist.
trackerDataarrayThe individual trackers evaluated for this checklist. See Tracker.

Each checklist is also returned with the unprefixed aliases name, score, and denominator, which carry the same values as checklistName, checklistScore, and checklistDenominator. Prefer the prefixed fields; the aliases are retained for backward compatibility.

Tracker

A single tracker within a Checklist. Returned in the trackerData array.

FieldTypeDescription
trackerNamestringName of the tracker.
trackerIsHitbooleanWhether the tracker was hit during the conversation.
trackerAiScorenumberAI-generated score for the tracker.

Each tracker is also returned with the unprefixed aliases name, isHit, and aiScore, which carry the same values as trackerName, trackerIsHit, and trackerAiScore. Prefer the prefixed fields; the aliases are retained for backward compatibility.

AiTracker

A single tracker in the flattened aiTrackers array of each ConversationsExport. Unlike trackerData, these are not nested under a checklist — each entry carries its own checklistName instead.

FieldTypeDescription
checklistNamestringName of the checklist this tracker belongs to.
trackerNamestringName of the tracker.
isHitbooleanWhether the tracker was hit during the conversation.
aiScorenumberAI-generated score for the tracker.

Team

Returned in the teams array. All usage metrics are calculated for the date range provided in the request.

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.
averageConversationDurationnumberAverage conversation duration, in seconds.
averageConversationLengthnumberAverage conversation length, in seconds.
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.
conversationsRecordednumberConversations recorded by the team.
conversationsViewednumberConversations viewed by team members.
longestCustomerMonologueAveragenumberAverage longest customer monologue, in seconds.
longestMonologueAveragenumberAverage longest rep monologue, in seconds.
patienceAveragenumberAverage patience score.
recordingCompliancenumberFraction of appointments that were recorded (01).
ridealongsReceivednumberRide-alongs received.
scorecardsGivennumberScorecards given.
scorecardsReceivednumberScorecards received.
talkRatioAveragenumberAverage rep talk ratio (01).
totalAppointmentsnumberTotal appointments in the range.
totalUsersWhoRecordednumberNumber of team members who recorded at least one conversation.
totalUsersnumberTotal number of users in the team.

User

Returned in the users array. Usage metrics are calculated for the date range provided in the request, and may be null when no data exists for the user in that range.

FieldTypeDescription
userIdstringRilla user ID.
namestringFull name.
emailstringEmail address.
accountSetUpbooleanWhether the user has completed account setup.
isRemovedbooleanWhether the user has been removed/deactivated.
rolestringThe user's role.
teamsarrayTeams the user belongs to: { teamId, name }[].
timeOfFirstRecordingstring | nullTimestamp of the user's first recording (ISO 8601), or null.
hasVoiceIdbooleanWhether the user has an enrolled voice ID.
analyticsViewednumberNumber of analytics views.
appointmentsRecordednumber | nullAppointments recorded.
averageConversationDurationnumber | nullAverage conversation duration, in seconds.
averageConversationLengthnumber | nullAverage conversation length, in seconds.
averageScriptCompliancenumber | nullAverage script compliance (01).
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.
conversationsRecordednumberConversations recorded.
conversationsViewednumberConversations viewed.
conversationViewDurationnumberTotal conversation view duration, in seconds.
lastRidealongAtstring | nullTimestamp of the user's last ride-along (ISO 8601), or null.
longestMonologueAveragenumber | nullAverage longest rep monologue, in seconds.
longestCustomerMonologueAveragenumber | nullAverage longest customer monologue, in seconds.
patienceAveragenumber | nullAverage patience score.
percentageOfRepsWithCommentsGivennumber | nullFor managers: fraction of reps they gave comments to.
recordingCompliancenumber | nullFraction of appointments recorded (01).
ridealongsReceivednumberRide-alongs received.
scorecardsReceivednumberScorecards received.
scorecardsGivennumberScorecards given.
talkRatioAveragenumber | nullAverage talk ratio (01).
totalAppointmentsnumberTotal appointments in the range.
totalEndOfRidealongsReachednumberRide-alongs completed through to the end.
totalRidealongsCompletednumberRide-alongs completed.
viewedRecordedRationumber | nullRatio of conversations viewed to recorded.
liveCoachingobjectLive coaching metrics. See LiveCoaching.

LiveCoaching

Live coaching metrics for a User, returned in the liveCoaching object.

FieldTypeDescription
sessionsHostednumberLive coaching sessions hosted.
viewEventsReceivednumberView events received on hosted sessions.
uniqueViewersnumberUnique viewers across hosted sessions.
viewDurationMinutesnumberTotal view duration, in minutes.
commentsReceivednumberComments received during live coaching.
uniqueCommentersnumberUnique commenters during live coaching.
moneySavednumberEstimated money saved through live coaching.
lastCoachedAtstring | nullTimestamp of the last live coaching session (ISO 8601), or null.

Analytics and usage metrics are calculated for the date range provided in the request.

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)
        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 }),
    })
    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": "2024-03-01T00:00:00Z", "toDate": "2024-04-01T00: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": "2024-03-01T00:00:00Z",
    "toDate": "2024-04-01T00: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: '2024-03-01T00:00:00Z',
    toDate: '2024-04-01T00: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": "2024-03-01T00:00:00Z", "toDate": "2024-04-01T00: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": "2024-03-01T00:00:00Z",
    "toDate": "2024-04-01T00: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: '2024-03-01T00:00:00Z',
    toDate: '2024-04-01T00:00:00Z',
  }),
})
curl -X POST https://customer.rillavoice.com/export/users \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fromDate": "2024-03-01T00:00:00Z", "toDate": "2024-04-01T00:00:00Z"}'

Error Codes

The API returns standard HTTP status codes. On error, the response body is a plain string describing the issue.

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.

Infrastructure-level Limits

Requests pass through AWS API Gateway. The following defaults apply:

  • Steady-state requests: 10,000 req/s per account (regional)
  • Burst limit: 5,000 requests across all APIs

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
page11-based page index.
limit5050Conversations per page.

Response Fields

FieldDescription
currentPageThe page number of the current response.
totalPagesTotal number of pages for the date range.
totalConversationsTotal conversations across all pages.
conversationsArray of conversation objects on this page.

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 }),
    })
    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.