API documentation - Helpdesk Export
The All Tickets Dump API returns the ticket-level data behind Helpdesk Analytics. For each ticket you get its category, status, priority, assignee, SLA and escalation details, key dates, and the profile of the person it was raised for. Use it to feed your own data warehouse, BI tool or reporting pipeline instead of exporting from the dashboard by hand.
The API is region-specific: you call the authentication and analytics hosts of the region your workspace is hosted in.
Before you startYou need an API credential with the Read Analytics Data scope, created in Admin Console → API credentials. See API credentials.
How it works
- Create an API credential in the Admin Console with the Read Analytics Data scope.
- Generate an access token from your region's authentication URL.
- Call the analytics endpoint for your region with the access token, a date range and pagination parameters.
- Page through the results until you have fetched all tickets.
Step 1: Create an API credential
- In the Admin Console, go to API credentials.
- Click Add credentials.
- Enter an Auth name (up to 50 characters).
- In Allowed scope, select Read Analytics Data.
- Click Create credentials.
- Copy the Client ID, Client secret, Username and Password, and store them in a secure location such as a secrets manager.
Use Read Analytics Data, not Download Ticket ReportThis API requires the Read Analytics Data scope. A credential that only has the Download Ticket Report scope is rejected with an
Invalid scopeerror.
Secrets are shown only onceThe client secret and password cannot be viewed again after you leave the page — not by you and not by Leena AI support. If you lose them, create a new credential and revoke the old one.
Find your regionThe How to use this key command shown on the credential screen already contains your region's authentication URL (for example
https://us-east-1-acl.leena.ai/...). Use the same region for the analytics URL below.
Already using the All Events Dump API?You can use the same credential and access token. Both APIs need the same scope. Only the
metricIdis different.
Step 2: Choose your regional base URLs
Use the Auth URL to generate tokens and the Analytics URL to fetch data. Both must belong to the same region — a token issued in one region is not valid in another.
| Region | Auth URL | Analytics URL |
|---|---|---|
| US East (us-east-1) | https://us-east-1-acl.leena.ai | https://us-east-1-analytics-api.leena.ai |
| EU West (eu-west-1) | https://eu-west-1-acl.leena.ai | https://eu-west-1-analytics-api.leena.ai |
| EU Central (eu-central-1) | https://eu-central-1-acl.leena.ai | https://eu-central-1-analytics-api.leena.ai |
| Canada Central (canadacentral) | https://canadacentral-acl.leena.ai | https://canadacentral-analytics-api.leena.ai |
| Asia Pacific – Singapore (ap-southeast-1) | https://ap-southeast-1-acl.leena.ai | https://ap-southeast-1-analytics-api.leena.ai |
| Asia Pacific – India (ap-south-1) | https://acl.leena.ai | https://analytics-api.leena.ai |
| Qatar Central (qatarcentral) | https://qatarcentral-acl.leena.ai | https://qatarcentral-analytics-api.leena.ai |
| Middle East Central 2 (me-central2) | https://me-central2-acl.leena.ai | https://me-central2-analytics-api.leena.ai |
Dedicated instancesIf your workspace runs on a dedicated instance, your hosts use your instance name instead of a region code. Contact your Leena AI representative for the exact URLs.
In the examples below, replace <AUTH_URL> and <ANALYTICS_URL> with the values for your region.
Step 3: Generate an access token
Send a POST request to your region's token endpoint. The Authorization header is HTTP Basic auth built from clientId:clientSecret, Base64-encoded. The username and password go in the request body.
Endpoint
POST <AUTH_URL>/api/v1.0/oauth/token
Request
curl --location '<AUTH_URL>/api/v1.0/oauth/token' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <base64(clientId:clientSecret)>' \
--data '{
"username": "<username>",
"password": "<password>",
"grant_type": "password"
}'Response — 200 OK
{
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 1800,
"refresh_token": "82e2cbfa-4d1a-42fc-857e-7da2faad7b70"
}
Tokens expire after 30 minutes
expires_inis in seconds. Generate a new token, or use the refresh token withPOST <AUTH_URL>/api/v1.0/oauth/refresh-token, before the access token expires. Long exports that page through many results should check token age between requests.
For more on grant types, refresh tokens and credential rotation, see API credentials – token generation.
Step 4: Fetch all tickets
Endpoint
GET <ANALYTICS_URL>/api/analytics/query/external
Headers
| Header | Value |
|---|---|
Authorization | Bearer <access_token> |
You don't need to pass a bot ID. The workspace is identified from the access token.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
metricId | string | Yes | Fixed value: cm:allTicketsDump (URL-encoded: cm%3AallTicketsDump). |
isCustomMetric | boolean | Yes | Fixed value: true. |
responseType | string | Yes | Fixed value: table. |
from | string (ISO 8601) | Yes | Start of the date range, e.g. 2026-01-01 or 2026-01-01T00:00:00+05:30. A date without a time is read as 00:00 UTC. |
to | string (ISO 8601) | Yes | End of the date range, in the same format as from. To cover all of January, use from=2026-01-01&to=2026-02-01. |
page | integer | No | Page number, starting at 1. Default: 1. |
limit | integer | No | Number of tickets per page. Default: 10. |
timezone | string (IANA) | No | Timezone used to render date and time values, e.g. America/New_York. Default: Asia/Calcutta. |
Request
Replace <ANALYTICS_URL> with your region's Analytics URL and <access_token> with the token from Step 3.
curl --location --request GET '<ANALYTICS_URL>/api/analytics/query/external?metricId=cm%3AallTicketsDump&isCustomMetric=true&responseType=table&from=2026-01-01&to=2026-02-01&page=1&limit=100' \
--header 'Authorization: Bearer <access_token>'For example, for a workspace in US East (us-east-1):
curl --location --request GET 'https://us-east-1-analytics-api.leena.ai/api/analytics/query/external?metricId=cm%3AallTicketsDump&isCustomMetric=true&responseType=table&from=2026-01-01&to=2026-02-01&page=1&limit=100' \
--header 'Authorization: Bearer <access_token>'
Import into PostmanYou can paste either command into Postman with Import → Raw text. Postman sets up the request, query parameters and header for you.
Response — 200 OK
The example below shows the response structure, with the columns and tableData arrays shortened.
{
"isSuccess": true,
"result": {
"current": 1,
"page": 1,
"limit": 100,
"total": 8421,
"isManageColumnsEnabled": true,
"columns": [
{
"key": "<column key>",
"label": "Ticket Id",
"type": "string",
"sortable": true,
"isDynamicColumn": false,
"isMandatory": true,
"isVisible": true,
"sticky": false
}
],
"tableData": [
{ "<column key>": "<value>" }
]
}
}| Field | Type | Description |
|---|---|---|
isSuccess | boolean | true if the query succeeded. |
result.tableData | array | The tickets on this page. Each element is one ticket, with one property for each column in result.columns. |
result.columns | array | Column metadata. Each entry's key is the property name used in tableData, and label is its display name. Use label to match a key to the columns described in Response columns. |
result.total | integer | Total number of tickets across all pages for the date range. |
result.page | integer | Page number returned. result.current holds the same value. |
result.limit | integer | Page size returned. |
result.isManageColumnsEnabled | boolean | Dashboard display setting. Can be ignored. |
Read values as stringsValues in
tableDataare returned as display-formatted strings. Empty fields contain"". Thetypeproperty inresult.columnsdescribes how the dashboard renders a column, not the data type of its values. Don't use it to parse the data.
Response columns
Each ticket in tableData contains the following columns. The labels below match label in result.columns. Read each column's key from result.columns and use it to read values from the rows.
Ticket fields
These columns are always present.
| # | Label | Description |
|---|---|---|
| 1 | Ticket Id | Unique ID of the ticket, as shown in Helpdesk. Use it as the primary key when storing or de-duplicating tickets. |
| 2 | Instance | The Helpdesk instance (department) the ticket belongs to. Returned as the instance's display name. |
| 3 | Category | Ticket category. |
| 4 | Sub Category | Ticket sub-category. |
| 5 | Request Type | Type of request. |
| 6 | Status | Current status of the ticket, e.g. open, resolved or closed. |
| 7 | Priority | Priority assigned to the ticket. |
| 8 | Created On | Date and time the ticket was created. |
| 9 | Closing Date | Date and time the ticket was closed. Empty if the ticket is still open. |
| 10 | Reopen Datetime | Date and time the ticket was last reopened. Empty if it was never reopened. |
| 11 | Reopen Count | Number of times the ticket has been reopened. |
| 12 | Assignee Name | Agent the ticket is assigned to. |
| 13 | Assignee Email | Email address of the assignee. |
| 14 | Assignee Group | Group or queue the ticket is assigned to. |
| 15 | Raised For Name | Person the ticket was raised for. |
| 16 | Raised For Email | Email address of the person the ticket was raised for. |
| 17 | Raised For Employee Id | Employee ID of the person the ticket was raised for. |
| 18 | Raised By Name | Person who raised the ticket. Differs from Raised For when someone raises a ticket on another person's behalf. |
| 19 | Raised By Email | Email address of the person who raised the ticket. |
| 20 | Raised By Employee Id | Employee ID of the person who raised the ticket. |
| 21 | Intake Channel | Channel the ticket was raised through, e.g. Web, Microsoft Teams, Email. |
| 22 | SLA Level | SLA tier that applies to the ticket. |
| 23 | Is Response Escalated | Whether the ticket breached its response SLA and was escalated. |
| 24 | Is Resolution Escalated | Whether the ticket breached its resolution SLA and was escalated. |
| 25 | Agent Comments Count | Number of comments agents added to the ticket. |
| 26 | Rating | Feedback rating the requester gave on the ticket. Empty if no rating was given. |
| 27 | Deleted | Whether the ticket has been deleted. |
User profile fields
After the ticket fields, each ticket includes profile fields for the person the ticket was raised for. Which fields appear depends on your workspace's user profile configuration, so the set varies between workspaces. For example:
| Label | Description |
|---|---|
| Country | User's country. |
| State | User's state or region. |
| Location | User's work location. |
| Business Unit | User's business unit. |
| Business Segment | User's business segment. |
| Manager Name | Name of the user's manager. |
| Management Chain Level 03 – 05 | The user's management hierarchy at levels 3, 4 and 5. |
| Termination Status | Whether the user is active or has left the organization. |
| VIP Membership | Whether the user is marked as a VIP. |
Read result.columns to get the exact list of fields for your workspace. Fields that aren't filled in for a user are returned as "".
For how ticket metrics are calculated in the dashboard, see Ticket Volume Trend.
Paginating through results
Results are paginated. To fetch all tickets for a date range:
- Request
page=1with your chosenlimit. - Read
result.totaland calculate the number of pages:ceil(total / limit). - Request each following page by incrementing
pageuntil you have fetched all pages.
Best practices
- Pull data in smaller date windows (for example one week or one month at a time) for high-volume workspaces. Large ranges and page sizes increase response time.
- Tickets change after they're created: their status, assignee, SLA escalation and closing date are updated over time. For scheduled syncs, re-fetch recent windows and update existing rows by Ticket Id instead of only appending new ones.
- Responses are not cached, so every call returns the latest processed data. Recent ticket updates can take some time to be processed before they appear.
- Store credentials in a secrets manager. Don't share them in documents, email or chat.
Errors
| Status | Message | What to do |
|---|---|---|
401 | You are not authorized to perform this action | The Authorization header is missing, or the token is invalid or expired. Generate a new token. Check that the token and analytics URLs are from the same region. |
401 | Invalid authorization header. Must be a bearer token | Send the header as Authorization: Bearer <access_token>. |
401 | You are not authorized to perform this action. Invalid scope. | The credential doesn't have the Read Analytics Data scope. Create a credential with that scope. |
401 (token endpoint) | — | Wrong client ID, client secret, username or password, or the credential has been revoked. |
500 | Metric not found | Check that metricId=cm:allTicketsDump and isCustomMetric=true are both set. |
Updated about 1 hour ago
