Using the Data Export API for AI agents

Zendesk AI agents are AI-powered chatbots that interact with your customers on messaging, email (including API and web form), and voice (EAP) channels. They can have conversations with customers and perform actions in authorized systems autonomously, automating and resolving issues so that your human agents can focus on more complex work.

What's my plan?

All Suites | Team, Growth, Professional, Enterprise, or Enterprise Plus

Support | Team, Professional, or Enterprise

Our Data Export API serves as the key to unlocking the full potential of your AI agent, empowering you to export conversation data and integrate it across diverse platforms and applications.

Whether you're a developer, business analyst, or IT professional, our API provides a streamlined and secure solution to extract valuable insights and conversation metadata, enabling you to drive innovation, make informed decisions, and propel your organization to new heights.

This article contains the following topics:

Get the organization ID

Generate an API token

About the API

File schema

Response example

Popular metrics

FAQs

Get the organization ID

This step can only be done by users with an admin role

In the left sidebar, 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:

/admin/organizations/77m57af6811115b53172431s

Generate an API token

Generating a Token can only be done by users with an admin role

In the left sidebar, 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 keep it safe.

Once you exit the Organization management page, you won't have access to the token. If you have lost the token you generated before, you can simply revoke it by clicking on the Regenerate button. The validity of the old token will be revoked and you can use the newly generated token.

About the API

The Data Export API is updated once per day, at midnight UTC (Coordinated Universal Time). This update process can run for a while, so running the import early morning UTC time will help ensure that the data is already there.

Send requests to https://{subdomain}.zendesk.com/ai-agents/api/data-export/v3/get-signed-urls

Header

name

required

type

botId

true

string

organizationId

true

string

authorization

true

string

Body

name

required

type

date

true

ISO date string

Response

HTTP code

response

200

{ "date": "string", "urls": [ "string" ] }

401

Unauthorized

500

Internal Server Error

Note:

The URL to the file expires after one day from the request date. To get a valid link, an API call can be performed once again.

You can request data going as far back as January 1, 2024. If you need older data, contact Zendesk customer support for help.

File schema

The output of the API is a JSON document with all the conversations for a given day, following the structure outlined here:

The file is a list of JSON objects where each object is a conversation

The file will have the name convention conversation_bot-id_date_000000000000.json

Property | Description | Type

"bot_id"

Bot's unique ID

"bot_id": {
"type": "string"
},

"bot_name"

Bot's name

"bot_name": {
"type": "string"
},

"conversation_id"

Generated conversation ID

"conversation_id": {
"type": "string"
},

"platform_conversation_id"

CRM-specific ID

"platform_conversation_id": {
"type": "string"
},

"conversation_start_time"

Date and time of when the conversation started based on UTC timezone

"conversation_start_time": {
"type": "string"
},

"conversation_end_time"

Date and time of when the conversation ended based on UTC timezone

"conversation_end_time": {
"type": "string"
},

"conversation_type"

Reply type that has been identified in the conversation. Possible values include Use case, Knowledge, Hybrid, and Others.

"conversation_type": {
"type": "string"
},

"language"

Language of the conversation

"language": {
"type": "string"
},

"channel"

Channel of the conversation. Either messaging or email

"channel": {
"type": "string"
},

"labels"

List of all the labels associated with the conversation

"labels": {
"type": "array",
"items": {
"type": "string"
}
},

"segments"

List of all the segments identified in the conversation. Learn more about segments.

"segments": {
"type": "array",
"items": {
"type": "string"
}
},

"conversations_data"

The session parameters are associated with the conversations. It is a list of the parameter’s key where it had a value. The undefined keys won’t be in this list

Note:

even though it is stored as a string, the “conversations_data” contains another JSON object

the BSAT score is provided in the conversations data object

BSAT Score Values

-1 = User was offered BSAT but did not leave a response

NULL = User was not offered BSAT

Example:

"conversations_data": {
"parameter1": true,
"parameter2": "parameter_value",
"parameter3": "1234"
},

"conversations_data": {
"type": "string"
},

"test_mode"

A flag to identify if the conversation is a test conversation

"test_mode": {
"type": "boolean"
},

"conversation_status"

Resolution of the conversation Example: bot_handled

"conversation_status": {
"type": "string"
},

"automated_resolution"

The outcome of evaluating the conversation as an automated resolution. Learn more about how automated resolutions are calculated.

"automated_resolutions": {
"type": "string"
},

"automated_resolution_reasoning"

The reasoning used to determine why a conversation has been marked as automatically resolved.

"automated_resolution_reasoning": {
"type": "string"
},

"last_resolution"

This is the final resolution of the conversation. It could be informed, resolved, escalated, or undefined.

We will be removing this feature at a date to be determined. Learn more about the upcoming feature removal.

"last_resolution": {
"type": "string"
},

"triggered_replies"

The details relating to a reply. This includes information like reply_id, language, reply_name, reply_type, intent_id.

"triggered_replies": {
"type": "array",
"items": {
"type": "string"
}
},

"triggered_procedures"

This includes information like procedure_id, intent_id, use_case_name.

This section is empty for zero-training AI agents or when there are no procedures triggered.

"triggered_procedures": {
"type": "array",
"items": {
"type": "string"
}
},

"triggered_use_cases"

A flag to identify if the use case is configured as a dialogue or a procedure.

"triggered_use_cases": {
"type": "array",
"items": {
"type": "string"
}
},

