Billing readiness
The fixed-period ledger of unique transmission days per enrollment, its tiers and pace states, the order reference, and the disclaimer that goes with all of it - evidence, never charges.
Evidence, not a charge
The ledger on this page presents evidence a billing team reconciles: which patient-local days carried a device reading, in which fixed period, against which configured bars. No route here records a charge state or an amount, and nothing in this product determines what may be charged. That determination belongs to the organization and its billing counsel.
The ledger
For every live program enrollment, the ledger divides time into fixed periods (30 days by default, never rolling), counts the patient-local calendar days in each period with at least one reading from the cellular device source, and labels the period by the bars the program configured. The calendar is evaluated in the patient's IANA timezone, and a reading counts on the day it was taken (device time), not the day it arrived.
Period one starts on the enrollment date by default, or on the first device reading on or after enrollment when the program says so; a first-transmission enrollment with no reading yet has no periods and is listed as omitted rather than silently missing.
Configuration
A program sets its bars in spec.billing_period; an absent block means the defaults, and the response echoes the configuration it used so a non-default program stays legible.
"billing_period": {
"period_days": 30,
"tier_low_min_days": 2,
"tier_high_min_days": 16,
"anchor": "enrollment"
}anchor is enrollment or first_transmission. A malformed block is reported as config_fell_back_to_defaults: true on every row it affects, and the defaults are used.
Tiers
tier | Meaning |
|---|---|
none | Fewer unique transmission days than the lower bar |
days_2_to_15 | The lower bar reached (default 2 days) and the upper bar not yet |
days_16_plus | The upper bar reached (default 16 days) |
The labels are fixed vocabulary; the thresholds that produce them are the program's. tier_reached_at, low_tier_reached_at and high_tier_reached_at carry the device time of the reading that crossed each bar.
Pace, for the current period only
The current period also carries where it stands against the upper bar today:
| Field | Meaning |
|---|---|
days_elapsed | Days of the period through today, today included |
days_remaining | Days of the period after today |
days_needed_for_high_tier | Unique days still needed to reach the upper bar; zero once reached |
high_tier_reachable | days_needed_for_high_tier <= days_remaining |
on_pace | Unique days so far are at or above the pro-rata share of the upper bar for the days elapsed, rounded up |
pace_state | One of three, exhaustive and disjoint |
pace_state | Meaning |
|---|---|
on_pace | At or ahead of the pro-rata share |
behind_reachable | Below the share, and the days remaining can still cover the days needed |
not_reachable | The days remaining cannot cover the days needed; this period is decided |
On the default configuration: three unique days on day 3 is on_pace (13 needed, 27 remaining); five unique days on day 15 is behind_reachable (11 needed, 15 remaining); five on day 20 is not_reachable (11 needed, 10 remaining); sixteen on day 30 is on_pace with nothing needed; fifteen on day 30 is not_reachable. A new period starts over.
The adherence nudge reads the same derivation: a patient is nudged only while behind_reachable; on_pace and not_reachable both end the evaluation with no message.
Routes
All four routes require a signed-in staff session on top of the key scope; developer keys alone and the patient SDK receive 403. They are environment-scoped, and every 200 carries Cache-Control: no-store because the bodies name patients.
GET /api/v1/billing-periods/current-period
The coordinator's view: the current period per live enrollment, narrowed by project_id and/or episode_profile_id, paged by limit (default 100, max 500) and offset. Rows are sorted behind_reachable first, then not_reachable, then on_pace, and within a state by fewest days remaining, so the patients a person can still help come first. Live enrollments with no current period yet are listed under omitted with reason no_current_period.
GET /api/v1/billing-periods/patients/{xuser_id}
Every enrollment ledger for one patient: the enrollment context and all of its periods.
GET /api/v1/billing-periods/programs/{episode_profile_id}/patients
One row per (patient, period) for a program, selected by period_index (1-based), by from and to (periods overlapping the range; either bound alone selects a day), or, by default, the current period. selection echoes which. omitted lists enrollments with no_reading_yet or no_period_in_selection.
PATCH /api/v1/billing-periods/enrollments/{enrollment_id}/order-reference
Body: { "order_reference": "<free text or an identifier from the clinic's own system>" }; null or blank clears it. Returns enrollment_id, order_reference, order_reference_missing. The reference is stored beside the enrollment and reported on every ledger row; its absence is reported (order_reference_missing: true), not treated as an error.
What each row carries
Per enrollment: enrollment_id, xuser_id, episode_profile_id, project_id, identifier and name (returned only to the authorized tenant), timezone, enrolled_at, revoked_at, setup_completed_at, consent_recorded_at and consent_missing (the earliest recorded consent grant for the patient; absent is reported, not an error), order_reference and order_reference_missing, config, config_fell_back_to_defaults, anchor_date.
Per period: period_index, period_start, period_end, unique_transmission_days, tier, the three reached-at times, device_identifiers (distinct devices that reported), device_classes (for example blood_pressure_cuff), device_replaced_in_period, first_reading_at, last_reading_at, is_current, and the pace fields above on the current period only.
In the dashboard
The RPM Adherence page reads GET /api/v1/billing-periods/current-period and nothing else: the current period per enrollment with its pace, sorted as above. What a coordinator sees is what the API returns.
Messaging and consent
SMS opt-in and decline, the consent ledger, STOP and START handling, the per-patient message budget, the identity disclosure, and what a program must have before it can text anyone.
API reference
The route list verified against the backend routers, grouped by task, with the key scope each needs, plus the generated OpenAPI document.