Median

Analytics

Nine support and cost numbers over one date range, and the explorer for any other question.

Updated Oct 1, 202612 minute read

Every role can open Analytics, cost tiles included. The explorer's Activity log dataset needs an owner or admin. See Roles.

Pick a range

The menu at the top right sets one range for every tile and chart on the page.

OptionCovers
Last 7 daysToday and the 6 days before it
Last 30 daysToday and the 29 days before it. The page opens on this range.
Last 90 daysToday and the 89 days before it
  • The range starts at midnight on your device's clock. Each day ends at your midnight.
  • Today counts while it is still going. Chart tooltips call it Today so far.
  • The header spells out the dates, like "Aug 28 to Sep 26".

The tiles

Nine tiles sit in a grid. Press one to draw it as the large chart under the grid. The page opens on Conversations.

Resolved by agent and Satisfaction draw a row of pills filled to their share. The other seven tiles draw a sparkline of their days. Press the table icon at the top right of the chart to see the same numbers as rows, one per day.

TileNumber on the tileChart seriesWhat counts
ConversationsConversations startedWidget, Email, DiscordEvery conversation started in the range, by the channel it came in on
Resolved by agentShare finished by the agentBy agent, By teamFinished means Resolved or Closed. By agent means the agent still held the conversation when it was finished. Open conversations count toward the whole, so the share rises as they close. Each conversation sits on the day it started.
HandoffsConversations handed to the teamHanded offThe agent asked for a person, or a teammate took over. A conversation handed back to the agent still counts.
SatisfactionAverage stars, out of 54 or 5 stars, 3 stars, 1 or 2 starsRatings left in the range, on the day they were left. The rating card is on Conversations.
Time to resolveMedian time from the first message to the lastMedian, 95th percentileFinished conversations that started in the range. A day with nothing finished leaves a gap in the line. The tooltip shows how many finished that day.
SignalsBugs and suggestions filedBugs, SuggestionsSignals created in the range, on the day they were filed
Credits usedCredits charged, in dollarsAI, Email, Page scrapingWhat was charged. Work that was not charged counts as zero. 1 credit is $1.
AI requestsModel callsAutomatic, By the teamAutomatic is work nobody pressed a button for, like replies, triage and indexing. By the team is work a teammate started, like the assistant and explorer questions. The tooltip shows the day's tokens.
Cost per messageAverage credits charged per message the agent wroteAverageCredits charged for the agent's messages, divided by how many it wrote, even ones charged $0. A message counts once, however many bubbles and model calls it took. Work a conversation sets off later, like learning from it once it is resolved, is left out. A day with no messages leaves a gap in the line. The tooltip shows how many messages the day covers.

Plans, prices and what a credit buys are on Billing.

Caps

Each tile reads a limited number of rows per range.

TilesReads at mostNamed in the header as
Conversations, Resolved by agent, Handoffs, Time to resolve2,000 conversations, newest firstthe latest 2,000 conversations
Satisfaction2,000 ratings, newest firstthe latest 2,000 ratings
Signals1,000 signals across the organization. Planned, Open and the other live statuses are read before Done and Declined1,000 signals, open ones first
Credits used, AI requests, Cost per message5,000 usage events, newest firstthe latest 5,000 usage events

Past a cap, the oldest days lose rows first. The header names every cap the range hit, like "counting the latest 2,000 conversations and the latest 2,000 ratings". The note is hidden on narrow screens.

Explore

The explorer answers one question at a time over anything the workspace records. It opens as a dialog.

Opened fromStarts on
Explore on AnalyticsConversations counted per day, over the page's range
Explore on LogsActivity log counted per day and split by outcome, over every day the log range touches. A range longer than 366 days opens on All time.

The range menu in the dialog offers Today, Last 7 days, Last 30 days, Last 90 days and All time. From Logs, the handed-over dates lead the menu. Each time the dialog opens it takes the page's range again. The query stays until you leave the page.

Ask in words

Type into Ask a question about your data and press Enter or the arrow button. Three sample questions sit under the box until you ask one. Press a sample to ask it.

Opened fromSamples
Analytics"Handoffs by channel, per week", "Busiest hours, by day of the week", "Credits used by feature"
Logs"Failed events by area", "Credits used by AI feature, per day", "Slowest tools"
  • Questions take up to 500 characters.
  • While it works, the chart area reads Reading the question, Choosing the data, then Writing the query.
  • The answer fills the query column, picks a chart and names it. A line under the box says what it did.
  • A question that names a range, like "last week", sets the range menu to the nearest preset.
  • A follow-up changes the query on screen instead of starting over, like "now split it by channel" or "only email".
  • Edit any step afterward. The chart updates live.
  • Asking needs Standard or Pro. See Plans. On the Explore plan the box is disabled and reads "Available on Standard and Pro." Owners and admins get a View plans link. Members see "Ask an owner or admin to upgrade." Building a query by hand works on every plan.
  • Each question is charged as AI usage. It shows in Logs as an Analytics question.
