More Tutorials

Show usage breakdowns by group-by attribute in your customer portal

Usage-based Billing

Overview

If you bill customers on usage with metered features on Chargebee Billing, you often want to show them inside your own product where that usage comes from: which projects, users, or models drove consumption this billing period, and how it trended over time.

This tutorial explains how to build those usage widgets using one Chargebee Billing read API: Retrieve usage summary for a subscription. The metered feature must have group-by attributes configured. You don't need a special portal API for this.

This is about your customer-facing UI, not Chargebee Billing's hosted self-serve portal. All Chargebee API calls must go through your backend.

Scope

This tutorial covers three use cases:

  1. Usage by project: a ranked view of how much each project used in the current billing period.
  2. Usage trend: a daily trend by project, for a chart.
  3. Team view: a filtered view that shows only the projects a team lead manages, split by model.

The examples group by project_id and model. The same pattern works with any group-by attribute configured on the metered feature, such as user_id or region.

It does not cover itemized usage PDFs for invoices, Usage Insights reports in Chargebee Billing, or Automatic Exports. For those, see Break down usage by group-by attributes.

Architecture overview

The flow splits responsibilities between your backend and Chargebee Billing as follows.

Your application:

  • Authenticates the signed-in customer and resolves their Chargebee subscription_id
  • Calls Chargebee Billing from your backend (never from the browser)
  • Shapes API responses into UI-ready payloads
  • Renders usage widgets in your product

Chargebee Billing:

  • Returns usage aggregated for a metered feature on a subscription over a timeframe
  • Returns one result for each unique combination of group-by attribute values
  • Optionally returns a time series, with one result per combination for each window

A typical flow:

  1. When the customer opens the usage page in your portal, your frontend calls your backend.
  2. Your backend calls Retrieve usage summary for a subscription, grouped by the attribute you want to show.
  3. Your backend labels and sorts the results and returns shaped JSON.
  4. Your frontend renders the table or chart.

Before you start

For this tutorial to work, you need the following setup:

  1. Enable Advanced Usage-Based Billing on your Chargebee Billing site.
  2. Add the group-by attributes that you want customers to see to your metered feature. In this tutorial, the Tokens metered feature aggregates usage as the Sum of tokens and is grouped by project_id, region, and model. To choose attributes, see Group-by attribute limits and best practices. Usage ingested before you add an attribute is reported under null for that attribute.
  3. Obtain an API key from your Chargebee Billing test site (subdomain ends in -test).
  4. Have a backend service that can call Chargebee REST APIs securely. The API authenticates with your site API key, which must never be exposed in the browser. The pattern throughout this guide is: your frontend calls your backend, your backend calls Chargebee, and you return a shaped response to the frontend. Every curl example below runs server-side.
  5. Be familiar with REST/JSON and the frontend framework of your choice. Formatting and layout are yours. This tutorial focuses on the data.

API at a glance

Use caseAPI callWhat it gives you
1. Usage by projectGET /subscriptions/{subscription_id}/usage_summary with group_byOne result per project for the timeframe
2. Usage trendThe same call with window_sizeOne result per project for each window
3. Team viewThe same call with an attributes filterResults limited to the attribute values you specify

Implementation steps

Follow these steps to power usage widgets in your customer portal.

Conventions used in the examples below:

  • Base URL: https://YOUR_CHARGEBEE_SUBDOMAIN.chargebee.com/api/v2/
  • Auth: HTTP Basic, with the API key as the username: -u YOUR_API_KEY:
  • Case sensitivity. Group-by attribute names and values are case-sensitive. Use them exactly as they appear in your usage events.
  • Timestamps. aggregated_from and aggregated_to are Unix timestamps in seconds (UTC). The start is inclusive and the end is exclusive.
  • Usage values are decimal strings. aggregated_value holds the aggregated usage as a string to preserve precision. Keep the string for storage and display. Before you sort, compare, or add usage values, parse the string with a decimal library. Don't use JavaScript +, <, or > on the raw string, and don't convert it with JavaScript Number.
  • List envelope. List responses use Chargebee's standard shape: { "list": [{ "usage_summary": { ... } }], "next_offset": "..." }. Response snippets below show the inner resource object unless noted.
  • Pagination. Every call in this tutorial can return more results than fit on one page. The endpoint returns 10 results per page by default, 100 maximum (limit). Pass the next_offset value from the previous response as offset in the next call, and repeat until the response has no next_offset. Collect every page before you sort, total, or render a view.

Use case 1: Usage by project

Goal: a ranked list of how much each project used in the current billing period, for example "proj_a used 1,250,000 tokens".

Call Retrieve usage summary for a subscription for the customer's subscription and the metered feature, with group_by[0] set to project_id. Without window_size, the response contains one aggregate per project for the whole reporting range. Without a timeframe, the range starts at the beginning of the subscription's current term and ends at the current time.

