> ## Documentation Index
> Fetch the complete documentation index at: https://docs.burthq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Catalog

> Inspect the public analytics model and its valid members

This page explains the analytics model and the members accepted by the query
endpoint.

## Terms

| Term                              | Meaning                                                                                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Agent run                         | The main execution of an agent for a task.                                                                                                                               |
| Excluded sub-agents               | Sub-agent, browser, phone, and platform runs that belong to an agent run. They are not counted as extra agent runs.                                                      |
| Attribution record                | A record that connects an identified person to an agent run because that person started it, was associated with it when it started, or interacted with it later.         |
| Automated starter                 | A schedule or integration that starts an agent run without a person starting it. `unique_initiator_count` includes that starter only when it has an identifier.          |
| Unique person-and-run combination | One identified person together with one agent run. Run-count metrics count that pair once even when several attribution records connect the same person to the same run. |

## Models

| Model                 | Grain                                                                     | Event clock  | What it counts                                                                                               |
| --------------------- | ------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------ |
| `agent_runs`          | `one agent run; sub-agent and supporting runs are not counted separately` | `createdAt`  | One row for each agent run.                                                                                  |
| `agent_user_activity` | `one attribution record for an identified person and an agent run`        | `occurredAt` | One row each time a person is recorded as starting, being associated with, or interacting with an agent run. |

**Grain** says what one row represents. For `agent_runs`, each row is one agent
run. Excluded sub-agents belong to that agent run and are not counted
separately. Individual messages and tool calls inside a run are not rows
either.

**Event clock** is the timestamp that decides which range bucket a row falls
into. `agent_runs` uses the moment the run was created, so date filters and the
`day` dimension group runs by when they started.

For `agent_user_activity`, each row is one attribution record. The person is
named by a normalized email address or an E.164 phone number. Its `occurredAt`
event clock uses the time of the attribution record. A person who joins an
older run appears in the period when they joined, not when the run started.

### Which channels produce attribution records

A channel produces an attribution record only when it supplies an address the
API can group by. `manual`, `outlook_email`, `front_email`, `front_mention`,
`agent_email`, `phone_inbound`, and `text_message_inbound` produce records.
`slack_mention` produces an `initiated` record only, and only when the mention
resolved to the author's email address. Script-launched runs use the `script`
trigger source and are automated, so they produce no person attribution
records. Teams, Twilio, and self-serve webhook triggers likewise produce no
attribution records at all, so runs from those channels are absent from
`agent_user_activity` while still being counted in `agent_runs`.

## Metrics