MessageCause
Ask something first.The box was empty
The model did not answer. Try again.The model call failed
That did not come back as a query. Try asking another way.The answer could not be read as a query

Build a query

The query is a row of pills under the ask box, read left to right. A pill shows its setting's name and value. Press it to change the value. Pills for a setting that does not apply yet, like the field to measure beside Count, stay hidden. On a phone the row scrolls sideways.

PillChoices
DatasetThe dataset. Changing it resets Measure to Count, clears filters and Split by, and sets Date to the dataset's first date. The time axis stays.
MeasureCount, Distinct, Total, Average, Median, the 75th, 90th, 95th and 99th percentile, Lowest, Highest, Percent where. Percent where adds a Where pill for its condition. The others except Count add an Of pill for the field to measure.
Split byPlain until set, then a field to draw one series per value. Setting it adds a pill like "Top 8" whose menu holds Show (3 to 20, 8 by default), Order (Default order, Largest first, Smallest first) and The rest (Show as Other or Hide).
Time axisOne total, Per day, Per week, Per month, By hour of day, By day of week. With All time only the last two are offered.
DateWhich date places a row, for datasets with more than one, like a conversation's Started or Last message
ComparePlain until set to Previous period, the same number of days just before the range. Hidden with All time.
FilterPick a field, then a comparison and a value. Up to 8 filters. They show as chips on a row under the pills. Typed values take up to 200 characters.

The chart takes the full width under the query and grows to fill the dialog's height.

MeasureWorks on
CountRows. Needs no field.
DistinctText, choice and id fields, like Customer
Total, Average, Median, the percentiles, Lowest, HighestNumber and duration fields
Percent whereA condition, picked like a filter. The share of the matched rows that meet it, from 0 to 100%. The handoff rate is Conversations, Percent where Handed off. It starts on the dataset's first yes-or-no field.

Filter comparisons are is, is not, is any of, is none of, is more than, is at least, is less than, is at most, contains, does not contain, is set and is not set. Each field offers the ones that fit it.

  • A field with named values, like Channel, lists them with checkboxes. Tick one or more, pick is or is not, then Apply. Two or more read as is any of or is none of.
  • For typed values, is any of and is none of take a list split by commas.
  • Duration filters take minutes. Over the API they take milliseconds.
  • Between two filters sits and. Press it to switch every join to or, so a row needs to pass only one filter. Press or to switch back.
  • Hours and weekdays follow your device's clock.

With Largest first or Smallest first, groups rank by what they measure, and the ranking decides which keep their names. Top 5 with Largest first on Conversations split by Page shows the five busiest pages. Other takes one of the places. Hide leaves the other groups off the chart, and the headline covers only the groups shown.

Previous period puts a line beside the headline number, like "12% vs previous period", with an arrow for the way it moved. Hover it for the earlier number. Table and Download CSV gain a Previous period column when the chart has no axis.

Datasets

Every dataset also has Hour of day and Day of week.

DataRowsDatesReads at most
ConversationsSupport threads from every channel. Fields include Channel, Status, Outcome, Handed off, Sentiment, Agent's work, Assignee, Page, Referrer and Time open.Started, Last message2,000
MessagesEvery message in a conversation, from the customer, the agent, the team, internal notes and system lines. Fields include From, Channel, Used tools, Failed, Attachments and Length.Sent5,000 messages from up to 400 conversations active in the range, 200 per conversation
RatingsStars customers left. Fields include Stars, Rating band and Left a comment.Rated2,000
SignalsBugs and suggestions. Fields include Kind, Status, Priority, Reporters, Issue tracker and Merged duplicates.Filed, Updated1,000
Activity logEntries from Logs. Owners and admins only. Fields include Area, Event, Done by, Outcome, AI feature, Tool, Duration, Credits used, Tokens and HTTP status. Area and Done by use the names the Logs filters use.Logged5,000
Knowledge documentsDocuments the agent knows. Fields include Source, Status, Public link, In a folder and Length.Added, Updated1,000
Knowledge suggestionsPages the agent suggested. Fields include Status, Edits a page, Reviewed by and Time to review.Suggested, Reviewed1,000
Tool requestsTools the agent asked for. Fields include Status, Risk, Reviewed by and Inputs.Requested, Reviewed500
Tool runsEvery custom tool call. Fields include Tool, Status, Started by, Waited on, Reviewer verdict and Time to settle.Started, Settled1,000
CustomersPeople who wrote in. Fields include Signed in, Device, Browser, Operating system, Language, Time zone, Company and Email domain.First seen, Last seen2,000
TasksCards from the Tasks API. Fields include Status, Priority, Assigned, From a signal, Issue tracker and Time to done.Created, Done, Updated1,000
UsageMetered AI, email and page scraping, with what each cost. Fields include Service, Feature, Started by, Paid from, Credits charged and token counts.Occurred5,000

