Data API
Introduction
Ema's Data API provides a reliable, self-serve way to export message-level chatbot conversation data for a specific AI Employee over a selected UTC date range, delivered as a streamed CSV file. This export is designed for customers who want to take data beyond the Ema product UI and perform deeper analysis in their own analytics stack (for example, Power BI, Tableau, Snowflake, or internal data science notebooks).
Using the Data API, you can:
- Build custom dashboards for adoption and engagement.
- Run advanced analyses such as sentiment/intent modeling on user queries and AI responses.
- Independently compute key metrics like sessions, active users, total queries/messages, and feedback rates.
The API is read-only and returns raw records (one row per message), allowing full flexibility to define derived metrics and trends. Data is refreshed daily with a 24-hour SLA, and exports are available for dates starting September 1, 2025 onward.
Data Dictionary (CSV Schema)
Each row represents one message. The following fields are included:
| Field | Format | Description |
|---|---|---|
conversation_id | string (UUID) | Groups related messages into a session. Inactivity period is configurable per channel (default: 30 minutes). |
persona_id | string (UUID) | Unique ID assigned by Ema for an AI Employee. (Note: persona_id is a query parameter, not a column in the exported CSV.) |
conversation_source | string | Human-readable channel name (for example, msteams, gchat, chatbot). |
conversation_created_at | ISO 8601 (UTC) | Timestamp when the first message was sent by the user. |
conversation_updated_at | ISO 8601 (UTC) | Timestamp of the last message or response in the conversation. |
message_id | string (UUID) | Unique ID assigned to each user message. |
message_created_at | ISO 8601 (UTC) | Timestamp when the message was sent. |
message_updated_at | ISO 8601 (UTC) | Timestamp when the message object was last updated. |
workflow_run_error | boolean | Indicates whether the workflow was successful. |
user_feedback_type | string | Feedback given by the end user: positive, negative, no_feedback_submitted, or empty (feedback was not requested). |
user_feedback_comment | string | Actual feedback comment given by the end user. |
feedback_message_sent | boolean | Indicates whether feedback was requested for the response. |
content_payload_json | JSON string | Message sent by the end user. |
user_context | JSON string | User attributes such as country, band, etc. |
unique_source_ids | JSON array | Deduplicated source file IDs seen in citations. |
country | string | Extracted from user_context (if available; otherwise empty). |
band | string | Extracted from user_context (if available; otherwise empty). |
encrypted_user_email | string | Base64-encoded encrypted user email. |
is_user_message | boolean | Whether this row represents a user message (as opposed to an AI response). |
external_tool_called | boolean | Whether an external tool was called during this message's processing. |
external_tool_call_success | boolean/string | Whether the external tool call succeeded. |
external_tool_name | string | Name of the external tool that was called (if any). |
events_per_message | JSON array | Array of events associated with this message. |
Data Model
- One session/conversation maps to multiple queries (1 to many).
- One feedback maps to one query (1:1).
- One query maps to multiple source IDs (1 to many).
Authentication
Endpoint
- Path:
/api/metric-data/chatbot/conversations - Method: GET
- Example:
https://api.yourcompany.ema.co/api/metric-data/chatbot/conversations
Bearer Token
Include a Bearer token in the Authorization header:
Authorization: Bearer <access_token>
Fetching the Access Token
curl --location --request POST 'https://api.yourcompany.ema.co/api/auth/generate_access_token' \
--header 'x-ema-api-key: <API-KEY>'
Contact your CSM or Support team to request an API key for each tenant.
Query Parameters
| Parameter | Required | Format | Description |
|---|---|---|---|
start_date | Yes | YYYY-MM-DD (UTC) | Start of the date range |
end_date | Yes | YYYY-MM-DD (UTC, inclusive) | End of the date range |
persona_id | Yes | UUID | The AI Employee's ID (last segment of the AI Employee URL) |
Validations and Limits
- Both dates must match
YYYY-MM-DDformat. end_datemust be >=start_date.- Maximum inclusive range: 31 days.
Response
- Status: 200 OK on success.
- Media type:
text/csv; charset=utf-8 - Transfer: Streamed response (no fixed Content-Length).
- Filename pattern:
chatbot-metrics-{persona_id}-{start_date}_to_{end_date}.csv
Error Responses
| Status | Cause |
|---|---|
| 400 Bad Request | Invalid persona_id, invalid date format, end_date earlier than start_date, or date range exceeds 31 days |
| 401 Unauthorized | Missing or invalid token, or token lacks tenant_id |
Sample Request
curl -G 'https://api.yourcompany.ema.co/api/metric-data/chatbot/conversations' \
-H 'Authorization: Bearer REPLACE_WITH_TOKEN' \
--data-urlencode 'start_date=2025-11-01' \
--data-urlencode 'end_date=2025-11-15' \
--data-urlencode 'persona_id=<persona-id>' \
-o chatbot-metrics.csv
Key Metrics and How to Calculate Them
Unique Users / Active Users
Count distinct values of encrypted_user_email. Filter by conversation_created_at and conversation_updated_at for a specific date range.
Total User Queries / Messages
Count all rows where message_id is not empty. Filter by message_created_at and message_updated_at.
Total Sessions
Count unique conversation_id values whose conversation_updated_at lies within the date range.
Positive Feedback Rate
Formula: 1 - (negative / (positive + negative + no_feedback_submitted))
Since the majority of users do not explicitly provide feedback, no response is also considered positive implicitly.
Segmentation by User Attributes
Use the user_context column or pre-populated columns like country and band to group metrics by user attributes.
FAQs
- What is the SLA for new data? Data is refreshed daily at 00:15 AM UTC with a 24-hour SLA.
- What data quality checks are used? Three types: PII exclusion checks, critical field population rules, and aggregate/trend-based validations against product metrics.
- What if no data is available? The response body will be empty for the given date range/persona.