Skip to main content
GET
Subscription Billing one day's renewals, each with its risk band

Authorizations

Authorization
string
header
required

Bearer token authentication. Requires a company-admin token whose role holds reports.view.

Query Parameters

date
string
required

Calendar date to list, as YYYY-MM-DD. Required and not defaulted: the drawer is always opened from a day the operator picked, so a missing date would answer for a different day than the one on screen. A value that is not this exact shape, or one that names a date which does not exist, returns 400 rather than being coerced.

Pattern: ^\d{4}-\d{2}-\d{2}$
Example:

"2026-09-17"

country
string

ISO alpha-2 code of one of the requesting company's configured countries (see GET /countries). When present, every service on this endpoint filters its data to that country and reports money in the country's own currency. Omit (or send "all") for the aggregate-across-countries view, which is the default and matches pre-Phase-004 behavior. Unknown ISO codes or ones the company is not configured for return 400.

Example:

"US"

tz
string

IANA timezone name (e.g. America/Denver) or Rails-style alias (Eastern Time (US & Canada)) used to anchor "today" boundaries and hour-of-day bucketing. The frontend sends Intl.DateTimeFormat().resolvedOptions().timeZone. Unknown or malformed values silently fall back to UTC — callers omit the param when the endpoint doesn't need wall-clock alignment (see CURRENT-3077).

Example:

"America/Denver"

Free text narrowing the day. Matched against the customer's name or email, the product title, the variant's own label, the plan name, the subscription token, and the subscription number as an exact match. Every whitespace-separated term has to match one of them, so jane essentials means the customer and the product rather than either alone.

The variant label is the one term the subscriptions index's own search does not cover. It is searched under the name the variant gives itself rather than the name the row shows: a renewal is named by its product wherever that product has a title, and the Large or Blue an operator knows it by has to find it all the same. A renewal whose product has been discarded is still searchable, for the same reason it is still listed.

Applied over the whole day rather than over the page that would otherwise have been returned, so total_count counts what matched and the pager walks the matches.

Example:

"alvarez"

status
string

Comma-separated statuses to list, drawn from failed, at_risk, retrying, scheduled and cleared. Omitted means every status.

Each row reports its own status on day_status, and the counts behind the chips are on summary.status_counts. A value outside the set returns 400 rather than being ignored: dropping it would answer with the whole day while the caller believed it had filtered.

Example:

"failed,at_risk"

page
integer

1-based page number. Defaults to 1. Values below 1 are read as 1.

Required range: x >= 1
Example:

1

per_page
integer

Renewals per page. Defaults to 25 and is capped server-side at 100 — a day drawer is a working list rather than an export, and the band lookup costs one extra query per page whatever its size.

A larger value is clamped to the cap rather than rejected, so the cap is deliberately not declared as a schema maximum: doing so would publish a constraint the endpoint does not enforce. Read per_page off the response for the size actually applied.

Required range: x >= 1
Example:

25

Response

One page of the day's renewals

date
string<date>
required

The date the roster covers.

time_zone
string
required

Zone the scheduled half was bucketed in, echoed back so the drawer can label itself. The settled half ignores it: billing events carry an already-local date.

Example:

"America/Denver"

currency
string
required

ISO code every amount on the response is quoted in.

Example:

"USD"

page
integer
required

1-based page number this payload represents.

per_page
integer
required

Page size actually applied, after clamping.

total_count
integer
required

Renewals matching search and status across every page. Equal to the day's own count when neither is given; summary.renewal_count is always the day's, filtered or not.

summary
object
required

The day as a whole, independent of which page was requested and of search and status — computed over the day's full scope, so neither paging nor filtering changes what these figures describe.

Two figures the prototype's day panel showed are absent rather than estimated. A count of scheduled smart retries has no source: billing events carry no retry marker, and the only real fact is whether a retry is scheduled right now, which is per renewal. New against returning is split per customer and not per renewal, so it does not sum to renewal_count.

entries
object[]
required