Premium This is a Aviate feature.

Overview

Usage-based billing covers scenarios like API calls, AI tokens, compute hours, storage GB, and messages. Aviate metering lets you create billing meters, record raw usage events, and connect them to usage-based plans for automatic invoice generation.

The Kill Bill core usage APIs support recording rolled-up usage data, but aggregation must be performed outside Kill Bill. Aviate metering wraps these APIs with additional queuing, aggregation, and validation so that raw (non-aggregated) usage events can be submitted directly. Usage events submitted to Aviate are ultimately recorded in Kill Bill’s usage store for invoicing.

Prerequisites

Before using the metering APIs, ensure the following:

Key Concepts

Billing Meters

A BillingMeter defines what you are measuring — API calls, tokens, minutes, etc. Each meter has:

  • name — human-readable label (e.g. "API Calls")

  • code — unique identifier referenced when recording events

  • eventKey — the event type key

  • aggregationType — how events are rolled up (e.g. SUM)

  • eventFilters — optional string array (reserved for future use)

Usage Events

A UsageEvent represents a single usage data point. Each event contains:

  • billingMeterCode — the code of the associated billing meter

  • subscriptionId — the Kill Bill subscription ID

  • trackingId — used for idempotency; resubmitting events with the same tracking ID is safe

  • timestamp — ISO 8601 timestamp of the event

  • value — numeric quantity (e.g. 150 API calls, 10.5 minutes)

Warning
Events within the same submission must have ascending timestamp values. Out-of-order events are rejected. All usage points for a specific subscription must be submitted sequentially (not concurrently).

Aggregation

The aggregationType on a billing meter defines how events are rolled up for billing within each billing period:

  • SUM — totals all event values in the billing period (e.g. 150 + 200 = 350 API calls)

Relationship to Kill Bill Usage

Aviate metering replaces the Kill Bill usage APIs for recording data. You should use either the Kill Bill usage APIs (for pre-aggregated data) or the Aviate metering APIs (for raw events) — not both. Usage events submitted through Aviate are aggregated and then recorded in Kill Bill’s usage store, where they drive invoice generation.

For complete API details, see the Aviate Metering API reference.

Step-by-Step: Create a Meter and Record Usage

Step 1: Create a Billing Meter

Use POST /v1/metering/billingMeters to create one or more billing meters. The request body is an array, so you can create multiple meters in one call.

curl -v -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "X-Killbill-ApiKey: my-tenant" \
  -H "X-Killbill-ApiSecret: my-secret" \
  -d '[
    {
      "name": "API Calls",
      "code": "api_calls",
      "eventKey": "api_call",
      "aggregationType": "SUM"
    }
  ]' \
  http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/billingMeters

A successful response returns HTTP 200.

Step 2: Verify the Meter Exists

Retrieve a single meter by its code with GET /v1/metering/{meterCode}/billingMeter:

curl -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "X-Killbill-ApiKey: my-tenant" \
  -H "X-Killbill-ApiSecret: my-secret" \
  http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/api_calls/billingMeter

Expected response (JSON):

{
  "name": "API Calls",
  "code": "api_calls",
  "eventKey": "api_call",
  "aggregationType": "SUM"
}

Step 3: List All Billing Meters

Use GET /v1/metering/billingMeters/all to list every meter configured for the tenant:

curl -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "X-Killbill-ApiKey: my-tenant" \
  -H "X-Killbill-ApiSecret: my-secret" \
  http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/billingMeters/all

The response is a JSON array of all billing meters.

Step 4: Record Usage Events

Submit usage events with POST /v1/metering/billing/{accountId}. The request body is an array of events:

curl -v -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "X-Killbill-ApiKey: my-tenant" \
  -H "X-Killbill-ApiSecret: my-secret" \
  -d '[
    {
      "billingMeterCode": "api_calls",
      "subscriptionId": "f3b2a1d4-c5e6-7890-abcd-123456789abc",
      "trackingId": "batch-2026-02-14-001",
      "timestamp": "2026-02-14T10:00:00Z",
      "value": 150
    },
    {
      "billingMeterCode": "api_calls",
      "subscriptionId": "f3b2a1d4-c5e6-7890-abcd-123456789abc",
      "trackingId": "batch-2026-02-14-002",
      "timestamp": "2026-02-14T11:00:00Z",
      "value": 200
    }
  ]' \
  http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/billing/e5d3d5b5-4415-4166-b57f-33ca00a59e88
Important
Events within the same submission must have ascending timestamp values. The trackingId provides idempotency — resubmitting events with the same tracking ID is safe.

Step 5: Connect to Invoicing

Usage events are aggregated per billing period based on the meter’s aggregationType. When the subscription’s billing cycle runs, the aggregated value appears as a USAGE invoice item.

To make this work end-to-end:

  1. Create a billing meter (Step 1 above).

  2. Create a catalog with a usage-based plan that references the meter’s code (see Catalog Guide — Creating Usage Plans).

  3. Create a subscription for the account using that plan.

  4. Record usage events against the subscription.

  5. When the billing period closes, Kill Bill generates an invoice with a USAGE line item reflecting the aggregated total.

Delete a Billing Meter

Use DELETE /v1/metering/{meterCode}/billingMeter to remove a meter. If usage events already exist for the meter, you must pass force=true:

curl -v -X DELETE \
  -H "Authorization: Bearer ${ID_TOKEN}" \
  -H "X-Killbill-ApiKey: my-tenant" \
  -H "X-Killbill-ApiSecret: my-secret" \
  "http://127.0.0.1:8080/plugins/aviate-plugin/v1/metering/api_calls/billingMeter?force=true&accountId=e5d3d5b5-4415-4166-b57f-33ca00a59e88"
Important
Without force=true, attempting to delete a meter that has associated usage events will return an error.

What to Verify

After completing the steps above, confirm that:

  • The meter appears in the response from GET /v1/metering/billingMeters/all.

  • Usage events are accepted (HTTP 200 on the POST).

  • After the billing cycle runs, the invoice shows a USAGE line item with the aggregated amount.

  • The Kill Bill usage API (/1.0/kb/usages/) reflects the recorded events.

Common Pitfalls

  1. Submitting events out of chronological order — events are rejected if timestamps are not ascending.

  2. Using a billingMeterCode that does not exist — the API returns an error.

  3. Missing subscriptionId in usage events — events cannot be linked to billing.

  4. Forgetting to create a usage-based plan in the catalog — events are recorded but no invoice is generated.

  5. Deleting a meter without force=true when events exist — the API returns an error.