---
title: "Get outbound Apple Messages for Business statistics by error code"
method: GET
path: "/v1/amb/stats/error-codes"
tags: ["amb-stats"]
---

# Get outbound Apple Messages for Business statistics by error code

`GET /v1/amb/stats/error-codes`

## Request

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

Returns outbound counts and latency percentiles grouped by failure reason, for the requested period. Rows are ranked by `send_failed + rejected` descending and capped at the requested `limit` (default 50, max 200). Only messages carrying a failure reason appear: a `bird:` code is usually a rejection (never charged, never attempted), an `apple:` code a send failure; use the summary for the period's full accepted total. Rows use accepted-time attribution: a send failure recorded during the period for a message accepted earlier counts against the earlier period. Each row also carries `first_response` latency percentiles, when a failed reply claimed an unanswered inbound message. There is no delivery receipt on this channel, so there is no `delivered` count anywhere in the row.
This is a workspace-scoped, single-dimension breakdown; it does not cross error code with any other dimension such as business. The maximum window is 365 days; a longer range returns `422`. Historical dates are supported within the maximum window length; the requested dates are not shifted forward. A breakdown is already a single-dimension view and takes no dimension filter.

## Query parameters

- `from` string, date
- `to` string, date
- `timezone` string
- `limit` integer

## Headers

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

## Response `200`

Per-error-code breakdown for the requested period.

- AMBStatsByErrorCodeResponse: Per-failure-reason breakdown for the requested period, ranked by `send_failed + rejected` descending and capped at the requested `limit` (default 50, max 200). Only messages carrying an error code appear: a `bird:` code is usually a rejection, an `apple:` code a send failure.
  - `period` AMBStatsSummaryPeriod, 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. Historical starts are preserved; the maximum request length does not impose a historical cutoff.
    - `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.
  - `attribution` 'accepted_time' | 'event_time', required: Which timestamp a statistics response buckets its rows and totals by: - `accepted_time`: attributed to when Bird accepted the outbound message for sending. The outbound send statistics use this, so a later event for the same message, such as a send failure, still counts against the day or hour its message was accepted. - `event_time`: attributed to when the event itself occurred. Inbound message statistics, conversation statistics and the staff per-business failure counts use this, since there is no earlier outbound event to anchor them to. A response never mixes the two axes: every row and total in one payload shares the same attribution.
  - `data` AMBErrorCodeStatsPoint[], required: Error-code rows ranked by `send_failed + rejected` descending.
    - `error_code` string, required: Machine-readable reason a send failed, in one of two namespaces: `bird:` for a reason Bird's own pipeline assigned (for example `bird:business_not_registered`), or `apple:` followed by the HTTP status Apple's API returned for the send attempt (for example `apple:404`). This is an open, growing set in both namespaces; accept unrecognized values.
    - `counts` AMBOutboundStatsCounts, required: Outbound Apple Messages for Business counts for the requested scope, attributed to when each message was accepted. Apple Messages for Business has no delivery receipt, so there is no `delivered` count anywhere in this API: `sent` is the last outbound state Bird observes for a message. Very large counts are close estimates rather than exact tallies. Rates are computed once here, clamped to 1, and null when nothing was accepted.
      - `accepted` integer, required: Distinct messages accepted for sending after admission checks. This is the denominator for `sent_rate` and `send_failure_rate`.
      - `sent` integer, required: Distinct messages handed off to Apple.
      - `send_failed` integer, required: Distinct accepted messages that Apple refused or that exhausted their send attempts. See `last_error.code` on the message for the reason; a refused charge is not a send failure, it is `rejected`.
      - `rejected` integer, required: Distinct messages refused before any send attempt, because the destination has no price, the wallet could not fund the send, or the content cannot be sent yet. Rejected messages are never charged and are not counted in `accepted`, so the total addressed is `accepted + rejected`. Excluded from `send_failure_rate`, which covers send failures only.
      - `sent_rate` number, nullable, required: Share of accepted messages Apple acknowledged, computed as `sent / accepted`. Null when no messages were accepted in scope. This stands where other channels report a delivery rate.
      - `send_failure_rate` number, nullable, required: Share of accepted messages that failed to send, computed as `send_failed / accepted`. Null when no messages were accepted in scope.
    - `latency` AMBStatsLatency, required: Processing-latency percentiles in milliseconds for the requested scope, from acceptance to Apple handoff. Apple Messages for Business has no delivery receipt, so there is no `delivery` or `total` member beside `processing`. Conversation response timing is reported separately in `first_response`. Always present; every percentile is null when no qualifying message in scope has a measurement.
      - `processing` AMBStatsQuantiles, required: 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.
    - `first_response` AMBStatsQuantiles: 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` integer, required: Total distinct error codes with activity in the period, regardless of `limit`.

## 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)
