Knowing how your customer service is performing is key to making the right decisions. The Intelligence API gives you the same data that powers analytics in Dixa, so you can bring it into your own dashboards, reports and tools.
Our Intelligence API is designed for:
- Retrieving metrics, such as the number of closed conversations, response times, CSAT or AI agent feedback, for a period of time.
- Retrieving records, the individual events behind each metric, such as every closed conversation, every agent presence interval or every tool an AI agent called.
- Narrowing both down with the same filters you know from Dixa, such as queue, team, agent, channel or tag.
The Intelligence API is part of the beta version of the Dixa API. It may change before it is promoted to v1.
Most of the Dixa API has one endpoint per resource, such as conversations, agents or queues. The Intelligence API works differently: it is catalogue-driven.
A small, fixed set of endpoints serves every metric and record. The catalogue tells you which metrics and records exist, and how each of them can be queried: which filters it accepts, which values it returns and which records it is built from. When we add a new metric, it shows up in the catalogue, and you can query it through the same endpoints without any changes on your side.
- Feeding key metrics, such as response time or CSAT per team, into your BI tool or data warehouse.
- Building your own dashboards with the same numbers your team sees in Dixa.
- Drilling down from a metric into the records behind it, e.g. to find the conversations that were abandoned before an agent picked them up.
Every metric and record belongs to a category: conversations, agents or aiagents. The category decides which endpoint you query:
AI agent metrics and records cover AI agents joining conversations, the tools they call and the feedback end users give on their answers.
A metric returns a handful of values, such as count, average or percentage. A record returns a page of rows, one per event.
The List metrics and List records endpoints return the catalogue. Add category=conversations, category=agents or category=aiagents to narrow it down.
curl -H "Authorization: <API token>" "https://dev.dixa.io/beta/intelligence/metrics?category=conversations"Each entry in the catalogue tells you everything you need to build a query:
id: the metric or record id that goes in the URL, e.g.closedConversations.primaryFilters: how the query can be anchored, byperiodand, for many conversation entries, byconversationIds.filters: the attributes you can filter on, theoperatorseach attribute accepts, and thedefaultOperatorused when you leave the operator out.aggregates(metrics only): the values the response contains.fields(records only): the columns a row can contain, and their types.relatedRecordIdsandrelatedMetricIds: the records a metric is built from, and the metrics a record feeds into.
Filters take ids, not names. The List filter values endpoint returns the ids and display names for one attribute, e.g. all your queues:
curl -H "Authorization: <API token>" "https://dev.dixa.io/beta/intelligence/filters/queue/values"Agents, queues, teams and tags are identified by UUIDs, the same ids the rest of the Dixa API uses. AI agents are listed under the aiAgent attribute; this endpoint is the place to look up their ids. Fixed values, such as channels, are identified by names such as Email or PstnPhone. Deactivated agents, queues and tags, and deleted AI agents, are still listed, marked with deactivated: true, since past activity still refers to them.
The catalogue and filter values are paginated. To fetch the next page, call the link in meta.next of the response as it is.
The metric or record id goes in the URL, and the query goes in the request body:
curl -X POST "https://dev.dixa.io/beta/intelligence/conversations/metrics/closedConversations" \
-H "Authorization: <API token>" \
-H "Content-Type: application/json" \
-d '{
"primaryFilter": {
"period": { "interval": { "from": "2026-06-01T00:00:00Z", "to": "2026-06-30T23:59:59.999Z" } }
},
"filters": [
{ "attribute": "queue", "values": ["2f9b6d51-38c4-4a72-9e15-7c8b3f6a2d90"], "operator": "IsOne" }
],
"timezone": "Europe/Copenhagen"
}'The response contains every value the metric offers:
{ "data": { "count": 1284 } }primaryFilteranchors the query and is one of:- A
periodwith aninterval, e.g.{ "period": { "interval": { "from": "2026-06-01T00:00:00Z", "to": "2026-06-30T23:59:59.999Z" } } }. Bothfromandtoare inclusive, andfrommust be beforeto. Both must end inZor a UTC offset, such as2026-06-01T00:00:00+02:00. - A
periodwith apreset, e.g.{ "period": { "preset": "Last7Days" } }, resolved in the timezone of the request.Last7Daysand otherLast{N}{Unit}spresets include the current unit, soLast7Daysincludes today.PreviousWeek,PreviousMonthand the otherPrevious{Unit}presets cover the last full unit, andThisMonthand the otherThis{Unit}presets cover the current unit so far. - A list of
conversationIds, e.g.{ "conversationIds": [8123456, 8123481] }, if the catalogue entry allows it. The query then ignores any period.
- A
filtersnarrows the query down. Each filter has anattribute, a list ofvaluesand, optionally, anoperator. All filters must match.IsEmptyandIsNotEmptytake an empty list of values. A filter on an attribute the catalogue entry doesn't list, or with an operator the attribute doesn't accept, is rejected rather than ignored.timezoneis required. Presets and day boundaries are evaluated in this timezone.
Record queries also accept:
pagination, with an optionalpageLimitof up to 1000 rows and thepageKeyof the page you want.includeLabels, which defaults totrue. Set it tofalseto receive ids without display names.
Metrics return every value listed under aggregates in the catalogue entry. If nothing matched the query, count is 0 and the other values, such as average or percentage, are null. Durations are in milliseconds.
Records return one page of rows under data, and the keys of the next and previous pages under meta. To fetch the next page, send the same query again with meta.next as pagination.pageKey. The page key is opaque, so pass it on unchanged.
Within a row:
- A column without a value is left out, so rows can have different keys.
- A reference, such as an agent or a queue, is an object with an
idand, unless you setincludeLabelstofalse, alabel. - A reference that no longer exists, such as a deleted queue, is left out of the row.
- Ids, attributes and JSON keys are written in camelCase, e.g.
closedConversationsorinitialDirection. Operators, presets and fixed values are written in PascalCase, e.g.IsOne,Last7DaysorPstnPhone. - Read the catalogue rather than hard-coding ids and filters, so new metrics and filters reach your integration automatically. Check the
deprecatedflag of an entry before relying on it. - An unknown metric or record id returns HTTP status 404 Not Found, and an invalid query returns 400 Bad Request with a message explaining what is wrong.
- Authentication and rate limits work the same way as for the rest of the Dixa API. Read more in API Standards & Rules, and see How to create an API token to get started.