---
title: "Metrics"
description: "Query MachineMail metrics for the organization, a pod or an inbox: event counts over a time range, rolling bounce and complaint rates, and current usage."
canonical: "https://machinemail.dev/docs/reference/api/metrics"
---

# Metrics

> Query MachineMail metrics for the organization, a pod or an inbox: event counts over a time range, rolling bounce and complaint rates, and current usage.

Source: https://machinemail.dev/docs/reference/api/metrics

| Method | Path                                    | Summary                                                       |
| ------ | --------------------------------------- | ------------------------------------------------------------- |
| `GET`  | `/v0/inboxes/{inbox_id}/metrics`        | [Query Events (alias) in Inbox](#query-events-alias-in-inbox) |
| `GET`  | `/v0/inboxes/{inbox_id}/metrics/events` | [Query Events in Inbox](#query-events-in-inbox)               |
| `GET`  | `/v0/inboxes/{inbox_id}/metrics/rates`  | [Query Rates in Inbox](#query-rates-in-inbox)                 |
| `GET`  | `/v0/inboxes/{inbox_id}/metrics/usage`  | [Query Usage in Inbox](#query-usage-in-inbox)                 |
| `GET`  | `/v0/metrics`                           | [Query Events (alias)](#query-events-alias)                   |
| `GET`  | `/v0/metrics/events`                    | [Query Events](#query-events)                                 |
| `GET`  | `/v0/metrics/rates`                     | [Query Rates](#query-rates)                                   |
| `GET`  | `/v0/metrics/usage`                     | [Query Usage](#query-usage)                                   |
| `GET`  | `/v0/pods/{pod_id}/metrics`             | [Query Events (alias) in Pod](#query-events-alias-in-pod)     |
| `GET`  | `/v0/pods/{pod_id}/metrics/events`      | [Query Events in Pod](#query-events-in-pod)                   |
| `GET`  | `/v0/pods/{pod_id}/metrics/rates`       | [Query Rates in Pod](#query-rates-in-pod)                     |
| `GET`  | `/v0/pods/{pod_id}/metrics/usage`       | [Query Usage in Pod](#query-usage-in-pod)                     |

## Query Events (alias) in Inbox

```http
GET /v0/inboxes/{inbox_id}/metrics
```

<Callout type="warn">Deprecated.</Callout>

Same as Query Events (alias) (`GET /v0/metrics`), limited to the inbox.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `inbox_id` | `string` | required | ID of the inbox. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev/metrics" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Events in Inbox

```http
GET /v0/inboxes/{inbox_id}/metrics/events
```

Same as Query Events (`GET /v0/metrics/events`), limited to the inbox.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `inbox_id` | `string` | required | ID of the inbox. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev/metrics/events" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Rates in Inbox

```http
GET /v0/inboxes/{inbox_id}/metrics/rates
```

Same as Query Rates (`GET /v0/metrics/rates`), limited to the inbox.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `inbox_id` | `string` | required | ID of the inbox. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `rate_types` | `string[]` |  | Rate types: bounce, complaint. Default: both. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points. |
| `window` | `integer` |  | How far back each point looks, in seconds: a whole multiple of period, at most 2592000 (30 days). Default 86400 when that is a multiple of period, otherwise period. |

#### Response

**200** Rates by type (`application/json`)

Type: `Record<string, RatePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev/metrics/rates" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Usage in Inbox

```http
GET /v0/inboxes/{inbox_id}/metrics/usage
```

Same as Query Usage (`GET /v0/metrics/usage`), limited to the inbox.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `inbox_id` | `string` | required | ID of the inbox. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `usage_types` | `string[]` |  | Usage types: storage_bytes, message_count, thread_count, inbox_count, pod_count, domain_count. Default: all. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period. |

#### Response

**200** Usage by type (`application/json`)

Type: `Record<string, UsagePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev/metrics/usage" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Events (alias)

```http
GET /v0/metrics
```

<Callout type="warn">Deprecated.</Callout>

Alias of `GET /v0/metrics/events`.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/metrics" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Events

```http
GET /v0/metrics/events
```

Counts of events per event type over time, in buckets of `period` seconds (default one day), over the last 24 hours unless `start` and `end` say otherwise. `message.received` includes its sub-types (spam, blocked, unauthenticated, quarantined). At most 100,000 events are counted per query.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/metrics/events" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Rates

```http
GET /v0/metrics/rates
```

Rolling bounce and complaint rates. At each `period` grid point: the bounced (or complained) messages over the preceding `window`, divided by the messages sent over the same window, with the send count alongside. Defaults: the last 24 hours, `period` 3600, `window` 86400.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `rate_types` | `string[]` |  | Rate types: bounce, complaint. Default: both. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points. |
| `window` | `integer` |  | How far back each point looks, in seconds: a whole multiple of period, at most 2592000 (30 days). Default 86400 when that is a multiple of period, otherwise period. |

#### Response

**200** Rates by type (`application/json`)

Type: `Record<string, RatePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/metrics/rates" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Usage

```http
GET /v0/metrics/usage
```

Current usage in the scope. Usage history is not kept yet: each series has a single point, at `end`, with the value now.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `usage_types` | `string[]` |  | Usage types: storage_bytes, message_count, thread_count, inbox_count, pod_count, domain_count. Default: all. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period. |

#### Response

**200** Usage by type (`application/json`)

Type: `Record<string, UsagePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/metrics/usage" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Events (alias) in Pod

```http
GET /v0/pods/{pod_id}/metrics
```

<Callout type="warn">Deprecated.</Callout>

Same as Query Events (alias) (`GET /v0/metrics`), limited to the pod.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `pod_id` | `string` | required | ID of the pod. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/metrics" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Events in Pod

```http
GET /v0/pods/{pod_id}/metrics/events
```

Same as Query Events (`GET /v0/metrics/events`), limited to the pod.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `pod_id` | `string` | required | ID of the pod. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `event_types` | `string[]` |  | Event types to count: message.received, message.received.spam, message.received.blocked, message.received.unauthenticated, message.received.quarantined, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified (the default is all of them). message.received counts every inbound message, including the message.received.* sub-types, which are also reported under their own keys. Other values give a series of zeros. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Bucket size in seconds, 1 to 86400. Default 86400 (one bucket per UTC day). The range may hold at most 1000 buckets. |

#### Response

**200** Event counts by type (`application/json`)

Type: `Record<string, MetricBucket[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/metrics/events" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Rates in Pod

```http
GET /v0/pods/{pod_id}/metrics/rates
```

Same as Query Rates (`GET /v0/metrics/rates`), limited to the pod.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `pod_id` | `string` | required | ID of the pod. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `rate_types` | `string[]` |  | Rate types: bounce, complaint. Default: both. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | How often a point is sampled, in seconds, 60 to 86400. Default 3600. The range may hold at most 1000 points. |
| `window` | `integer` |  | How far back each point looks, in seconds: a whole multiple of period, at most 2592000 (30 days). Default 86400 when that is a multiple of period, otherwise period. |

#### Response

**200** Rates by type (`application/json`)

Type: `Record<string, RatePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/metrics/rates" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```

## Query Usage in Pod

```http
GET /v0/pods/{pod_id}/metrics/usage
```

Same as Query Usage (`GET /v0/metrics/usage`), limited to the pod.

**Authentication:** `Authorization: Bearer <api key>` or the dashboard `mm_session` cookie. Permission: `metrics_read`.

#### Path parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `pod_id` | `string` | required | ID of the pod. |

#### Query parameters

| Field | Type | | Description |
| --- | --- | --- | --- |
| `usage_types` | `string[]` |  | Usage types: storage_bytes, message_count, thread_count, inbox_count, pod_count, domain_count. Default: all. Another value is a 400. |
| `start` | `string (date-time)` |  | Start of the range. Default: 24 hours before end. |
| `end` | `string (date-time)` |  | End of the range. Default: now; a later time is clamped to now. |
| `limit` | `integer` |  | Return at most this many points per series. |
| `descending` | `boolean` |  | Newest point first. |
| `period` | `integer` |  | Accepted for AgentMail compatibility; usage has no history, so there is one point whatever the period. |

#### Response

**200** Usage by type (`application/json`)

Type: `Record<string, UsagePoint[]>`

#### Errors

| Status | Meaning                                                                                                                                                                                                                                |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid request: error.type is validation and error.param names the field.                                                                                                                                                             |
| `401`  | Missing, invalid, expired or revoked credential.                                                                                                                                                                                       |
| `403`  | The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account\_suspended: error.message says what still works; do not retry or re-register). |
| `404`  | Not found. Also returned for resources outside the credential scope.                                                                                                                                                                   |
| `500`  | Unexpected server error.                                                                                                                                                                                                               |

Error bodies use the [error envelope](https://machinemail.dev/docs/reference/errors).

#### Example

```bash title="Request"
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/metrics/usage" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
```

```json title="Response 200"
{
  "key": "value"
}
```
