Download a CSV billing statement

GET https://emails.routeon.io/api/v1/billing/statement

Returns a raw text/csv file, not a JSON envelope. kind=summary (default) emits one aggregate row per activity group and covers at most 92 days; kind=messages emits one row per message and covers at most 31 days and 200,000 rows (a 422 is returned before any row data is fetched if the row count would exceed that limit). The actor column carries an email address only for users of the calling tenant; every other actor is reported as a fixed label. Recipient-level detail under kind=messages is only available for days still inside the tenant's message-log retention window; for pruned days the rows themselves remain (they are ledger-backed) but to_email, status and sent_at come back empty, and kind=summary — computed from the ledger, not from the message log — is unaffected. That window is unrelated to, and does not change, the 31-day span cap above.

Parameters

from string<date> required query
to string<date> required query

Inclusive.

kind string query
summary messages

Responses

200 CSV statement file
403 The caller has no tenant context.
422 The period exceeds the 92-day (summary) or 31-day (messages) span limit — `code: statement_period_too_long` — or, for `kind=messages`, the period's row count exceeds 200,000 — `code: statement_too_large`. Both are ordinary error envelopes carrying the code and its numeric limit under `meta.details` (e.g. `{ code: statement_too_large, rows: 240000, limit: 200000 }`). All other schema violations (bad date format, `to <= from`, unknown `kind`) return the same 422 with `meta.validation_error` instead.

Example response · 200

"string"