When a query stops at its cap, a note under the chart reads like "Counting the latest 5,000 usage events". Members do not see Activity log in the menu. A query for it from a member returns "Only admins and owners can view audit logs."

Chart kinds

The row of chart icons sits beside the headline number. A kind that does not fit the query stays dimmed and says why on hover.

KindNeeds
ColumnsAn axis or a split. The default for counts and totals over time.
Line, AreaAn axis. Line is the default for other measures over time.
BarsA split and no axis. The default for a split with no axis.
DonutA split, no axis, and Count, Distinct or Total
HeatmapAn axis and a split
NumberNothing. The default for one total.
TableNothing

Records and CSV

Chart and Records switch the result.

  • Records lists the rows the query matched. Filters, date and range apply. Measure, split and axis do not.
  • The menu over the list sorts it: Newest first, Oldest first, or any number field highest or lowest first, like Duration, highest first for the slowest tool runs. Rows with no value sort last. A sorted field shows first on each row.
  • It loads 50 rows. Show more adds 50, up to 200. The footer reads like "Latest 50 of 1,240 conversations", or "First 50" when sorted another way.
  • A row opens its page in the app and closes the dialog. Tasks and Usage rows have no page to open.
  • Download CSV saves the numbers behind the chart, the same rows Table shows. The file is named after the chart's title. Log entries themselves export from Logs.

Over the API, CLI and MCP

The same numbers are on the management API. The API returns more than the page draws, like conversations by hour, top pages, sentiment and the knowledge base's shape.

EndpointReturns
GET /v1/analytics/overviewThe headline numbers on the Dashboard
GET /v1/analytics/conversations, /satisfaction, /signals, /knowledge, /billingOne day per bucket. days is 7, 30 or 90, default 30. from defaults to exactly days ago, so pass your own midnight to match the page.
GET /v1/analytics/activityLog entries per day. Owners and admins.
POST /v1/analytics/exploreOne explorer query. days is a whole number from 1 to 366, default 30, counted back from today in UTC. Anything else returns invalid_request. from moves the start.
POST /v1/analytics/recordsThe rows a query matched. days and from work as for explore. limit is 1 to 200, default 50. sort is { "by": "time" or a field id, "direction": "desc" or "asc" }. fields lists the field ids each row reads out.

A query takes the same steps as the builder:

KeyTakes
measure{ "op", "field" }. op is count, distinct, sum, avg, median, p75, p90, p95, p99, min, max or percent. percent takes where, one filter, instead of field.
filters{ "field", "op", "value" } each. op is is, isNot, in, notIn, gt, gte, lt, lte, contains, notContains, isSet or isNotSet. in and notIn take a list of up to 50 values.
matchall (default) or any
groupByA field id, or null
top, order, other1 to 20 (default 8); natural (default), largest or smallest; true (default) folds the rest into __other, false leaves them off
bucketday, week, month, hour, weekday, or null
when{ "field", "scope" }, scope range (default) or all
comparetrue adds previous: the same measure over the days just before the window, one value per group. Ignored with scope all.

Money in /billing is in microcredits, 1,000,000 to the dollar.

median analytics explore --days 90 \
  --query '{"dataset":"conversations","measure":{"op":"count"},"groupBy":"channel","bucket":"week"}'

# The handoff rate by channel, against the 30 days before
median analytics explore --days 30 \
  --query '{"dataset":"conversations","measure":{"op":"percent","where":{"field":"handedOff","op":"is","value":true}},"groupBy":"channel","compare":true}'
curl https://api.median.sh/v1/analytics/explore \
  -H "Authorization: Bearer $MEDIAN_KEY" \
  -H "content-type: application/json" \
  -d '{"days":90,"query":{"dataset":"conversations","measure":{"op":"count"},"groupBy":"channel","bucket":"week"}}'
return await median.analytics.explore({
  days: 90,
  query: { dataset: "conversations", measure: { op: "count" }, groupBy: "channel", bucket: "week" },
});

Queries take field ids rather than labels, like channel for Channel. median_docs with topic analytics lists every dataset's field ids. Every command and flag is in the CLI reference. The MCP server is on MCP.

Still need help?

    Esc