Usage & Metering
Usage-based billing metrics for hosted services.
This capability lets a central billing system (typically the OBAPI client) pull consumption metrics from any hosted service (mail hosting, proxy, storage, Nextcloud, etc.) in a normalized way, without knowing the service internals.
The design is self-describing in two steps:
- The server declares which metrics it exposes (
GET /obapi/v1/usage/metrics). - The client asks for the values of those metrics for one account over a
period (
GET /obapi/v1/usage).
A service that only implements this capability is a valid minimal OBAPI server:
its discovery response lists ["usage"] and nothing else.
Metric catalog
- Method:
GET /obapi/v1/usage/metrics - Headers:
Authorization: Bearer {apikey}
Returns the list of metrics this server can measure. This endpoint takes no account parameter: it describes the service, not a specific customer.
{
"metrics": [
{
"code": "storage_bytes",
"label": "Storage used",
"description": "Total disk space occupied by the account",
"unit": "byte",
"kind": "gauge",
"aggregation": "last",
"billable": true,
"product_ref": "NC-STORAGE"
},
{
"code": "user_count",
"label": "Number of users",
"unit": "count",
"kind": "gauge",
"aggregation": "max",
"billable": true,
"product_ref": "NC-USER"
},
{
"code": "bandwidth_bytes",
"label": "Bandwidth consumed",
"unit": "byte",
"kind": "counter",
"aggregation": "sum",
"billable": true,
"product_ref": "PROXY-TRAFFIC"
}
]
}
Metric object
| Field | Type | Description |
|---|---|---|
code |
string | Stable machine identifier of the metric (see standard vocabulary below) |
label |
string | Human-readable name |
description |
string | Optional longer description |
unit |
string | Measurement unit, always an SI base unit (byte, count, second) |
kind |
string | gauge (point-in-time value) or counter (accumulated over the period) |
aggregation |
string | How to reduce the metric over a period: last, max, avg, sum |
billable |
boolean | Hint: this metric is meant to drive billing |
product_ref |
string | Optional. Product/service reference the metric maps to, for automatic line mapping |
gauge vs counter
The distinction is essential to bill correctly over a period:
- gauge -- a value that exists at a point in time (storage used, number of
users). The server states how to reduce it over the period through
aggregation(last= value at end of period,max= peak,avg= average). - counter -- a value accumulated during the period (bandwidth, sent emails).
It is naturally reduced with
aggregation: "sum".
The client MUST honor the declared aggregation and never guess.
Units
Units are always expressed as SI base units, never as multiples, so any tool can convert consistently:
| Unit | Meaning |
|---|---|
byte |
bytes (not KB / MB / GB) |
count |
a plain integer count |
second |
seconds (not minutes / hours) |
Standard metric vocabulary
To let tools auto-map metrics to products, common metrics SHOULD reuse these
code values. Services MAY expose additional custom metrics prefixed with
x- (for example x-antispam_rules).
| Code | Unit | Typical kind | Description |
|---|---|---|---|
storage_bytes |
byte |
gauge | Disk space occupied |
bandwidth_bytes |
byte |
counter | Network traffic over the period |
user_count |
count |
gauge | Number of user accounts |
mailbox_count |
count |
gauge | Number of mailboxes |
mailbox_quota_bytes |
byte |
gauge | Total mailbox quota allocated |
email_sent_count |
count |
counter | Emails sent over the period |
request_count |
count |
counter | Requests served over the period |
compute_seconds |
second |
counter | Compute time consumed |
Metric values for an account
- Method:
GET /obapi/v1/usage - Headers:
Authorization: Bearer {apikey}
| Parameter | Type | Required | Description |
|---|---|---|---|
account |
string | yes | Account identifier -- the customer email address on the service |
period |
string | no | Billing period YYYY-MM (default: current month) |
metrics |
string | no | Comma-separated list of metric codes to restrict the response |
Account identification
The account parameter is the email address of the customer account on the
service. It is the natural business key for mail, storage and proxy hosting, and
the central billing system already knows it from the customer record.
A customer holding several accounts on the same service (several mailboxes, several users) is represented as several accounts: one request per account. The central system is responsible for summing per-customer if needed.
Response
{
"account": "client@example.com",
"period": {
"start": "2026-06-01",
"end": "2026-06-30",
"granularity": "month"
},
"measures": [
{
"code": "storage_bytes",
"value": "48318382080",
"unit": "byte",
"captured_at": "2026-06-30T23:59:59Z"
},
{
"code": "user_count",
"value": "12",
"unit": "count"
},
{
"code": "bandwidth_bytes",
"value": "912680550400",
"unit": "byte"
}
]
}
Measure object
| Field | Type | Description |
|---|---|---|
code |
string | Metric code, matching a code from the catalog |
value |
string | Value as a decimal string (never a float) in the metric unit |
unit |
string | Unit of the value, echoed from the catalog |
captured_at |
string | Optional. ISO 8601 timestamp when a gauge value was read |
Errors
If the account is unknown to the service:
{
"error": {
"type": "not_found",
"code": "ACCOUNT_NOT_FOUND",
"message": "No account matches the provided identifier"
}
}
Reference implementation
A single-file PHP example implementing this capability on top of a Nextcloud
instance is available in the repository: examples/usage-nextcloud.php. It is a
complete minimal OBAPI server (discovery + usage only, no dependency but curl)
that maps a customer account (email) to a Nextcloud group and reports the group's
total storage used and user count via the OCS Provisioning API.
Example calls:
GET / -> { "capabilities": ["usage"], ... }
GET /usage/metrics -> { "metrics": [ storage_bytes, user_count ] }
GET /usage?account=client@example.com&period=2026-06
-> { "measures": [ ... ] }