# Usage

Raw voice, SMS and data records as one chronological feed, granular enough to bill on.

> Partner API · https://developer.telgea.com/docs/partner/api/usage

## The usage record object {#object}

Retrieve raw voice, SMS, and data usage records for billing and suspension.

| Field | Type | Description |
| --- | --- | --- |
| `id` | string (required) | Identifier of this usage record. Stable, so you can deduplicate across pages. Example: `"cdr_01j9v2k8f3m4n5p6q7r8s9t0u1"` |
| `type` | enum (required) | What was metered. `UNKNOWN` is a record the network sent us that we could not classify. One of: `VOICE`, `SMS`, `MMS`, `DATA`, `UNKNOWN`. Example: `"DATA"` |
| `provider` | string (required) | The network that reported this usage. Example: `"telia-denmark"` |
| `msisdn` | string (required) | The number the usage was recorded against, in E.164 format. Example: `"+4520123456"` |
| `timeStarted` | string (required) | When the session or message started, ISO 8601 UTC. Example: `"2026-09-11T08:30:00.000Z"` |
| `timeEnded` | string (required) | When it ended, ISO 8601 UTC. Null for records the network reports without a duration. Example: `"2026-09-11T08:34:12.000Z"` |
| `amount` | number (required) | Usage quantity, expressed in `unit`. Example: `10485760` |
| `unit` | enum (required) | What `amount` counts: seconds for voice, count for messages, bytes for data. One of: `seconds`, `count`, `bytes`. Example: `"bytes"` |
| `servingCountryCode` | string (required) | ISO-2 country serving the subscriber. Example: `"DK"` |
| `usageClass` | enum (required) | Where the usage sat relative to the home market. One of: `domestic`, `roaming`, `international`. Example: `"domestic"` |
| `counterpartyMsisdn` | string (required) | Communication records only. Example: `"+4598765432"` |
| `callDirection` | enum (required) | Which way the call or message went. Null for data. One of: `inbound`, `outbound`. Example: `"outbound"` |
| `counterpartyCountryCode` | string (required) | ISO-2 country of the other party. Null for data. Example: `"DK"` |
| `networkType` | string (required) | Data records only. Example: `"5G"` |
| `userId` | string (required) | The end-user this usage belongs to, or null when the number is not attached to one. Example: `"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"` |
| `date` | string (required) | Calendar day the usage is billed under, YYYY-MM-DD. Example: `"2026-09-11"` |
| `totalPrice` | string (required) | What this record costs, as a decimal string so no precision is lost. A connected voice call may also carry a one-off connection fee, which is included here and is not derivable from unitPrice. Null until the record is rated, and on usage covered by a pool. Example: `"0.043200"` |
| `unitPrice` | string (required) | The rate applied, as a decimal string. Priced per minute for voice, per binary megabyte (1024²) for data, and per message for SMS and MMS — so for voice and data this is not the same unit `amount` is counted in. Null until the record is rated. Example: `"0.004320"` |
| `currency` | string (required) | ISO 4217 currency of the prices. Null until rated. Example: `"EUR"` |
| `rateId` | string (required) | The rate that priced this record, for reconciling a bill line by line. Null until rated. Example: `"rate_01j9v2k8f3m4n5p6q7r8s9t0u1"` |

## Operations

