<Intro>

<EndpointHeader />

<Description>

Returns a single-row aggregate across the requested period covering SMS lifecycle counts (accepted, sent, delivered, undelivered, failed, rejected, expired) plus the derived delivery and failure rates, and processing/delivery/total latency percentiles (p50/p95/p99). Suitable for KPI tiles and dashboard headers.
Rows are attributed to send time, not event time: a delivery confirmed during the period for a message accepted earlier counts against the earlier period, not this one. A recent period therefore under-reports `delivered` while its delivery reports are still arriving, and its counts only ever grow toward the truth.
Rate fields are null when their denominator is zero -- for example, `delivery_rate` is null in a period where nothing was accepted.
`from` and `to` accept either calendar days (YYYY-MM-DD) or RFC 3339 instants. With days the window covers whole calendar days, up to 365 days. With instants the window is hour-grain -- bounds round down to the hour, both inclusive -- so a rolling window such as the last 24 hours is a single request; hour windows may span up to 720 hours (30 days), and `compare=previous_period` compares against the preceding equal-length hour window. Both bounds must use the same form; mixing a day and an instant returns 422. Set `timezone` to report in a local zone instead of UTC (it then governs the day and hour boundaries; see `timezone`).

</Description>

</Intro>

<Parameters in="query">

<Parameter name="from" type="string">

<Description>

Inclusive start of the window: a calendar day (YYYY-MM-DD) or an RFC 3339 instant (rounded down to the hour). Interpreted in `timezone` -- a calendar day names a local day and an instant is rounded down to the local hour -- or in UTC when `timezone` is omitted. A numeric UTC offset (for example `+05:45`) is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `to`. Defaults to 30 days before `to` for day windows, or 168 hours (7 days) before `to` for hour windows, when omitted.

</Description>

</Parameter>

<Parameter name="to" type="string">

<Description>

Inclusive end of the window: a calendar day (YYYY-MM-DD) or an RFC 3339 instant (rounded down to the hour). Interpreted in `timezone` -- a calendar day names a local day and an instant is rounded down to the local hour -- or in UTC when `timezone` is omitted. A numeric UTC offset is rejected when `timezone` is set; use a calendar day or a `Z` (UTC) instant. Must use the same form as `from`. Defaults to today for day windows, or the current hour for hour windows, in that timezone, when omitted. Day windows may not exceed 365 days; hour windows may not exceed 720 hours (30 days).

</Description>

</Parameter>

<Parameter name="timezone" type="string">

<Description>

IANA timezone identifier (for example `Asia/Kathmandu`) to report in; defaults to UTC. Day and hour boundaries and the default window when `from` and `to` are omitted both follow it, so a calendar-day `from` or `to` names a local day. A `from` or `to` carrying its own UTC offset is rejected while this is set: pass a calendar day or a `Z` instant.

</Description>

</Parameter>

<Parameter name="originator" type="string">

<Description>

Restrict the statistics to a single originator (the sender address messages were sent from). Mutually exclusive with the other dimension filters (`country`, `category`, `carrier`); only one may be set per request. Matches the message `from`.

</Description>

</Parameter>

<Parameter name="country" type="string">

<Description>

Restrict the statistics to a single destination country, as an ISO 3166-1 alpha-2 code. Mutually exclusive with the other dimension filters (`originator`, `category`, `carrier`); only one may be set per request.

</Description>

</Parameter>

<Parameter name="category" type="string">

<Description>

Restrict the statistics to a single category. Mutually exclusive with the other dimension filters (`originator`, `country`, `carrier`); only one may be set per request.

</Description>

</Parameter>

<Parameter name="carrier" type="string">

<Description>

Restrict the statistics to a single delivery carrier. Mutually exclusive with the other dimension filters (`originator`, `country`, `category`); only one may be set per request.

</Description>

</Parameter>

<Parameter name="compare" type="string">

<Description>

Set to `previous_period` to also include the same statistics for the immediately preceding window of equal length, plus the change between the two, so you can show "+X% vs last period" without a second request.

</Description>

<Description>

Possible values: `previous_period`

</Description>

</Parameter>

</Parameters>

<Payload kind="response">

<Field name="period" type="object" required>

<Description>

The window the response covers (echoed back from the request, day or hour grain), plus `data_as_of`, the freshness boundary the data is current to.

</Description>

<FieldChildren kind="response">

<Field name="from" type="string" prefix="period." required>

<Description>

