---
"@context": https://schema.org
"@type": TechArticle
"@id": https://www.twilio.com/docs/usage/billing/usage-api-guide#article
headline: Usage API guide
description: Complete guide to the Twilio Billing Usage API, including OAuth authentication, query optimization, advanced filtering, and programmatic integration for cost tracking.
url: https://www.twilio.com/docs/usage/billing/usage-api-guide
inLanguage: en
dateModified: 2026-10-20T17:20:50.000Z
author:
  "@type": Organization
  name: Twilio Developer Education Team
publisher:
  "@type": Organization
  name: Twilio
---

# Usage API guide

The Billing Usage API provides comprehensive, invoice-aligned usage data for programmatic cost tracking and reporting. This guide covers authentication, query optimization, and advanced integration patterns.

## Authentication and OAuth setup

The Billing Usage API requires OAuth 2.0 authentication for all requests. All API requests must be authenticated using an OAuth access token.

### Register an OAuth application

Before generating a token, create an OAuth application in OneConsole to acquire your client credentials. The application type depends on the scope of the endpoints you intend to query:

* **Organization-level applications:** Required if you're querying Billing Group-level endpoints.
* **Account-level applications:** Required if you're querying Account level endpoints.

### Configure permission scopes

Ensure your application is explicitly configured with the following permission scope:

```text
twilio/billing-insights/usage/read
```

This scope grants read access to billing usage data at the appropriate level (organization or account).

### Generate an OAuth access token

Obtain an access token by submitting a request to the token endpoint using your client credentials. Include this access token in the `Authorization` header of every API request:

```text
Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN
```

## API capabilities

The Billing Usage API provides data you can reconcile with your invoice. It includes:

* **Structured JSON payloads:** Use `POST` requests with JSON request bodies to combine date, product, aggregation, and pagination filters for precise query customization.
* **Invoice-aligned product taxonomy:** The `productCategory` parameter aligns with the standardized, multi-level product taxonomy used in the Console and billing statements.
* **Separated usage and price data:** Response payloads clearly separate usage measurements and costs into distinct, structured objects for easier integration.
* **Predictable query ranges:** A custom date range can cover up to 365 days. Use explicit dates instead of legacy endpoints (such as `/Today` and `/Alltime`).
* **Token-based pagination:** Use `nextToken` from the response metadata to page through results, replacing legacy page indexing.
* **Standardized data freshness:** Data updates in predictable 24-hour batches, which keeps intra-month reporting consistent.

## Retrieve usage data by Billing Group

Billing Group usage data is retrieved through the Billing Usage API using two complementary methods:

| Method | URL endpoint                                                                        | Description                                                   |
| ------ | ----------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| POST   | `https://billing.twilio.com/v2/Public/Usage/BillingGroups/{billingGroupId}/Records` | Initiate a query with filter parameters in the request body.  |
| GET    | `https://billing.twilio.com/v2/Public/Usage/BillingGroups/{billingGroupId}/Records` | Paginate results using `pageToken` and `pageSize` parameters. |

Replace `{billingGroupId}` with the specific `billing_group_` string retrieved from the Console. This ensures the API correctly identifies the billing entity for which you are requesting records.

### Sample request structure

```text
POST https://billing.twilio.com/v2/Public/Usage/BillingGroups/{billingGroupId}/Records
```

The request body is a JSON object containing your filter parameters:

```json
{
  "startOn": "2025-01-01",
  "endOn": "2025-01-31",
  "productCategory": "sms",
  "aggregationPeriod": "DAILY",
  "pageSize": 100
}
```

## Query optimization: Request parameters and filtering

Precise data retrieval makes analysis more effective. By using request parameters, you can isolate specific cost drivers, filter by product categories, and define exact timeframes.

> \[!NOTE]
>
> The `timePeriod` parameter is an alternative to `startOn` and `endOn`. Do not use them in the same request.

### Parameter reference

| Parameter           | Type                                                       | Description                                                                                       |
| ------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `startOn`           | Date (`YYYY-MM-DD`)                                        | Filter usage from this date (inclusive). Maximum range is 365 days.                               |
| `endOn`             | Date (`YYYY-MM-DD`)                                        | Filter usage to this date (inclusive). Maximum range is 365 days.                                 |
| `timePeriod`        | Enum: `YESTERDAY`, `THIS_MONTH`, `LAST_MONTH`, `THIS_YEAR` | A predefined filter as an alternative to custom start and end dates.                              |
| `productCategory`   | String                                                     | Isolate usage data for a specific Twilio product category (for example, `sms`, `voice`, `video`). |
| `aggregationPeriod` | Enum: `DAILY`, `MONTHLY`                                   | Define how records are grouped within the requested range.                                        |
| `pageSize`          | Integer                                                    | Limit the number of items returned in a single response. Range is 1-1000.                         |
| `pageToken`         | String                                                     | Token from the previous response's `meta.nextToken` field to retrieve the next page of results.   |

### Choosing aggregation periods

The `aggregationPeriod` is a critical tool for financial granularity:

* **DAILY:** Identify specific usage spikes or trends within a month. Vital for spotting anomalies and understanding daily cost drivers. Use daily aggregation when investigating unexpected charges or tracking hour-to-hour changes.
* **MONTHLY:** Provides a high-level executive view of spend for period-over-period analysis.

### Query range limitations

> \[!WARNING]
>
> Queries are currently limited to a maximum date range of one month. If you attempt to request data spanning more than one month, the system will return an error or incomplete results. This is a temporary limitation while Twilio works to enhance system capabilities. Use `timePeriod` shortcuts (such as `THIS_MONTH` or `LAST_MONTH`) for month-long queries, or break larger date ranges into monthly chunks.