- `GET` [List usage records](#list-usage-records)

### List usage records {#list-usage-records}

`GET /v1/usage` · Enterprise API + Partner API

Returns raw voice, SMS, and data usage records for your organization whose `timeStarted` falls between `startDate` and `endDate`, as one feed — you do not need to know that we store calls and data separately. Records come in the order we stored or last corrected them, not by `timeStarted`.

Walk a period with the opaque `cursor`: send the first request with a `startDate`/`endDate`, then keep passing the `nextCursor` from each response until `hasMore` is `false`. Filter to one subscriber with `userId`.

Records are granular enough to bill on. Each arrives once the network reports it, from minutes to days after the usage depending on the market, and keeps its original `timeStarted`; a record we correct later comes round again with the same `id`. To poll incrementally, keep the `cursor` you sent for the last page and send it again, with the same window, on the next poll: you receive everything stored or corrected since, including records whose `timeStarted` is earlier than any you have seen. De-duplicate on `id`, keeping the latest copy. Records written in the last few minutes are held back until they settle. Expect usage from the last 24–48 hours to keep changing as late records arrive and are rated; the cursor delivers those updates.

**Polling budget.** Each API key allows 1000 requests per 24 hours, shared across every endpoint. Walk a whole organisation with the default page size rather than polling per subscriber — a request over the budget returns `429`.

Requires the permission `consumption:read` on the key.

[Try it in the playground](https://developer.telgea.com/playground#tag/usage/GET/v1/usage). Calls run against your live organization; there is no sandbox.

**Parameters**

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `startDate` | query | string (date) (required) | Inclusive start of the usage window (YYYY-MM-DD, UTC). Example: `2026-09-01` |
| `endDate` | query | string (date) (required) | Inclusive end of the usage window (YYYY-MM-DD, UTC). The window may span at most 31 days. Example: `2026-09-30` |
| `pageSize` | query | integer | Records per page (max 100) Example: `50` |
| `cursor` | query | string | Opaque cursor from a previous response's nextCursor. Omit for the first page. Example: `eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ` |
| `userId` | query | string (uuid) | Restrict to one end-user your organization owns. Omit for every user. Example: `9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01` |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| `200` | A page of usage records with a forward cursor. | `UsageFeedResponse` |
| `400` | Invalid cursor, a query window wider than the published maximum, or schema validation | none |
| `401` | Missing or invalid API key in the X-API-Key header | `UnauthorizedError` |
| `403` | The API key lacks the consumption:read scope | `ForbiddenError` |
| `429` | The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets. | `TooManyRequestsError` |
| `500` | Internal server error. Contact support if this persists. | `InternalError` |

**Response fields (200, UsageFeedResponse)**

| Field | Type | Description |
| --- | --- | --- |
| `items` | array of UsageRecord (required) | Usage records on this page, in the order they were stored or last corrected. |
| `items.id` | string (required) | Identifier of this usage record. Stable, so you can deduplicate across pages. Example: `"cdr_01j9v2k8f3m4n5p6q7r8s9t0u1"` |
| `items.type` | enum (required) | What was metered. `UNKNOWN` is a record the network sent us that we could not classify. One of: `VOICE`, `SMS`, `MMS`, `DATA`, `UNKNOWN`. Example: `"DATA"` |
| `items.provider` | string (required) | The network that reported this usage. Example: `"telia-denmark"` |
| `items.msisdn` | string (required) | The number the usage was recorded against, in E.164 format. Example: `"+4520123456"` |
| `items.timeStarted` | string (required) | When the session or message started, ISO 8601 UTC. Example: `"2026-09-11T08:30:00.000Z"` |
| `items.timeEnded` | string (required) | When it ended, ISO 8601 UTC. Null for records the network reports without a duration. Example: `"2026-09-11T08:34:12.000Z"` |
| `items.amount` | number (required) | Usage quantity, expressed in `unit`. Example: `10485760` |
| `items.unit` | enum (required) | What `amount` counts: seconds for voice, count for messages, bytes for data. One of: `seconds`, `count`, `bytes`. Example: `"bytes"` |
| `items.servingCountryCode` | string (required) | ISO-2 country serving the subscriber. Example: `"DK"` |
| `items.usageClass` | enum (required) | Where the usage sat relative to the home market. One of: `domestic`, `roaming`, `international`. Example: `"domestic"` |
| `items.counterpartyMsisdn` | string (required) | Communication records only. Example: `"+4598765432"` |
| `items.callDirection` | enum (required) | Which way the call or message went. Null for data. One of: `inbound`, `outbound`. Example: `"outbound"` |
| `items.counterpartyCountryCode` | string (required) | ISO-2 country of the other party. Null for data. Example: `"DK"` |
| `items.networkType` | string (required) | Data records only. Example: `"5G"` |
| `items.userId` | string (required) | The end-user this usage belongs to, or null when the number is not attached to one. Example: `"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"` |
| `items.date` | string (required) | Calendar day the usage is billed under, YYYY-MM-DD. Example: `"2026-09-11"` |
| `items.totalPrice` | string (required) | What this record costs, as a decimal string so no precision is lost. A connected voice call may also carry a one-off connection fee, which is included here and is not derivable from unitPrice. Null until the record is rated, and on usage covered by a pool. Example: `"0.043200"` |
| `items.unitPrice` | string (required) | The rate applied, as a decimal string. Priced per minute for voice, per binary megabyte (1024²) for data, and per message for SMS and MMS — so for voice and data this is not the same unit `amount` is counted in. Null until the record is rated. Example: `"0.004320"` |
| `items.currency` | string (required) | ISO 4217 currency of the prices. Null until rated. Example: `"EUR"` |
| `items.rateId` | string (required) | The rate that priced this record, for reconciling a bill line by line. Null until rated. Example: `"rate_01j9v2k8f3m4n5p6q7r8s9t0u1"` |
| `nextCursor` | string (required) | Pass as `cursor` to fetch the next page; null once the feed is exhausted. To pick up later changes, resend the cursor that fetched the last page. Example: `"eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ"` |
| `hasMore` | boolean (required) | Whether another page follows. Equivalent to nextCursor being non-null. Example: `true` |

**Example request**

```bash
curl -X GET "https://api.telgea.com/v1/usage" \
  -H "x-api-key: $TELGEA_API_KEY"
```

**Response 200**

```json
{
  "items": [
    {
      "id": "cdr_01j9v2k8f3m4n5p6q7r8s9t0u1",
      "type": "DATA",
      "provider": "telia-denmark",
      "msisdn": "+4520123456",
      "timeStarted": "2026-09-11T08:30:00.000Z",
      "timeEnded": "2026-09-11T08:34:12.000Z",
      "amount": 10485760,
      "unit": "bytes",
      "servingCountryCode": "DK",
      "usageClass": "domestic",
      "counterpartyMsisdn": null,
      "callDirection": null,
      "counterpartyCountryCode": null,
      "networkType": "5G",
      "userId": "9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01",
      "date": "2026-09-11",
      "totalPrice": "0.043200",
      "unitPrice": "0.004320",
      "currency": "EUR",
      "rateId": "rate_01j9v2k8f3m4n5p6q7r8s9t0u1"
    }
  ],
  "nextCursor": "eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ",
  "hasMore": true
}
```