Inclusive start of the window the response covers -- a calendar day (YYYY-MM-DD) for day windows, or an hour boundary (RFC 3339) for hour windows.

</Description>

</Field>

<Field name="to" type="string" prefix="period." required>

<Description>

Inclusive end of the window the response covers -- a calendar day (YYYY-MM-DD) for day windows, or an hour boundary (RFC 3339) for hour windows.

</Description>

</Field>

<Field name="data_as_of" type="nullable string" prefix="period.">

<Description>

The instant the statistics in this response are current to: events recorded up to roughly this time are reflected, while more recent events may not be yet. Statistics are served from a rolling aggregation that refreshes every few seconds, so a response is near-real-time but not live; use this field to label data freshness (for example "as of 14:03") rather than assuming the numbers are to-the-second. Null when the freshness boundary is not being reported.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="delivery" type="object" required>

<FieldChildren kind="response">

<Field name="accepted" type="integer" prefix="delivery." required>

<Description>

Distinct messages accepted for sending after admission checks. This is the denominator for `delivery_rate` and `failure_rate`.

</Description>

</Field>

<Field name="sent" type="integer" prefix="delivery." required>

<Description>

Distinct messages handed off to the carrier for delivery.

</Description>

</Field>

<Field name="delivered" type="integer" prefix="delivery." required>

<Description>

Distinct messages the carrier confirmed as delivered to the handset.

</Description>

</Field>

<Field name="undelivered" type="integer" prefix="delivery." required>

<Description>

Distinct messages the carrier reported as not delivered.

</Description>

</Field>

<Field name="failed" type="integer" prefix="delivery." required>

<Description>

Distinct messages that failed during sending.

</Description>

</Field>

<Field name="rejected" type="integer" prefix="delivery." required>

<Description>

Distinct messages rejected before any send attempt, for example by sending policy or a message-generation failure.

</Description>

</Field>

<Field name="expired" type="integer" prefix="delivery." required>

<Description>

Distinct messages that could not be delivered within their validity window and expired.

</Description>

</Field>

<Field name="delivery_rate" type="nullable number" prefix="delivery." required>

<Description>

Share of accepted messages that were delivered, computed as `delivered / accepted`. Null when no messages were accepted in scope.

</Description>

</Field>

<Field name="failure_rate" type="nullable number" prefix="delivery." required>

<Description>

Share of accepted messages that ultimately failed, computed as `(undelivered + failed + expired) / accepted`. Null when no messages were accepted in scope.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="latency" type="object" required>

<FieldChildren kind="response">

<Field name="processing" type="object" prefix="latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="latency.processing." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="latency.processing." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="latency.processing." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="delivery" type="object" prefix="latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="latency.delivery." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="latency.delivery." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="latency.delivery." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="total" type="object" prefix="latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="latency.total." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="latency.total." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="latency.total." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

</FieldChildren>

</Field>

<Field name="comparison" type="object">

<FieldChildren kind="response">

<Field name="period" type="object" prefix="comparison." required>

<Description>

The preceding window these comparison figures cover -- the equal-length window ending immediately before the requested start (the prior day for day windows, the prior hour for hour windows).

</Description>

<FieldChildren kind="response">

<Field name="from" type="string" prefix="comparison.period." required>

<Description>

Inclusive start of the window the response covers -- a calendar day (YYYY-MM-DD) for day windows, or an hour boundary (RFC 3339) for hour windows.

</Description>

</Field>

<Field name="to" type="string" prefix="comparison.period." required>

<Description>

Inclusive end of the window the response covers -- a calendar day (YYYY-MM-DD) for day windows, or an hour boundary (RFC 3339) for hour windows.

</Description>

</Field>

<Field name="data_as_of" type="nullable string" prefix="comparison.period.">

<Description>

The instant the statistics in this response are current to: events recorded up to roughly this time are reflected, while more recent events may not be yet. Statistics are served from a rolling aggregation that refreshes every few seconds, so a response is near-real-time but not live; use this field to label data freshness (for example "as of 14:03") rather than assuming the numbers are to-the-second. Null when the freshness boundary is not being reported.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="delivery" type="object" prefix="comparison." required>

<FieldChildren kind="response">

<Field name="accepted" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages accepted for sending after admission checks. This is the denominator for `delivery_rate` and `failure_rate`.

</Description>

</Field>

<Field name="sent" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages handed off to the carrier for delivery.

</Description>

</Field>

