Skip to main content
muveya computes a closed set of management metrics from your operational records: stock alerts, deliveries, orders, approvals, custody and consumption. This page defines each one in plain words and says where you can read it. All of them share the same rules:
  • Read-only and live. A metric is computed when you ask for it, from the current records. Nothing is cached or stored, except the CSV file of an export.
  • Deterministic. The same records give the same figure. No AI computes or rewrites a figure.
  • Counts, quantities and durations only. No metric carries a cost, an order value or a patient reference.
  • The same figure everywhere. The console, the public API and MCP run the same calculation, so the same question gets the same number on every surface.
  • UTC. Every date, window and bucket is in UTC.

Where each capability lives

The console has one analytics screen today: Consumption report. Everything else is read through the public API with an API key or through MCP with OAuth. There is no console screen for the other metrics, for exports, or for creating API keys; to get a key, write to team@muveya.com. For the technical details of each surface, see Exports and MCP tools.

Who can read them

reports.read is enough: a metric reads the underlying orders, deliveries and stock on your behalf only to count them, and never returns a field you could not read otherwise. An API key covers every clinic and warehouse of its dental clinic account. A console member limited to some warehouses sees consumption for those warehouses only.

Fields the results share

Most results carry these fields. The exact shape of each operation is in the API reference. A value of null means there was no sample to compute a percentage, median or average. It is never replaced by zero.

Scan limits

Operational metrics

GET /v1/analytics/metrics/{metric} returns one scalar figure. {metric} must be one of these eight ids; any other value is refused with 400 and common.invalid_request.

Snapshot counts

These describe the situation now. catalogItemId narrows the two stock counts to one supply.

Pilot signals

These three add numerator, denominator and sampleCount where they apply, a definition, and machine-readable caveats.
wall_clock_hours_no_business_calendar means nights, weekends and holidays count as hours. muveya does not apply a business-hours calendar yet.
A window whose from is not before to, or a date that cannot be read, is refused with 400. The result includes period only when you send both from and to.

Operational exceptions

GET /v1/analytics/exceptions lists the problems a manager should act on, most urgent first. catalogItemId narrows the stock exceptions to one supply. Each entry also has priority, a per-entry evidenceId, and, for stock alerts, detectedAt. Entries are sorted by priority, then by drill-down id. The report adds total. To follow a drill-down with the same key:
  • order: GET /v1/orders/{orderId} and GET /v1/fulfillments/{orderId}.
  • movement: the movement appears in GET /v1/inventory/boxes/{boxId}/movements, using the boxId in reference.
  • item: GET /v1/catalog/items/{itemId}.
Each of those operations needs its own scope. See Scopes.

Clinic comparison

GET /v1/analytics/clinics/comparison (metric ORDERS_BY_CLINIC, unit orders) ranks the clinics of your account by order volume. Clinics are ranked by totalOrders, most first, then by clinic id. Order values are never included.

Consumption trend

GET /v1/analytics/consumption-trend (metric CONSUMPTION_TREND) is the calculation behind the console’s Consumption report. The window must have from before to and span at most 366 days; otherwise 400. The result has one entry in series per supply and unit (seriesKey is catalogItemId:unitOfMeasure), with totalConsumed, usedQuantity (observed use), issuedQuantity (delivered to rooms that do not count their stock, an estimated consumption) and movementCount, plus buckets per day or week. usedQuantity + issuedQuantity = totalConsumed. There is never a total across supplies or units. coverage states what the figures stand for: measuredMovementCount, unverifiedMovementCount (records from before the unit was verified, counted but not quantified, listed per supply in unverifiedItems), warehouseScope (all or restricted) and coveredFrom when the scan was cut. A narration is included only when it passes the check that every number in it equals the table.

Approval backlog

GET /v1/analytics/approval-backlog (metric APPROVAL_BACKLOG, unit orders) counts the orders waiting for approval across the account, grouped by how long they have waited since submission. It also returns total and oldestSubmittedAt. For the approver’s own inbox, see Order approvals.

Order cycle time

GET /v1/analytics/cycle-time (metric ORDER_CYCLE_TIME, unit hours) gives the average duration of each stage of an order’s life, over the orders that reached that stage. Each stage has averageHours (two decimals, null when no order reached it) and sampleCount. observedFulfillments is the number of deliveries read. The average is not limited to a window. See Delivery and receipt.

Management briefing

GET /v1/analytics/briefing (metric MANAGEMENT_BRIEFING) is a reproducible digest that puts the metrics above in one flat list of figures. period is daily (default) or weekly; any other value is 400. Each figure has metric (its source), dimension (the sub-key, absent for a single number), label, value, unit and the evidenceId of its source. The figures come in this order: What period changes:
  • The consumption part always covers the consumption metric’s default window, the last 30 days. daily groups it by day and weekly by week. Because the briefing lists totals, the figures of a daily and a weekly briefing are currently the same; only the consumption evidenceId differs.
  • The snapshot counts, the backlog and the cycle time are not narrowed to a day or a week.
Labels follow the reader’s language: the Accept-Language header on the API (en, es or pt, English otherwise) and the Accept-Language header on MCP, with English as the fallback. Ids, dimensions, units, values and evidenceId never change with the language. A supply the catalog cannot name is labelled Unknown supply. The briefing’s own evidenceId is MANAGEMENT_BRIEFING:period=daily or MANAGEMENT_BRIEFING:period=weekly, and truncated is true if any of its sources was truncated. On MCP, management.briefing returns this briefing together with the operational exceptions.

CSV exports

The briefing can be exported as a CSV file. Exports are requested and collected only through the public API. The full request and response shapes are in Exports.
1

Request the export

POST /v1/analytics/exports with an optional period (daily by default, or weekly). The Accept-Language header of this request fixes the language of the CSV labels. The answer is 202 with an exportId and the job status.
2

Poll until it is ready

GET /v1/analytics/exports/{exportId} returns the current state. The file is built in the background, so the first answer is usually pending, although it can already be ready.
3

Download

When status is ready, the answer carries downloadUrl and downloadExpiresAt. The link works for 5 minutes. Each poll creates a fresh link, so poll again if it expired. The file is named management-briefing-daily.csv or management-briefing-weekly.csv.
4

Verify

Compare the SHA-256 of the downloaded bytes with checksum, and the size with byteSize.

Export states

Rules

  • Expiry. An export job is kept for 7 days. After that, GET /v1/analytics/exports/{exportId} answers 404. A download link lasts 5 minutes and is never permanent.
  • Isolation. An exportId only works with a key of the same dental clinic account. Any other id answers 404, without saying whether it exists elsewhere.
  • Redaction. The file holds counts, quantities, durations, labels and evidence ids only. No cost, order value or patient reference can be in it.
  • Format. UTF-8 with a byte-order mark (so spreadsheets read accents correctly), CRLF line endings, and the columns metric, dimension, label, value, unit, evidenceId. A figure without a sample has an empty value cell, never 0. A cell that starts with =, +, -, @, a tab or a carriage return is prefixed with a single quote, so a spreadsheet never runs it as a formula.
  • Audit. Each request writes an analytics.export audit fact. A finished file writes analytics.export_built with its checksum and size, which outlives the 7-day job. A key without analytics:read is refused with 403 before the export is requested, and that refusal writes no audit fact.

What can go wrong

The full error format is in Errors.

Consumption report

The console screen for consumption by supply.

Exports

Request and poll a briefing export.

MCP tools

analytics.consumption, management.briefing, management.compare_clinics.

Replenishment and alerts

Where the low-stock and expiry alerts come from.