All metrics return numbers. **Additive** metrics can be summed across groups
(for example, weekly totals from daily groups). Non-additive metrics cannot be
summed; selecting one adds a `non_additive_metric` warning to the response.
No metric or dimension is currently deprecated. See
[Versioning and deprecation](#versioning-and-deprecation).

### `agent_runs` metrics

| Metric                   | Type   | Additive | Description                                                                                                                                                                         |
| ------------------------ | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run_count`              | number | Yes      | Agent runs in the selected range, whatever their status.                                                                                                                            |
| `completed_run_count`    | number | Yes      | Agent runs that completed successfully (`COMPLETED`).                                                                                                                               |
| `failed_run_count`       | number | Yes      | Agent runs that failed (`FAILED`).                                                                                                                                                  |
| `cancelled_run_count`    | number | Yes      | Agent runs that were cancelled (`CANCELLED`).                                                                                                                                       |
| `active_run_count`       | number | Yes      | Agent runs still working or waiting at query time: queued, running, waiting for capacity, cancelling, awaiting a reply, sleeping, pausing, or paused.                               |
| `run_success_rate`       | number | No       | Share of finished runs that completed: completed divided by completed plus failed. Cancelled and active runs are excluded from both sides. Returns `null` when no run has finished. |
| `unique_initiator_count` | number | No       | Distinct identified starters. A starter may be a person or an automated starter. Starters without identifiers are excluded.                                                         |

Notes:

* The four status count metrics partition the same rows by outcome, so within
  one result
  `completed_run_count + failed_run_count + cancelled_run_count + active_run_count`
  equals `run_count`.
* `run_success_rate` is computed per group after grouping. Do not average or
  sum it across groups; re-query the groups you need instead.

### `agent_user_activity` metrics

Every count below is over the attribution records that the query's range and
filters selected.

| Metric                           | Type   | Additive | Description                                                                                                                                           |
| -------------------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `attributed_run_count`           | number | No       | Unique person-and-run combinations with at least one attribution record.                                                                              |
| `initiated_run_count`            | number | No       | Unique person-and-run combinations in which the person started the run.                                                                               |
| `associated_run_count`           | number | No       | `associated_run_count = attributed_run_count - initiated_run_count`. See the calculation below before reading it as "runs this person did not start". |
| `interacted_run_count`           | number | No       | Unique person-and-run combinations with at least one recorded interaction.                                                                            |
| `interaction_count`              | number | Yes      | Recorded interactions. Unlike the run metrics above, every interaction counts.                                                                        |
| `completed_attributed_run_count` | number | No       | Person-and-run combinations whose run is currently `COMPLETED`.                                                                                       |
| `failed_attributed_run_count`    | number | No       | Person-and-run combinations whose run is currently `FAILED`.                                                                                          |
| `cancelled_attributed_run_count` | number | No       | Person-and-run combinations whose run is currently `CANCELLED`.                                                                                       |
| `active_attributed_run_count`    | number | No       | Person-and-run combinations whose run currently has a non-terminal status.                                                                            |

`alex@example.com` starts one run and later sends three messages.
`attributed_run_count`, `initiated_run_count`, and `interacted_run_count` are
each 1. `interaction_count` is 3.

#### How `associated_run_count` is calculated

`associated_run_count` is arithmetic, not a stored category:

```text theme={null}
associated_run_count = attributed_run_count - initiated_run_count
```

Both values come from the records selected by the query's date range and
filters. `alex@example.com` starts a run on Monday and sends a message on
Tuesday. A Tuesday-only query sees one attributed run and no initiated run, so
`associated_run_count` is 1. A query covering both days returns 1 - 1 = 0.
This metric is calculated from the selected records. It is not a count of rows
whose `activity_type` is `associated`.

## Dimensions

Dimensions group results. Selecting a dimension produces one row per distinct
value inside the range. Filters accept these names too (see
[Filtering and ordering](#filtering-and-ordering)).

### `agent_runs` dimensions

| Dimension         | Type   | Description                                                                                                                                                                                   | Companion fields |
| ----------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `agent_id`        | string | Identifier of the agent for the agent run. Filters accept either the agent UUID or its optional slug. Runs of deleted agents still appear, grouped under the id they had.                     | `agent_name`     |
| `user_identifier` | string | Identifier for the person or automated starter that started the run, such as a normalized email address or phone number. Runs without an identifier form a `null` group.                      | `user_name`      |
| `user_type`       | string | Class of the starter: `internal`, `external`, `automated`, `unknown`, or `null` when absent. `automated` marks an automated starter, which is a schedule or integration rather than a person. | None             |
| `day`             | date   | Day the run started, in the requested IANA timezone, formatted `YYYY-MM-DD`. Only days with data appear; empty days are not filled in.                                                        | None             |

### `agent_user_activity` dimensions

`agent_id`, `user_identifier`, and `day` are named the same as on `agent_runs`
and carry the same companion fields, but `day` groups by `occurredAt` rather
than by when the run started. There is no `user_type` dimension on this model.
`run_initiation_type` classifies the run, not the person.

| Dimension             | Type   | Description                                                                                                                                                                        | Companion fields |
| --------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `agent_id`            | string | Identifier of the agent for the attributed agent run. Filters accept either the agent UUID or its optional slug.                                                                   | `agent_name`     |
| `user_identifier`     | string | Normalized email address or E.164 phone number of the attributed person. Never `null`. A sender the API cannot identify produces no row.                                           | `user_name`      |
| `user_domain`         | string | Email domain of the person, lowercased. `null` when the person is identified by a phone number.                                                                                    | None             |
| `activity_type`       | string | `initiated`, `associated`, or `interacted`.                                                                                                                                        | None             |
| `run_initiation_type` | string | How the agent run itself started: `human`, `automated`, or `unknown`. `automated` means an automated starter began it. The value is frozen when the attribution record is written. | None             |
| `source`              | string | Channel that produced the attribution record, such as `outlook_email`. See [which channels produce attribution records](#which-channels-produce-attribution-records).              | None             |
| `day`                 | date   | Day of the attribution record, in the requested IANA timezone, formatted `YYYY-MM-DD`. Only days with data appear.                                                                 | None             |

### Companion fields

Companion fields enrich a dimension and are returned automatically whenever
their dimension is selected. You cannot request them on their own. Each one
appears immediately after its dimension in `columns`:

* `agent_name`: current display name from the joined task-agent record.
  Soft-deleted agents remain joinable, but renaming an agent changes the name
  shown for historical runs.
* `user_name`: lexicographically greatest non-null display name in the
  `user_identifier` group.

Companions are plain output columns: they cannot be filtered or ordered by
name, and they do not count toward the eight-dimension limit.

## Filtering and ordering

* Filters apply to dimensions only. A filter on a metric or companion name is
  rejected as `unknown_member`.
* Each filter is either `"eq"` with one `value`, or `"in"` with a `values`
  array of 1–50 non-empty strings. At most eight filters apply per query.
* Use `YYYY-MM-DD` local dates in the range timezone for `day` filters. Filter
  strings are not independently date-validated; an unmatched value returns no
  rows.
* Filter values are strings; there is no equality test for `null`. To see the
  unattributed group, do not filter on that dimension. It appears as `null`
  rows.
* Up to eight unique order terms (`{ member, direction }`) may reference
  selected metrics or dimensions. Totals queries cannot specify ordering.
  Ordering by anything else is rejected as `invalid_query`.
* Without an explicit `order`, results sort ascending by every selected
  dimension. Explicit terms apply first, then remaining dimensions ascend.
  Ascending sorts place `null` values last; descending sorts place them first.
* Ordering by a metric produces a single-page top-N result and never returns a
  cursor. Dimension-ordered grouped queries paginate. See
  [Pagination](/api/pagination).

## Versioning and deprecation

`catalogVersion` identifies the published metric and dimension set and its
semantics. It is response metadata only: requests cannot pin a version, and a
request body containing `catalogVersion` is rejected. When the catalog changes,
the version changes too, and any outstanding pagination cursor stops working
with `invalid_cursor`; restart the walk from a fresh request.

Every metric and dimension carries a `deprecated` field; models and companion
fields do not. It is currently `null` for every metric and dimension. When set,
the object contains `since` (the catalog version that introduced the
deprecation) and `note` (migration guidance). Deprecated members remain
queryable and do not automatically add a query warning, so clients should
inspect this metadata.

## Example

```bash theme={null}
curl -sS https://api.burthq.com/api/v1/analytics/catalog \
  -H "Authorization: Bearer $BURT_API_KEY"
```

<Accordion title="Example response" defaultOpen={false}>
  ```json theme={null}
  {
    "catalogVersion": "2026-08-24.2",
    "models": [
      {
        "name": "agent_runs",
        "description": "One row for each agent run. Sub-agent work and the supporting browser, phone, inbound-phone, and platform runs it starts are not counted separately. The date range filters on createdAt.",
        "grain": "one agent run; sub-agent and supporting runs are not counted separately",
        "eventClock": "createdAt",
        "metrics": [
          {
            "name": "run_count",
            "type": "number",
            "description": "Agent runs, whatever their status.",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "completed_run_count",
            "type": "number",
            "description": "Agent runs that completed successfully (COMPLETED).",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "failed_run_count",
            "type": "number",
            "description": "Agent runs that failed (FAILED).",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "cancelled_run_count",
            "type": "number",
            "description": "Agent runs that were cancelled (CANCELLED).",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "active_run_count",
            "type": "number",
            "description": "Agent runs still working or waiting: PENDING, RUNNING, WAITING_FOR_SLOT, CANCELLING, AWAITING_REPLY, SLEEPING, PAUSING, or PAUSED.",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "run_success_rate",
            "type": "number",
            "description": "Completed agent runs divided by the sum of completed and failed runs. Cancelled and active runs are excluded from both sides. The result is null when the denominator is zero.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "unique_initiator_count",
            "type": "number",
            "description": "Distinct identified starters. A starter may be a person or an automated starter. Starters without identifiers are excluded.",
            "additive": false,
            "deprecated": null
          }
        ],
        "dimensions": [
          {
            "name": "agent_id",
            "type": "string",
            "description": "Task-agent identifier for the agent run. Filters accept either the agent UUID or its optional slug. Rows for soft-deleted agents are still returned. The agent_name companion comes from the current joined task-agent record, so renames affect historical results. Slug resolution is point-in-time: a slug filter matches whichever agent currently holds that slug, not the agent it identified when the filter was written. Because agent_id always returns the agent UUID, pin the UUID instead of the slug for filters that must stay stable across renames.",
            "companions": [
              {
                "name": "agent_name",
                "type": "string",
                "description": "Current display name from the joined task-agent record. Soft-deleted agents remain joinable, but renames affect historical results."
              }
            ],
            "deprecated": null
          },
          {
            "name": "user_identifier",
            "type": "string",
            "description": "Identifier for the person or automated starter that started the run, such as a normalized email address or phone number. Rows without an identifier group together and return null.",
            "companions": [
              {
                "name": "user_name",
                "type": "string",
                "description": "Lexicographically greatest non-null display name in the user-identifier group."
              }
            ],
            "deprecated": null
          },
          {
            "name": "user_type",
            "type": "string",
            "description": "Class of the starter: internal, external, automated, unknown, or null when absent. The automated value marks an automated starter, which is a schedule or integration rather than a person.",
            "companions": [],
            "deprecated": null
          },
          {
            "name": "day",
            "type": "date",
            "description": "Creation day in the requested IANA timezone, formatted YYYY-MM-DD. Filters take the same format. Only days with data are returned; the series is not gap-filled.",
            "companions": [],
            "deprecated": null
          }
        ]
      },
      {
        "name": "agent_user_activity",
        "description": "One row each time a person is recorded as starting, being associated with, or interacting with an agent run. The date range filters on occurredAt.",
        "grain": "one attribution record for an identified person and an agent run",
        "eventClock": "occurredAt",
        "metrics": [
          {
            "name": "attributed_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations with at least one attribution record.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "initiated_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations in which the person started the run.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "associated_run_count",
            "type": "number",
            "description": "associated_run_count = attributed_run_count - initiated_run_count. Both values come from the attribution records selected by the query's date range and filters.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "interacted_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations with at least one recorded interaction.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "interaction_count",
            "type": "number",
            "description": "Recorded interactions. Unlike the run metrics above, every interaction counts.",
            "additive": true,
            "deprecated": null
          },
          {
            "name": "completed_attributed_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations whose run is currently COMPLETED.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "failed_attributed_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations whose run is currently FAILED.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "cancelled_attributed_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations whose run is currently CANCELLED.",
            "additive": false,
            "deprecated": null
          },
          {
            "name": "active_attributed_run_count",
            "type": "number",
            "description": "Unique person-and-run combinations whose run currently has a non-terminal status.",
            "additive": false,
            "deprecated": null
          }
        ],
        "dimensions": [
          {
            "name": "agent_id",
            "type": "string",
            "description": "Task-agent identifier for the attributed agent run. Filters accept either the agent UUID or its optional slug. The agent_name companion comes from the current joined task-agent record. Slug resolution is point-in-time: a slug filter matches whichever agent currently holds that slug, not the agent it identified when the filter was written. Because agent_id always returns the agent UUID, pin the UUID instead of the slug for filters that must stay stable across renames.",
            "companions": [
              {
                "name": "agent_name",
                "type": "string",
                "description": "Current display name from the joined task-agent record."
              }
            ],
            "deprecated": null
          },
          {
            "name": "user_identifier",
            "type": "string",
            "description": "Normalized email address or E.164 phone number for the attributed person.",
            "companions": [
              {
                "name": "user_name",
                "type": "string",
                "description": "Lexicographically greatest non-null captured display name in the user-identifier group."
              }
            ],
            "deprecated": null
          },
          {
            "name": "user_domain",
            "type": "string",
            "description": "Lowercased email domain when the person is identified by an email address. Null when the person is identified by a phone number.",
            "companions": [],
            "deprecated": null
          },
          {
            "name": "activity_type",
            "type": "string",
            "description": "Attribution activity: initiated, associated, or interacted.",
            "companions": [],
            "deprecated": null
          },
          {
            "name": "run_initiation_type",
            "type": "string",
            "description": "How the agent run started: human, automated when an automated starter began it, or unknown. The value is frozen when the attribution record is written.",
            "companions": [],
            "deprecated": null
          },
          {
            "name": "source",
            "type": "string",
            "description": "Channel that produced the attribution record.",
            "companions": [],
            "deprecated": null
          },
          {
            "name": "day",
            "type": "date",
            "description": "Day of the attribution record in the requested IANA timezone, formatted YYYY-MM-DD. Filters use the same format.",
            "companions": [],
            "deprecated": null
          }
        ]
      }
    ]
  }
  ```
</Accordion>
