Interaction Metrics
Define reusable metric definitions that aggregate your interaction data.
Interaction Metrics are reusable metric definitions that aggregate your interaction data. They serve as the foundation for Metric Alerts — you define what to measure, and alerts define when to act on it.
Overview
A metric definition specifies:
- What to aggregate — count, sum, average, min, max, distinct count, or rate
- Which interactions — scoped by resource type, action, origin, and custom filters
- Over what period — a time window like 5m, 1h, 24h
- Grouped by what — optional dimensions like
resourceId,interaction.country
When calculated, the metric runs a SQL aggregation against your interaction data and returns one or more result rows.
Creating a metric
POST /api/interaction-metrics
{
"name": "Failed Logins (5m)",
"description": "Count of failed login attempts in the last 5 minutes",
"resourceTypeId": "customer-uuid",
"actionId": "login-fail-uuid",
"metricTypeId": "count-metric-type-uuid",
"timeWindow": "5m",
"filters": [],
"groupBy": [],
"enabled": true
}Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Human-readable metric name |
description | No | What this metric measures |
metricTypeId | Yes | Aggregation type (see metric types) |
resourceTypeId | No | Scope to a resource type, or omit for all |
actionId | No | Scope to an action, or omit for all |
originId | No | Scope to an origin, or omit for all |
field | Conditional | Field to aggregate (required for sum, avg, min, max, distinct count) |
filters | No | Additional filter conditions |
timeWindow | No | Aggregation window (omit for all time) |
groupBy | No | Dimensions to group by |
enabled | No | Whether the metric is active (default: true) |
Metric types
Retrieve available metric types:
GET /api/interaction-metrics/types| Type | Mnemonic | Description | Requires field |
|---|---|---|---|
| Count | COUNT | Number of matching interactions | No |
| Sum | SUM | Sum of a numeric field | Yes |
| Average | AVG | Average of a numeric field | Yes |
| Minimum | MIN | Minimum value of a field | Yes |
| Maximum | MAX | Maximum value of a field | Yes |
| Distinct Count | DISTINCT_COUNT | Count of unique values | Yes |
| Rate | RATE | Count per time unit | No (requires timeWindow) |
Time window format
| Format | Example | Meaning |
|---|---|---|
{n}m | 5m | 5 minutes |
{n}h | 1h | 1 hour |
{n}d | 7d | 7 days |
Omit timeWindow to aggregate across all time.
Filters
Filters narrow the interactions included in the metric calculation. Each filter has:
| Field | Description |
|---|---|
field | The field to filter on — resourceId, or interaction.{key} for nested fields |
operator | eq, neq, gt, gte, lt, lte, contains |
value | The value to compare against |
{
"filters": [
{ "field": "interaction.country", "operator": "eq", "value": "ZA" },
{ "field": "interaction.attempts", "operator": "gt", "value": 3 }
]
}Group by
Group by adds dimensions to the metric result. Instead of a single aggregate value, you get one row per unique combination of dimension values.
{
"groupBy": ["interaction.country", "interaction.browser"]
}Result:
{
"results": [
{ "value": 42, "dimensions": { "interaction_country": "ZA", "interaction_browser": "Chrome" } },
{ "value": 18, "dimensions": { "interaction_country": "US", "interaction_browser": "Safari" } }
]
}Supported group-by fields:
resourceId— group by resourceinteraction.{key}— group by any field in the interaction JSON
Field discovery
If you've selected a resource type and action, you can discover which fields exist in your interaction data:
GET /api/interaction-metrics/fields/discover?resourceTypeId=uuid&actionId=uuidReturns an array of field paths:
["interaction.email", "interaction.country", "interaction.browser", "interaction.ip_address"]Calculating metrics
Single metric
POST /api/interaction-metrics/:metricId/calculateReturns:
{
"metricId": "uuid",
"metricName": "Failed Logins (5m)",
"metricType": "COUNT",
"calculatedAt": "2026-03-20T14:30:00.000Z",
"results": [
{ "value": 42, "dimensions": null }
]
}For grouped metrics, results contains one entry per dimension combination:
{
"results": [
{ "value": 25, "dimensions": { "interaction_country": "ZA" } },
{ "value": 17, "dimensions": { "interaction_country": "US" } }
]
}All metrics
POST /api/interaction-metrics/calculate-allReturns:
{
"calculated": 5,
"results": [
{
"metricId": "uuid",
"metricName": "Failed Logins (5m)",
"metricType": "COUNT",
"calculatedAt": "2026-03-20T14:30:00.000Z",
"resultCount": 1,
"sampleValue": 42,
"results": [{ "value": 42, "dimensions": null }]
}
]
}Examples
Count of orders in the last hour
{
"name": "Orders (1h)",
"metricTypeId": "count-uuid",
"resourceTypeId": "order-uuid",
"actionId": "created-uuid",
"timeWindow": "1h"
}Average order value by origin
{
"name": "Avg Order Value by Origin",
"metricTypeId": "avg-uuid",
"resourceTypeId": "order-uuid",
"actionId": "chk-done-uuid",
"field": "interaction.total",
"timeWindow": "24h",
"groupBy": ["interaction.origin"]
}Failed logins per country (5 min)
{
"name": "Failed Logins by Country (5m)",
"metricTypeId": "count-uuid",
"resourceTypeId": "customer-uuid",
"actionId": "login-fail-uuid",
"timeWindow": "5m",
"groupBy": ["interaction.login_location"]
}Email bounce rate
{
"name": "Email Bounces (1h)",
"metricTypeId": "count-uuid",
"resourceTypeId": "email-uuid",
"actionId": "bounced-uuid",
"timeWindow": "1h"
}API reference
| Method | Endpoint | Description |
|---|---|---|
GET | /api/interaction-metrics | List all metrics |
GET | /api/interaction-metrics/:id | Get metric by ID |
POST | /api/interaction-metrics | Create metric |
PUT | /api/interaction-metrics/:id | Update metric |
DELETE | /api/interaction-metrics/:id | Delete metric |
GET | /api/interaction-metrics/types | List metric types |
GET | /api/interaction-metrics/fields/discover | Discover fields for resource type + action |
POST | /api/interaction-metrics/:id/calculate | Calculate single metric |
POST | /api/interaction-metrics/calculate-all | Calculate all enabled metrics |