"has_knowledge_response_attempt"

A flag to identify if the conversation is a Knowledge conversation (has at least one Knowledge answer), regardless of whether the Knowledge answer was understood, a technical error occurred, was small talk, etc.

"has_knowledge_response_attempt": {
"type": "boolean"
},

"knowledge_notUnderstood_count"

The count of not-understood messages in the Knowledge conversation. 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_notUnderstood_count": {
"type": "string"
},

"knowledge_responseGenerated_count"

The count of response-generated messages in the Knowledge conversation.

"knowledge_responseGenerated_count": {
"type": "string"
},

"knowledge_errorOccurred_count"

The count of error occurred messages in the Knowledge conversation.

"knowledge_errorOccurred_count": {
"type": "string"
},

"knowledge_escalationRequired_count"

The count of escalationRequired messages in the Knowledge conversation. This status is applicable only for generative reply-handled Knowledge responses.

"knowledge_escalationRequired_count": {
"type": "string"
},

"knowledge_fallback_count"

The count of fallback messages in the Knowledge conversation.

"knowledge_fallback_count": {
"type": "string"
},

"knowledge_sources"

A list of the knowledge base type, article title, and URL used in the conversation.

"knowledge_sources": {
"type": "array",
"items": {
"type": "string"
}
},

"bot_messages_count"

The count of AI agent messages

"bot_messages_count": {
"type": "string"
},

"visitor_messages_count"

the count of customer messages

"visitor_messages_count": {
"type": "string"
},

"not_understood_messages_count"

The count of the not understood messages in general

"not_understood_messages_count": {
"type": "string"
},

session_ended_timestamp

Timestamp when the user session expired based on UTC timezone. No new messages are added to the conversation after this point.

“session_ended_timestamp”: {
“type”: “string”
}

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…"]}

The file contains each conversation as a json object following this 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",
"bookingNo": null,
"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"
},
{
"reply_timestamp": "2024-05-03T08:10:03.355+00:00",
"reply_id": "64628e8e55e4f2459bcb2f4b",
"reply_language": "eng",
"reply_name": "Welcome reply",
"reply_type": "welcome"
},
{
"reply_timestamp": "2024-05-03T08:10:12.951+00:00",
"reply_id": "2475e571f88f9c35af3ff45e",
"reply_language": "eng",
"reply_name": "Office or store location and opening hours",
"reply_type": "normal",
"intent_id": "6385e571f88f9c35af3ff46e"
}
],
"triggered_intent_replies": [
{
"intent_timestamp": "2024-05-03T08:10:02.991+00:00",
"intent_id": "53628e8e55b4f2459bcb2e72",
"intent_name": "Greeting",
"not_meaningful": true
},
{
"intent_timestamp": "2024-05-03T08:10:12.951+00:00",
"intent_id": "6375b571f88f9c35af3ff44e",
"intent_name": "Find location of rental",
"not_meaningful": false
}
],
"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 of our suggestions to start the data exploration journey of the exported files.

AI agent metrics

SELECT
--Total conversations
count(distinct conversation_id) total_conversations,

--AI agent handled rate
count(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 rate
count(distinct case when conversation_status not in ('email', 'agent', 'customEscalation') then conversation_id end)/count(distinct conversation_id) deflection_rate,

--Escalation rate
count(distinct case when conversation_status in ('email', 'agent', 'customEscalation') then conversation_id end)/count(distinct conversation_id) escalation_rate,

--Failed escalation rate
count(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_rate

FROM TABLE

First / Last Intent from a conversation

select
distinct conversation_id,
triggered_use_cases[safe_offset(0)].intent_name first_intent,
array_reverse(triggered_intent_replies)[safe_offset(0)].intent_name last_intent
FROM TABLE

FAQs

Are the exported files immutable or do they change over time, requiring you to re-sync them?
The exported files are immutable, so they do not have to be reimported, thus making your BI pipeline less error-prone.

I see differences in conversation counts for a specific date between the exported conversations and AI agent Summary analytics. What could be the reason?
The exported data for a specific date has data only for conversations that ended on that date. This is a different approach than in the AI agent Summary analytics, where any conversation at any state is included. This is done for multiple reasons, among them are: export file immutability and duplicate data prevention.

Then how can I achieve parity between the numbers reported in the AI agent summary and the exported files?
To get a complete picture of all conversations that took place on a certain day x, you can just ingest the file generated for day x and day x + 1. By ingesting files from these two dates, you ensure that you will have counted all the conversations for date x, even if it spilled over to the next day.

I see differences in conversation counts for a specific date between the exported conversations and conversation logs. What could be the reason?
Remember that the exported data for a specific date has data only for conversations that ended on that date. This is a different approach than in the Conversation Logs, where any conversation at any state is included to enable real-time debugging.

Does a conversation include information about all replies triggered in a conversation, even if those replies happened on a previous day?
Yes. If a conversation is included in the file, it will have all of its data, even if it occurred on a previous day.

My virtual agent has conversations as part of the suggestion engine, will those appear in the export?
Yes. Although in the AI agent summary dashboard these are excluded, these will still be available in the exported data. To exclude these and achieve parity with AI agent summary dashboard, filter by "bot_messages_count > 0".

Why are there discrepancies between the exported data and the metrics in the Reporting dashboard?
The Reporting dashboard filters data by the conversation start time (conversation_start_date), whereas the data export API exports only completed conversations and uses the actual conversation end time (session_ended_date).