---
title: "Get daily outbound WhatsApp statistics"
method: GET
path: "/v1/whatsapp/stats/daily"
tags: ["whatsapp-stats"]
---

# Get daily outbound WhatsApp statistics

`GET /v1/whatsapp/stats/daily`

## Request

- Base URL: `https://us1.platform.bird.com`
- URL: `https://us1.platform.bird.com/v1/whatsapp/stats/daily`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `bird_session`

Returns one row of aggregate WhatsApp statistics per calendar day for the workspace. Rows use send-time attribution, so a delivery confirmation received on Wednesday for a message accepted the prior Monday is counted in Monday's row. Recent rows can under-report `delivered` while delivery reports arrive. Days with no activity are included with zero counts.

Each row carries lifecycle counts (accepted, sent, delivered, read, failed) and its own latency percentiles; delivery, failure, and read rates are whole-window aggregates available from the summary endpoint instead. `from` and `to` are optional calendar days (YYYY-MM-DD), defaulting to the trailing 30 days. The maximum window is 365 days; a longer range returns `422`. Set `timezone` to report rows by your local calendar day.

Set at most one dimension filter (`template`, `category`, `phone_number`, `tag`) to restrict the statistics to that dimension's value; setting more than one returns 422.

## Query parameters

- `from` string, date
- `to` string, date
- `timezone` string
- `template` string
- `category` string: Meta's content classification for a template. - `authentication`: delivers one-time passcodes. - `utility`: delivers transaction-triggered updates (receipts, order status). - `marketing`: carries promotional content. The category determines the sender number and price. This is an open enum. Accept unrecognized values.
- `phone_number` string
- `tag` string

## Headers

- `X-Workspace-Id` string
- `X-Organization-Id` string

## Response `200`

Daily aggregate stats for the requested period.

- WhatsAppStatsResponse: Time-series stats payload. `period` echoes the range and bucket grain the server computed against; `data` is one row per bucket in chronological order.
  - `period` WhatsAppStatsSeriesPeriod, required: The window and bucket grain the response covers, echoed from the request, plus the freshness boundary the data is current to.
    - `from` string, required: Inclusive start of the window. A calendar day (YYYY-MM-DD) on the day grain, an RFC 3339 instant on the hour grain.
    - `to` string, required: Inclusive end of the window. A calendar day (YYYY-MM-DD) on the day grain, an RFC 3339 instant on the hour grain.
    - `grain` 'day' | 'hour', required: The bucket grain of the series, either `day` or `hour`.
    - `data_as_of` string, date-time, nullable: Latest time reflected in the statistics. More recent events might not be included yet. Null when the freshness boundary is unavailable.
  - `data` WhatsAppStatsPoint[], required: One row per day or hour in chronological order. Buckets with no activity contain zero counts.
    - `bucket` string, required: The day (YYYY-MM-DD) or hour (RFC 3339, on the hour) this point covers, matching the period's grain.
    - `delivery` WhatsAppDeliveryCounts, required: WhatsApp lifecycle counts for a time bucket, attributed by send time. A message accepted on Monday and delivered on Tuesday counts in Monday's bucket. The sibling `engagement` block reports read counts. Rates are available only for the whole period. Very large counts are close estimates rather than exact tallies.
      - `accepted` integer, required: Distinct messages accepted for sending after admission checks.
      - `sent` integer, required: Distinct messages handed off for delivery.
      - `delivered` integer, required: Distinct messages confirmed delivered to the recipient's device.
      - `failed` integer, required: Distinct messages that failed during sending or delivery.
      - `rejected` integer, required: Distinct messages rejected before any send attempt, because the recipient is on the workspace's suppression list, no reachable recipient was given, the destination has no price, or the wallet could not fund the send. Rejected messages are never charged and are not counted in `accepted`, so the total addressed is `accepted + rejected`. Excluded from `failure_rate`, which covers send failures only.
    - `engagement` WhatsAppEngagementCounts, required: WhatsApp engagement counts for a time bucket, attributed by send time. A message accepted on Monday and read on Tuesday counts in Monday's bucket. Read rates are available only for the whole period. Very large counts are close estimates rather than exact tallies.
      - `read` integer, required: Distinct messages confirmed read by the recipient.
    - `latency` WhatsAppLatencyStats, required: Latency percentiles in milliseconds for the requested scope: - `processing`: From acceptance to WhatsApp handoff. - `delivery`: From WhatsApp handoff to delivery confirmation. - `total`: From acceptance to delivery confirmation. Each family is omitted when no qualifying message contributes a measurement. Individual percentiles can also be null. `delivery` is measured on a best-effort basis, so it can be absent for a scope whose `processing` and `total` are present.
      - `processing` WhatsAppLatencyQuantiles: Approximate p50, p95, and p99 latency percentiles in milliseconds for one latency family. All three are null when no qualifying event contributed a measurement.
        - `p50_ms` integer, nullable, required: Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p95_ms` integer, nullable, required: 95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p99_ms` integer, nullable, required: 99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.
      - `delivery` WhatsAppLatencyQuantiles: Approximate p50, p95, and p99 latency percentiles in milliseconds for one latency family. All three are null when no qualifying event contributed a measurement.
        - `p50_ms` integer, nullable, required: Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p95_ms` integer, nullable, required: 95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p99_ms` integer, nullable, required: 99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.
      - `total` WhatsAppLatencyQuantiles: Approximate p50, p95, and p99 latency percentiles in milliseconds for one latency family. All three are null when no qualifying event contributed a measurement.
        - `p50_ms` integer, nullable, required: Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p95_ms` integer, nullable, required: 95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.
        - `p99_ms` integer, nullable, required: 99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Insufficient permissions
- `404`: Resource not found
- `422`: The request has invalid field values, violates a business rule, or carries a query parameter the endpoint does not declare. Field validation errors use `type: validation_error` and include the affected fields in `details`. Business-rule errors identify the failed rule in `type`.
- `429`: Rate limit exceeded
- `500`: Internal server error
- `503`: The service is temporarily unavailable. If `Retry-After` is present, wait for that delay before retrying; otherwise, retry with exponential backoff. Reuse the same idempotency key and request when retrying a mutation.

---

[API](https://skmtc.dev/messagebird/apis/bird-api.md) · [All operations](https://skmtc.dev/messagebird/apis/bird-api/llms.txt) · [OpenAPI document](https://skmtc.dev/messagebird/apis/bird-api/revisions/3e2a50466454?raw)
