---
title: "Get outbound SMS statistics by country"
method: GET
path: "/v1/sms/stats/countries"
tags: ["sms-stats"]
---

# Get outbound SMS statistics by country

`GET /v1/sms/stats/countries`

## Request

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

Returns aggregate delivery and latency stats grouped by destination country for the requested period. Rows are ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, hard maximum 200). Use this to compare sending performance across the countries you send to.

Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive.

The maximum window is 365 days; requesting a longer range returns 422.

## Query parameters

- `from` string, date
- `to` string, date
- `timezone` string
- `sort` 'accepted' | 'sent' | 'delivered' | 'undelivered' | 'failed' | 'rejected' | 'expired' | 'delivery_rate' | 'failure_rate': Metric to rank breakdown rows by, applied descending. Shared by the volume breakdowns whose rows carry the full delivery and latency block (originators, countries, categories, carriers). Any lifecycle count or derived rate may be used; rows whose rate is undefined (zero denominator) sort last.
- `limit` integer
- `include_trend` boolean
- `trend_grain` 'daily' | 'hourly': Bucket grain for a stats trend series.

## Headers

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

## Response `200`

Per-country breakdown for the requested period.

- SMSStatsByCountryResponse: Per-country breakdown for the requested period, ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, max 200).
  - `period` SMSStatsSummaryPeriod, required: The window the server actually computed against. The summary serves two window grains: calendar days (bounds are YYYY-MM-DD) and hours (bounds are RFC 3339 instants on the hour). The grain of `from` and `to` mirrors the grain of the request's bounds.
    - `from` string, required: Inclusive start of the window, as a calendar day (`YYYY-MM-DD`) or an RFC 3339 hour boundary.
    - `to` string, required: Inclusive end of the window, as a calendar day (`YYYY-MM-DD`) or an RFC 3339 hour boundary.
    - `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` SMSCountryStatsPoint[], required: Country breakdown rows, ranked by the `sort` metric (default `accepted`) descending. Empty when no messages were sent in the period.
    - `country` string, required: The destination country this row aggregates, as an ISO 3166-1 alpha-2 code.
    - `delivery` SMSDeliveryStats, required: SMS lifecycle counts and rates for a whole period or breakdown. Counts use the message send time, so a later delivery stays attributed to the bucket in which the message was sent. Rates are null when their denominator is zero.
      - `accepted` integer, required: Distinct messages accepted for sending after admission checks. This is the denominator for `delivery_rate` and `failure_rate`.
      - `sent` integer, required: Distinct messages handed off to the carrier for delivery.
      - `delivered` integer, required: Distinct messages the carrier confirmed as delivered to the handset.
      - `undelivered` integer, required: Distinct messages the carrier reported as not delivered.
      - `failed` integer, required: Distinct messages that failed during sending.
      - `rejected` integer, required: Distinct messages rejected before any send attempt, for example by sending policy or a message-generation failure.
      - `expired` integer, required: Distinct messages that could not be delivered within their validity window and expired.
      - `delivery_rate` number, nullable, required: Share of accepted messages that were delivered, computed as `delivered / accepted`. Null when no messages were accepted in scope.
      - `failure_rate` number, nullable, required: Share of accepted messages that ultimately failed, computed as `(undelivered + failed + expired) / accepted`. Null when no messages were accepted in scope.
    - `latency` SMSLatencyStats, required: Latency percentiles in milliseconds for the requested scope: - `processing`: From acceptance to carrier handoff. - `delivery`: From carrier handoff to delivery confirmation. - `total`: From acceptance to delivery confirmation. Each family is omitted when no qualifying event contributes a measurement. Individual percentiles can also be null.
      - `processing` SMSLatencyQuantiles: 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` SMSLatencyQuantiles: 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` SMSLatencyQuantiles: 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.
    - `trend` SMSStatsPoint[]: Per-bucket lifecycle counts for this country, using `trend_grain`. Includes only buckets with activity. Present when `include_trend=true`.
      - `bucket` string, required: The day (YYYY-MM-DD) or hour (RFC 3339, on the hour) this point covers, matching the period's grain.
      - `delivery` SMSDeliveryCounts, required: SMS lifecycle counts for a time bucket. Counts use the message send time, so a message accepted on Monday and delivered on Tuesday counts in Monday's bucket. Rates are available only for whole periods and breakdowns.
        - `accepted` integer, required: Distinct messages accepted for sending after admission checks.
        - `sent` integer, required: Distinct messages handed off to the carrier for delivery.
        - `delivered` integer, required: Distinct messages the carrier confirmed as delivered to the handset.
        - `undelivered` integer, required: Distinct messages the carrier reported as not delivered.
        - `failed` integer, required: Distinct messages that failed during sending.
        - `rejected` integer, required: Distinct messages rejected before any send attempt, for example by sending policy or a message-generation failure.
        - `expired` integer, required: Distinct messages that could not be delivered within their validity window and expired.
  - `total` integer, required: Total number of distinct destination countries with activity in the period, regardless of `limit`. When it exceeds the number of rows returned, the ranking was capped; raise `limit` (up to 200) or narrow the window to see more.

## 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/6dfce1179799?raw)