curl https://YOUR_CHARGEBEE_SUBDOMAIN.chargebee.com/api/v2/subscriptions/__test__8asukSOXdv6kOj/usage_summary -G \
  -u YOUR_API_KEY: \
  --data-urlencode "feature_id=Tokens" \
  --data-urlencode "group_by[0]=project_id"

Each list[].usage_summary looks like this (abridged):

{
  "feature_id": "Tokens",
  "aggregated_value": "1250000",
  "aggregated_from": 1748822400,
  "aggregated_to": 1751414400,
  "attributes": [
    { "name": "project_id", "value": "proj_a" }
  ]
}

A subscription with more than 10 projects returns them across several pages. Collect every page with next_offset before you rank the projects, or the table will leave some out.

Map each result to a row in your UI:

  • Project → attributes[0].value
  • Usage → aggregated_value (a decimal string; compare with a decimal library when you rank projects)
  • Period → aggregated_from to aggregated_to (Unix seconds; format as dates)

Label empty groups

Every event that the metered feature counts is placed in a group, so your results can include groups with no real value. Label them in your UI instead of showing raw null.

value in the responseWhat it meansSuggested label
nullThe event doesn't include the attribute, includes it with a null value, or includes the text NULL. Usage ingested before you added the attribute is also reported here.Unassigned
""The event includes the attribute with an empty string.(No value)

Use case 2: Usage trend

Goal: daily usage for each project, for a trend chart.

Add window_size to the same call. With window_size=day, the response contains one result for each project for each day in the reporting range. The supported window sizes are minute, hour, day, week, and month.

Windows start at timeframe_start and continue back to back until timeframe_end. They are aligned to timeframe_start, not to calendar boundaries. To align daily windows to calendar days, set timeframe_start to 00:00:00 UTC on the day you want.

curl https://YOUR_CHARGEBEE_SUBDOMAIN.chargebee.com/api/v2/subscriptions/__test__8asukSOXdv6kOj/usage_summary -G \
  -u YOUR_API_KEY: \
  --data-urlencode "feature_id=Tokens" \
  --data-urlencode "group_by[0]=project_id" \
  --data-urlencode "window_size=day" \
  --data-urlencode "timeframe_start=1748822400" \
  --data-urlencode "timeframe_end=1751414400"

The response contains one usage_summary for each project and day. Two consecutive days for the same project look like this (abridged):

[
  {
    "aggregated_value": "41000",
    "aggregated_from": 1748822400,
    "aggregated_to": 1748908800,
    "attributes": [{ "name": "project_id", "value": "proj_a" }]
  },
  {
    "aggregated_value": "38500",
    "aggregated_from": 1748908800,
    "aggregated_to": 1748995200,
    "attributes": [{ "name": "project_id", "value": "proj_a" }]
  }
]

Map each result to a point on your chart:

  • Series → attributes[0].value
  • X axis → aggregated_from
  • Y axis → aggregated_value

Use case 3: Team view

Goal: show a team lead only the projects they manage, and which models those projects use.

Add an attributes filter to the same call, and group by the attribute you want to show. This call filters to two projects and groups by model:

curl https://YOUR_CHARGEBEE_SUBDOMAIN.chargebee.com/api/v2/subscriptions/__test__8asukSOXdv6kOj/usage_summary -G \
  -u YOUR_API_KEY: \
  --data-urlencode "feature_id=Tokens" \
  --data-urlencode "group_by[0]=model" \
  --data-urlencode 'attributes[project_id][in]=["proj_a","proj_b"]'

Each list[].usage_summary looks like this (abridged):

{
  "feature_id": "Tokens",
  "aggregated_value": "720000",
  "aggregated_from": 1748822400,
  "aggregated_to": 1751414400,
  "attributes": [
    { "name": "model", "value": "model-a" }
  ]
}

The filter operators are:

OperatorValueExample
is, is_notA single valueattributes[project_id][is]=proj_a
in, not_inA JSON-encoded arrayattributes[project_id][in]=["proj_a","proj_b"]

You can filter on several attributes in the same call. The filters are combined with AND.

The filtered response is paginated in the same way. Collect every page with next_offset before you render the team view, so no model is left out.

Summary

In this tutorial, you learned how to:

  • Retrieve usage for a subscription grouped by a group-by attribute, and map the results to a ranked table.
  • Add window_size for a time series.
  • Collect every page with next_offset before you sort, total, or render a view.
  • Filter by attribute values to build views for a subset of projects.
  • Proxy all Chargebee Billing calls from your backend and shape responses for your frontend.

Reference

Was this tutorial helpful ?
Need more help?

We're always happy to help you with any questions you might have! Click here to reach out to us.