Skip to main content

Billing and usage

Your subscription has a monthly base and a metered seat-day price. CrossTrade computes seat-days from its own records and reports them to Stripe; you can read the same ledger.

What a seat-day is​

For each UTC day, CrossTrade counts the distinct members whose seat overlapped the day while your service was billable (active, or past_due within its grace period) for any positive length of time.

  • A day's count only grows while the day is open. A member whose seat ends during the day is still charged for that day; the seat drops out of the count on the next day. If you start a day with 100 seats, add 5 and then end 25, that day bills 105.
  • A seat that ends exactly at midnight is not charged for the next day.
  • A member revoked and reopened the same day counts once.
  • A suspension that starts at noon still charges that day; a day fully inside a suspension charges nothing, even after you pay and service resumes.
  • Once a payment is past due, the grace deadline is fixed at that moment and billing never extends past it, however late the housekeeping runs.

Each seat-day is charged to the calendar month that contains it.

The usage endpoint​

GET /v1/api/partner/usage?from=YYYY-MM-DD&to=YYYY-MM-DD uses a partner token with partner:read. See GET Usage for headers, query parameters and Python/JavaScript/cURL examples. Supply both dates or omit both. The requested range is inclusive and may span at most 92 days; only closed UTC days are returned. Without dates, the endpoint returns the current month's closed days. On the first of a month, the default list is empty with a total of zero and to is the previous month's last day.

{
"success": true,
"usage": {
"from": "2026-10-01",
"to": "2026-10-04",
"days": [
{
"day": "2026-10-01",
"quantity": 11,
"state": "accepted",
"delivery_state": "accepted",
"computed_at": "2026-10-02T00:20:03Z",
"accepted_at": "2026-10-02T00:20:04Z",
"reconciled_at": null,
"reconciliation_state": "pending",
"invoice": null,
"error": null,
"difference": null
},
{
"day": "2026-10-02",
"quantity": 0,
"state": "reconciled",
"delivery_state": "not_required",
"computed_at": "2026-10-03T00:20:01Z",
"accepted_at": null,
"reconciled_at": "2026-10-03T00:20:01Z",
"reconciliation_state": "matched",
"invoice": null,
"error": null,
"difference": null
},
{
"day": "2026-10-03",
"quantity": 13,
"state": "accepted",
"delivery_state": "accepted",
"computed_at": "2026-10-04T00:20:02Z",
"accepted_at": "2026-10-04T00:20:03Z",
"reconciled_at": null,
"reconciliation_state": "pending",
"invoice": null,
"error": null,
"difference": null
},
{
"day": "2026-10-04",
"quantity": null,
"state": "pending_computation",
"delivery_state": "pending",
"computed_at": null,
"accepted_at": null,
"reconciled_at": null,
"reconciliation_state": "pending",
"invoice": null,
"error": null,
"difference": null
}
],
"total": 24,
"total_is_estimate": true,
"open_seats": 12,
"as_of": "2026-10-05T00:10:05Z"
},
"meta": {
"requestId": "preq_b1c2d3e4f5a60718"
}
}
FieldMeaning
from, toThe inclusive window actually answered; to never reaches the open day
days[].dayThe UTC day
days[].quantitySeat-days billed for that day; null while pending_computation
days[].stateThe ledger state of the day, listed below
days[].delivery_statepending, accepted (Stripe's meter took it), not_required (zero seats), or the ledger state while sending
days[].computed_at, accepted_at, reconciled_atWhen the day was frozen, accepted by Stripe, and reconciled against Stripe's daily meter summary (zero-seat days reconcile locally)
days[].reconciliation_statepending, matched or mismatch. Meter reconciliation and later invoice checks can identify discrepancies
days[].invoiceReconciled invoice reference (id, quantity, period_start, period_end), or null. Its quantity describes the invoice period, not necessarily this one day's seats
days[].errorThe last send error for the day, null when none
days[].differenceInvoice-period quantity minus the ledger total for that period once compared, null before
totalSum of the known quantities in the window; pending computation contributes zero to this sum, not proof of zero usage
total_is_estimatetrue until every day in the window is reconciled
open_seatsSeats open at report time; future usage depends on later seat and service-state changes
as_ofWhen the report was built

States per day: computed (frozen, not yet sent), submitting, accepted (Stripe took the event; daily meter reconciliation is pending), reconciled, unknown (the send result is uncertain and checked against meter evidence before any retry), rejected, manual_review. A zero-seat day is reconciled with delivery_state: not_required. Days not yet computed appear as pending_computation, never as zeros.

total_is_estimate becomes false when every returned day is reconciled; this can happen before an invoice exists. Later invoice checks compare metered quantities for the invoice period and can flag discrepancies. Invoice totals can also include the base fee, taxes and discounts.