Using the AI Agents Data Export API
The Data Export API lets you securely extract conversation data and metadata from your AI agents. Use this API to export transcripts and analytics for integration with your data warehouse, reporting tools, or other applications.
This article guides you through the end-to-end process of exporting conversation data from AI agents using the data export API.
You’ll learn how to:
- Locate your organization id and generate an API token so you can authenticate requests securely.
- Make a request to the data export API to get signed download links for your conversation data for a specific day.
- Download and manage data files using time-limited URLs provided by the API.
- Understand the format and schema of exported files so you can easily integrate the data into your analytics pipeline or reporting tools.
- Explore example metrics.
Getting the organization id
Every API request must include your organization id to ensure data is exported from the correct account. This unique identifier allows the API to authenticate your request and target the right dataset for your export. Only Zendesk admins can view and copy the organization id.
-
In the left sidebar of AI agents - Advanced, click Organization management.
Note: If you purchased AI agents - Advanced before October 7, 2024, click User management > Organization management instead.
-
Click your organization to open its profile.
-
Find your organization id in the URL in your browser.
Example:https://dashboard.ultimate.ai/admin/organizations/77m57af6811115b53172431s
Generating an API token
To securely access data via the Data Export API, you’ll need an API token. This token acts as your authentication credential and is required in all API requests. Only admins can generate new API tokens for your organization.
-
In the left sidebar of AI agents - Advanced, click Organization management.
Note: If you purchased AI agents - Advanced before October 7, 2024, click User management > Organization management instead.
-
Click your organization to open its profile.
-
Select the API key tab.
-
Click Generate.
-
Click Save.
-
Copy the key and store it in a secure location.
About the API
The data export API allows you to programmatically retrieve conversation transcripts and analytics for your AI agent. Export files are generated once every day, updated at midnight UTC (Coordinated Universal Time). The export process can take some time to complete, especially for large volumes of data. For best results, schedule your data imports or automation to run later in the UTC morning, so that the export for the previous day is finalized and ready for download.
Choose the endpoint that matches your data's region:
- EU:
POST https://api.ultimate.ai/data-export/v3/get-signed-urls - US:
POST https://api.us.ultimate.ai/data-export/v3/get-signed-urls
Request
Include your authentication and organization details as headers, and specify the export date you want in the request body.
Headers:
| Name | Required | Type |
|---|---|---|
| botId | true | string |
| organizationId | true | string |
| authorization | true | string |
Body:
| Name | Required | Type |
|---|---|---|
| date | true | ISO date string |
| ttl | false | integer |
Response
The API responds with links to one or more export files for the requested date:
| HTTP code | Response example |
|---|---|
| 200 | { "date": "string", "urls": [ "string" ] } |
| 401 | Unauthorized |
| 500 | Internal Server Error |
Note the following:
- The URL to the file expires after one day from the request date. To get a valid link, make the API call again.
- You can request data as far back as January 1, 2024. For older data, contact Zendesk customer support.
File schema
The output of the API is a JSON document with all the conversations for a given day, following the structure outlined here:
- Each file is a list of JSON objects (one per conversation).
- The file follows the naming convention
conversation_<bot-id>_<date>_000000000000.json
| Property | Type | Description |
|---|---|---|
| bot_id | string | Bot's unique id |
| bot_name | string | Bot's name |
| conversation_id | string | Generated conversation id |
| platform_conversation_id | string | CRM-specific id |
| conversation_start_time | string | Conversation start time (UTC) |
| conversation_end_time | string | Conversation end time (UTC) |
| conversation_type | string | Reply type. Possible values are "Use case", "Knowledge", "Hybrid", "Others" |
| language | string | Language of the conversation |
| channel | string | Channel. Possible values are "messaging", "email" |
| labels | array of strings | List of all the labels associated with the conversation |
| segments | array of strings | List of all the segments identified in the conversation. See Creating segments |
| conversations_data | string | Session parameters and BSAT score, stored as a JSON object. See BSAT Score Values |
| test_mode | boolean | If true, the conversation is a test |
| conversation_status | string | Resolution of the conversation. For example, "bot_handled" |
| automated_resolution | string | Outcome of evaluation as automated resolution. See About automated resolutions for AI agents |
| automated_resolution_reasoning | string | Reasoning for automated resolution |
| last_resolution | string | Final resolution of the conversation. Possible values are "informed", "resolved", "escalated" |
| triggered_replies | array of strings | Details relating to a reply. This includes information like reply_id, language, reply_name, reply_type, intend_id |
| triggered_procedures | array of strings | Procedures triggered like procedure_id, intent_id, use_case_name. This section is empty for zero-trainign AI agents or when there are no procedures triggered |
| triggered_use_cases | array of strings | Flag for dialogue or procedure use case configuration |
| has_knowledge_response_attempt | boolean | If true, the conversation has at least one Knowledge answer |
| knowledge_notUnderstood_count | string | Number of not-understood messages in Knowledge conversations. For agentic Knowledge responses, this may include follow-up questions where the AI agent did not match the question to an appropriate knowledge source to generate a response |
| knowledge_responseGenerated_count | string | Number of generated Knowledge responses |
| knowledge_errorOccurred_count | string | Number of error occurred messages in Knowledge conversations |
| knowledge_escalationRequired_count | string | Number of escalationRequired status in Knowledge responses. This status is applicable only for generative reply-handled Knowledge responses |
| knowledge_fallback_count | string | Number of fallback messages in Knowledge conversation |
| knowledge_sources | array of strings | List of article title and URL used in the conversation |
| bot_messages_count | string | Number of AI agent messages |
| visitor_messages_count | string | Number of customer messages |
| not_understood_messages_count | string | Number of not understood messages |
BSAT Score Values
-1: User was offered BSAT but did not leave a responseNULL: User was not offered BSAT
Response example
The response of the API call is an url link to a file in a google storage bucket that you can access with a GET request:
{"date": "2024-05-03","urls": ["https://storage.googleapis.com/production-eu-ultimateai-backend-data-export/files/your_bot_id/2024-05-0/conversation_your_bot_id_20240503_000000000000.json…"]}
Each conversation in the exported file has the following format:
{"bot_id": "98174e8d635471c383b9ec7b","bot_name": "INDUSTRY DEMO (Travel) - SunCo","conversation_id": "67bc4129-6609-4v67-869d-db1d0186d1d8","platform_conversation_id": "57459bd72555b8452378f693","conversation_start_time": "2024-05-03T08:10:01.211+00:00","conversation_end_time": "2024-05-03T08:10:25.744+00:00","language": "eng","channel": "chat","labels": ["web", "API:getBookingDetails-Success"],"conversations_data": {"bsatScore": 5,"convoId": "552cd72556e8452378d344","email": null,"location": null,"confidence_score": 95,"lastDetectedLanguage": "eng","lastDetectedSentiment": "neutral","usedLanguage": "eng","channel": "web","booking": [{"country": "Spain","url": "https://cdn.pixabay.com/photo/2015/05/05/01/10/house-753270__340.jpg","location": "41.3485806,1.9787689","city": "Barcelona","numOfGuests": 4,"days": 4,"arrivalDate": "12-12-2022"}],"city": "Barcelona","manageBooking": "possible"},"test_mode": false,"conversation_status": "botHandled","last_resolution": "resolved","triggered_replies": [{"reply_timestamp": "2024-05-03T08:10:02.991+00:00","reply_id": "53628e8e55b4f2459bcb2e72","reply_language": "eng","reply_name": "Greeting","reply_type": "normal","intent_id": "64628b8e55e4f2459bcb2e68"}],"triggered_intent_replies": [{"intent_timestamp": "2024-05-03T08:10:02.991+00:00","intent_id": "53628e8e55b4f2459bcb2e72","intent_name": "Greeting","not_meaningful": true}],"is_llm_conversation": false,"bot_messages_count": "7","customer_messages_count": "4","not_understood_messages_count": "0"}
Popular metrics
Congratulations! You have successfully exported the AI agent's conversation data. Here are some suggestions to start your exploration of the exported files:
AI agent metrics
SELECT-- Total conversationscount(distinct conversation_id) total_conversations,-- AI agent handled ratecount(distinct case when conversation_status = 'botHandled' then conversation_id end) bot_handled_conversations,count(distinct case when conversation_status = 'botHandled' then conversation_id end)/count(distinct conversation_id) bot_handled_rate,-- Deflection ratecount(distinct case when conversation_status not in ('email', 'agent', 'customEscalation') then conversation_id end)/count(distinct conversation_id) deflection_rate,-- Escalation ratecount(distinct case when conversation_status in ('email', 'agent', 'customEscalation') then conversation_id end)/count(distinct conversation_id) escalation_rate,-- Failed escalation ratecount(distinct case when conversation_status = 'failedEscalation' then conversation_id end)/count(distinct conversation_id) failed_escalation_rate,-- Message understood rate(sum(customer_messages_count)-sum(not_understood_messages_count))/sum(customer_messages_count) messages_understood_rateFROM TABLE
First or last intent from a conversation
selectdistinct conversation_id,triggered_use_cases[safe_offset(0)].intent_name first_intent,array_reverse(triggered_intent_replies)[safe_offset(0)].intent_name last_intentFROM TABLE
FAQs
Are the exported files immutable or do they change over time?
Exported files are immutable and do not need to be reimported, making your BI pipeline less error-prone.
Why are there differences in conversation counts between exported conversations and AI agent Summary analytics for a specific date?
Exported data for a specific date only includes conversations that ended on that date, while AI agent Summary analytics includes any conversation in any state. This provides immutability and avoids duplicate data.
How can I match AI agent summary numbers with exported files?
Ingest files generated for both day x and day x+1. This ensures you count all conversations for date x, even if some ended the next day.
Why do exported conversation counts differ from Conversation Logs?
Exported data only covers conversations that ended on the given date, while Conversation Logs include all ongoing conversations for real-time debugging.
Does a conversation include all replies triggered, even if those replies were made on previous days?
Yes, included conversations capture all data, even if events occurred earlier.
Will conversations as part of the suggestion engine appear in the export?
Yes. Unlike in the AI agent summary dashboard, suggestion engine conversations are available in the exported data. To match dashboard results, filter by "bot_messages_count > 0".