<Field name="delivered" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages the carrier confirmed as delivered to the handset.

</Description>

</Field>

<Field name="undelivered" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages the carrier reported as not delivered.

</Description>

</Field>

<Field name="failed" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages that failed during sending.

</Description>

</Field>

<Field name="rejected" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages rejected before any send attempt, for example by sending policy or a message-generation failure.

</Description>

</Field>

<Field name="expired" type="integer" prefix="comparison.delivery." required>

<Description>

Distinct messages that could not be delivered within their validity window and expired.

</Description>

</Field>

<Field name="delivery_rate" type="nullable number" prefix="comparison.delivery." required>

<Description>

Share of accepted messages that were delivered, computed as `delivered / accepted`. Null when no messages were accepted in scope.

</Description>

</Field>

<Field name="failure_rate" type="nullable number" prefix="comparison.delivery." required>

<Description>

Share of accepted messages that ultimately failed, computed as `(undelivered + failed + expired) / accepted`. Null when no messages were accepted in scope.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="latency" type="object" prefix="comparison." required>

<FieldChildren kind="response">

<Field name="processing" type="object" prefix="comparison.latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="comparison.latency.processing." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="comparison.latency.processing." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="comparison.latency.processing." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="delivery" type="object" prefix="comparison.latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="comparison.latency.delivery." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="comparison.latency.delivery." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="comparison.latency.delivery." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

<Field name="total" type="object" prefix="comparison.latency.">

<Description>

p50, p95, and p99 latency percentiles in milliseconds for one latency family over the scope. Percentiles are approximate (computed from a high-volume aggregation pipeline). All three are null together when no qualifying event contributed a latency measurement in scope.

</Description>

<FieldChildren kind="response">

<Field name="p50_ms" type="nullable integer" prefix="comparison.latency.total." required>

<Description>

Median (50th percentile) latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p95_ms" type="nullable integer" prefix="comparison.latency.total." required>

<Description>

95th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

<Field name="p99_ms" type="nullable integer" prefix="comparison.latency.total." required>

<Description>

99th percentile latency in milliseconds. Null when no qualifying event contributed a measurement.

</Description>

</Field>

</FieldChildren>

</Field>

</FieldChildren>

</Field>

<Field name="delta" type="object" prefix="comparison." required>

<FieldChildren kind="response">

<Field name="accepted_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in accepted messages (`delivery.accepted`) versus the previous period, as a signed fraction. Null when the previous period accepted none.

</Description>

</Field>

<Field name="sent_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in sent messages (`delivery.sent`) versus the previous period, as a signed fraction. Null when the previous period had none.

</Description>

</Field>

<Field name="delivered_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in delivered messages (`delivery.delivered`) versus the previous period, as a signed fraction. Null when the previous period delivered none.

</Description>

</Field>

<Field name="undelivered_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in undelivered messages (`delivery.undelivered`) versus the previous period, as a signed fraction. Null when the previous period had none.

</Description>

</Field>

<Field name="failed_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in failed messages (`delivery.failed`) versus the previous period, as a signed fraction. Null when the previous period had none.

</Description>

</Field>

<Field name="rejected_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in rejected messages (`delivery.rejected`) versus the previous period, as a signed fraction. Null when the previous period had none.

</Description>

</Field>

<Field name="expired_pct_change" type="nullable number" prefix="comparison.delta." required>

<Description>

Relative change in expired messages (`delivery.expired`) versus the previous period, as a signed fraction. Null when the previous period had none.

</Description>

</Field>

<Field name="delivery_rate_pp" type="nullable number" prefix="comparison.delta." required>

<Description>

Signed difference between this period's and the previous period's delivery rate, both fractions in [0,1] (multiply by 100 for percentage points). Null when either period's delivery rate is undefined.

</Description>

</Field>

<Field name="failure_rate_pp" type="nullable number" prefix="comparison.delta." required>

<Description>

Signed difference between this period's and the previous period's failure rate (multiply by 100 for percentage points). Unlike the delivery rate, the failure rate is not capped at 1. Its numerator sums undelivered, failed and expired, and a message that reaches more than one of those is counted in each, so the sum can exceed the messages accepted; counts are also approximate at high volume, which moves numerator and denominator independently. The difference can therefore fall outside [-1, 1]. Null when either period's failure rate is undefined.

</Description>

</Field>

</FieldChildren>

</Field>

</FieldChildren>

</Field>

</Payload>