## Data interpretation: Analyzing the usage response

The Usage API returns structured output that maps technical usage metrics directly to costs. The response shows what was used, when it was used, and the associated price.

### Record properties

The API returns records with the following properties:

| Property          | Type                | Description                                                                                                                                                                 |
| ----------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `asOf`            | Date (`YYYY-MM-DD`) | The latest date/time for the records, formatted in UTC. This represents when the data snapshot was taken.                                                                   |
| `updatedOn`       | Date (`YYYY-MM-DD`) | The date the data was last updated, formatted in UTC. The latest value is typically the day before the request date because the current day's data is still being computed. |
| `productName`     | String              | A human-readable name of the Twilio product (for example, `United States-Outbound-LC-MMS`).                                                                                 |
| `productCategory` | String              | The standardized category for the product (for example, `united-states-outbound-lc-mms`).                                                                                   |
| `startOn`         | Date (`YYYY-MM-DD`) | The first date for which usage is included (UTC).                                                                                                                           |
| `endOn`           | Date (`YYYY-MM-DD`) | The last date for which usage is included (UTC).                                                                                                                            |
| `usage`           | Object              | Contains `amount` (numeric volume) and `unit` (metric type, such as segments, minutes, or messages).                                                                        |
| `price`           | Object              | Contains `amount` (total cost in the billing currency) and `currency` (ISO 4217 code, such as USD, GBP, EUR).                                                               |

### Example response

```json
{
  "updatedOn": "2025-01-31",
  "records": [
    {
      "productName": "United States-Outbound-LC-MMS",
      "productCategory": "united-states-outbound-lc-mms",
      "startOn": "2025-01-01",
      "endOn": "2025-01-31",
      "usage": {
        "amount": 66505,
        "unit": "segments"
      },
      "price": {
        "amount": 100.5,
        "currency": "USD"
      }
    },
    {
      "productName": "United States-Outbound-SMS",
      "productCategory": "united-states-outbound-sms",
      "startOn": "2025-01-01",
      "endOn": "2025-01-31",
      "usage": {
        "amount": 1250000,
        "unit": "messages"
      },
      "price": {
        "amount": 625.0,
        "currency": "USD"
      }
    }
  ],
  "meta": {
    "key": "records",
    "pageSize": 100,
    "previousToken": "eyJzdGFydE9uIjoiMjAyNS0wMS0wMSIsImVuZE9uIjoiMjAyNS0wMS0zMSIsInBhZ2UiOiIxIiwicGFnZVNpemUiOiIxMDAifQ",
    "nextToken": "eyJzdGFydE9uIjoiMjAyNS0wMS0wMSIsImVuZE9uIjoiMjAyNS0wMS0zMSIsInBhZ2UiOiIyIiwicGFnZVNpemUiOiIxMDAifQ"
  }
}
```

## Pagination strategies

For organizations with high volume usage, managing pagination is critical:

### Using page tokens

The `meta` section of the response contains:

* **`pageSize`:** The number of records returned in the current response.
* **`previousToken`:** Token to retrieve the previous page (if available).
* **`nextToken`:** Token to retrieve the next page (if available).

### Traversing results

To iterate through all records without missing data:

1. Execute your initial query with your desired filters.
2. Process the records returned in the `records` array.
3. If `meta.nextToken` is present, make another request with the same filters. Add `"pageToken": "NEXT_TOKEN"` to the request body, replacing *NEXT\_TOKEN* with the value of `meta.nextToken`.
4. Repeat until `meta.nextToken` is not present or is null.

This token-based pagination replaces legacy page-number indexing and lets you traverse large datasets reliably.

### Example pagination workflow

```json
// First request
{
  "startOn": "2025-01-01",
  "endOn": "2025-01-31",
  "pageSize": 100
}

// Response includes meta.nextToken

// Second request with pagination
{
  "startOn": "2025-01-01",
  "endOn": "2025-01-31",
  "pageSize": 100,
  "pageToken": "eyJzdGFydE9uIjoiMjAyNS0wMS0wMSIsImVuZE9uIjoiMjAyNS0wMS0zMSIsInBhZ2UiOiIyIiwicGFnZVNpemUiOiIxMDAifQ"
}
```

## Data considerations

### Data freshness

Usage data is updated in batches and may be up to 24 hours behind current activity. The latest available `updatedOn` value is typically the day before the request date because the current day's data is still being computed. This standardized cadence ensures every record reflects verified billing data, eliminating data drift and intra-day reconciliation discrepancies.

### Data accuracy

> \[!WARNING]
>
> Usage API data is an estimate. Actual billed usage is reflected on your invoice or usage statement after month-end. Use the Usage API for real-time cost tracking and internal reporting, but reconcile with your official invoice for final billing records.

## Related resources

* [Billing Groups](/docs/usage/billing/billing-group) — Basic guide to Billing Groups and finding your Billing Group ID.
* [Billing](/docs/usage/billing) — Overview of Twilio billing tools and resources.
* [Usage records API](/docs/usage/api/usage-record) — REST API reference for usage records.
* [Twilio Help Center: Billing](https://help.twilio.com/articles/360038270333) — General billing FAQs and account management.
* [Billing Group ID: Consolidated Billing and Usage Analytics](https://help.twilio.com/articles/49506588886299-Twilio-Billing-Group-ID-A-Guide-to-Consolidated-Billing-and-Usage-Analytics) — Detailed guide to Billing Group IDs and the Usage API.
