Usage
Metered usage aggregated per contract, metric and period, and how long it is kept.
Metered usage is ingested by your systems (or Fynex connectors), aggregated per contract, metric, and billing period, and rated into usage invoices at period close. This API exposes the aggregated view.
Endpoints
GET /billing-api/v1/contracts— the contracts visible to your key, the entry point for every per-contract read. Paged by ascending contract id: whilehasMoreis true, pass the returnednextCursorback ascursor.
{
"contracts": [
{
"contractId": 42,
"contractNumber": "UK2607AA",
"version": 1,
"sellerCustomerId": 7,
"currency": "EUR",
"status": "active",
"startDate": "2026-01-01",
"customerName": "Ada Lovelace",
"customerCompanyName": "Harbour Group BV"
}
],
"hasMore": false
}
GET /billing-api/v1/contracts/{contractId}/usage— the current open billing periods of every metric on the contract:
{
"contractId": 42,
"metrics": [
{
"metricName": "api_calls",
"used": "10250",
"includedUnits": "10000",
"capQuantity": "50000",
"capMode": "hard",
"percentOfCap": "20.5",
"percentOfPlan": "102.5",
"periodStart": "2026-08-01",
"periodEnd": "2026-08-31"
}
]
}
used counts everything metered this period; includedUnits is the
allotment.includedUnits of the metric price effective for the period — the
allowance the period close rates with (carried-over rollover units are not
added; a priced metric whose price includes nothing shows 0; an unpriced
metric, or one whose price cannot be read, falls back to its limit policy's
included units);
capQuantity/capMode describe the limit policy when one is configured. Quantities are decimal strings. An unknown contract id answers
404; a real contract with nothing metered answers 200 with an empty
metrics array.
Important
This is a live reading, not the figure the customer will be invoiced. The period is still open, so
usedmoves with every event that arrives — including events for work already done that reach us late. It is also pre-invoice: allowances, credits, discounts and rounding are applied when the period closes and the invoice is produced, and none of them are reflected here.Show it to a customer as "usage so far", never as an amount owed, and reconcile against the invoice the period produced rather than against this endpoint. A dashboard that quotes this number as the bill will disagree with the bill.
This endpoint reads a meter; something has to fill it. Writing usage —
registering a metric, pricing it, and sending events — happens under
/billing-api/v1/usage, with the same seller secret key, and is documented in
full under Usage ingestion. In short: POST /billing-api/v1/usage/metrics
to declare the meter, PUT
/billing-api/v1/usage/contracts/{contractId}/metrics/{metricName}/price to
price it, and POST /billing-api/v1/usage/events (or :batch, or /csv) to
report consumption.
What this endpoint keeps, and for how long
This is a meter, not a history API. It answers with the contract's currently open billing periods — one entry per metric with a limit policy or metered usage. It has no date range and no paging, and a period that has closed is no longer in the response. If you need consumption over time, record what you read while the period is open, or take it from the invoice the period produced: the invoice is the durable record of what was billed.
Stored events are retained indefinitely. Nothing prunes them — there is no retention window on ingested usage and no job that deletes it, so an idempotency key you used a year ago is still recognised and resending that event is still a no-op. Two practical consequences:
- Idempotency keys must stay unique for the lifetime of your integration, not just for a period. Derive them from something durable — a row id, an export digest — rather than from a timestamp that repeats.
- Correcting metered history is done by issuing a correction against the period (see Usage corrections), never by deleting events. There is no delete.
Documents are the exception: invoices and credit notes carry a statutory retention period per jurisdiction, which is a legal minimum on how long they are kept, not a window after which this endpoint stops answering.