Skip to main content

Overview

BoxBilling supports full usage-based billing. The pipeline works in three stages:
Events → Billable Metrics → Charges → Fees on Invoices
  1. Events are ingested via the API with a metric code, customer ID, and properties
  2. Billable Metrics define how events are aggregated (count, sum, max, etc.)
  3. Charges attach metrics to plans with a pricing model (standard, graduated, volume, etc.)
  4. Fees are calculated at invoice time based on aggregated usage

Ingesting events

Single event

curl -X POST /v1/events \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "txn_unique_123",
    "external_customer_id": "cust_001",
    "code": "api_calls",
    "timestamp": "2025-01-15T10:30:00Z",
    "properties": {
      "region": "us-east",
      "method": "POST",
      "bytes": 1024
    }
  }'

Batch ingestion

curl -X POST /v1/events/batch \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "transaction_id": "txn_1",
        "external_customer_id": "cust_001",
        "code": "api_calls",
        "timestamp": "2025-01-15T10:30:00Z",
        "properties": {"region": "us-east"}
      },
      {
        "transaction_id": "txn_2",
        "external_customer_id": "cust_001",
        "code": "api_calls",
        "timestamp": "2025-01-15T10:31:00Z",
        "properties": {"region": "eu-west"}
      }
    ]
  }'
  • Up to 100 events per batch
  • Events are idempotent — duplicate transaction_id values return the existing event
  • Rate limited per organization (default: 1000/minute, configurable)

ClickHouse acceleration

For high-volume event ingestion, enable ClickHouse by setting the CLICKHOUSE_URL environment variable. Events are dual-written to both the primary database and ClickHouse, with aggregation queries routed to ClickHouse for performance.

Billable metrics

Billable metrics define how raw events are aggregated into usage values.

Create a metric

curl -X POST /v1/billable_metrics \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "api_calls",
    "name": "API Calls",
    "aggregation_type": "count"
  }'

Aggregation types

TypeDescriptionRequires field_name
countNumber of eventsNo
sumSum of a numeric propertyYes
maxMaximum value of a propertyYes
unique_countCount of distinct property valuesYes
weighted_sumTime-weighted sum (proportional to duration)Yes
latestMost recent event’s valueYes
customCustom expression evaluationRequires expression

Example: sum aggregation

curl -X POST /v1/billable_metrics \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "data_transfer",
    "name": "Data Transfer (GB)",
    "aggregation_type": "sum",
    "field_name": "bytes",
    "rounding_function": "ceil",
    "rounding_precision": 0
  }'

Rounding

FunctionBehavior
roundHalf-up rounding
ceilRound up
floorRound down
Precision: 0–15 decimal places.

Filters

Filters segment events by property values, enabling different pricing per segment:
curl -X POST /v1/billable_metrics/api_calls/filters \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "region",
    "values": ["us-east", "us-west", "eu-west"]
  }'

Charge models

Charges connect billable metrics to plans with a pricing model. When creating a plan, include charges in the request:
curl -X POST /v1/plans \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "pro",
    "name": "Pro Plan",
    "interval": "monthly",
    "amount_cents": 9900,
    "charges": [
      {
        "billable_metric_id": "metric-uuid",
        "charge_model": "standard",
        "properties": {
          "unit_price": "0.01"
        }
      }
    ]
  }'

Available models

Standard

Simple per-unit pricing.
{
  "charge_model": "standard",
  "properties": {
    "unit_price": "0.01"
  }
}
Formula: amount = units × unit_price

Graduated

Tiered pricing where different unit ranges have different prices.
{
  "charge_model": "graduated",
  "properties": {
    "tiers": [
      {"from": 0, "to": 100, "unit_price": "0.10", "flat_fee": "0"},
      {"from": 101, "to": 1000, "unit_price": "0.05", "flat_fee": "0"},
      {"from": 1001, "to": null, "unit_price": "0.01", "flat_fee": "0"}
    ]
  }
}

Volume

The total units determine the per-unit price for all units.
{
  "charge_model": "volume",
  "properties": {
    "tiers": [
      {"from": 0, "to": 100, "unit_price": "0.10", "flat_fee": "0"},
      {"from": 101, "to": null, "unit_price": "0.05", "flat_fee": "0"}
    ]
  }
}

Package

Fixed price per block of units.
{
  "charge_model": "package",
  "properties": {
    "package_size": 10,
    "package_price": "50.00"
  }
}

Percentage

Percentage of a total amount.
{
  "charge_model": "percentage",
  "properties": {
    "rate": "2.5",
    "fixed_amount": "0.30"
  }
}

Graduated Percentage

Tiered percentage rates based on amount ranges.

Custom

Uses a custom expression for aggregation:
{
  "charge_model": "custom",
  "properties": {
    "expression": "cpu_seconds + memory_gb * 2"
  }
}

Dynamic

Per-event property-based pricing — each event is priced individually based on its properties.

Charge filters

Apply different pricing based on event properties:
{
  "charges": [
    {
      "billable_metric_id": "metric-uuid",
      "charge_model": "standard",
      "properties": {"unit_price": "0.01"},
      "filters": [
        {
          "billable_metric_filter_id": "filter-uuid",
          "values": ["us-east"],
          "properties": {"unit_price": "0.02"}
        }
      ]
    }
  ]
}
Events matching the filter values use the filter’s properties (here, 0.02/unitforuseast).Allothereventsusethebasechargeproperties(0.02/unit for `us-east`). All other events use the base charge properties (0.01/unit).

Usage thresholds

Trigger actions when cumulative usage crosses a monetary threshold within a billing period.

Create a threshold

# On a plan (applies to all subscriptions)
curl -X POST /v1/plans/{plan_code}/usage_thresholds \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_cents": 10000,
    "recurring": true
  }'

# On a specific subscription
curl -X POST /v1/subscriptions/{id}/usage_thresholds \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_cents": 5000,
    "recurring": false
  }'
When a threshold is crossed:
  1. A usage_threshold.crossed webhook is sent
  2. Progressive billing invoices can be generated for early collection

Check current usage

curl /v1/subscriptions/{id}/current_usage \
  -H "Authorization: Bearer $API_KEY"
Returns the current billing period’s aggregated usage amount.

Daily usage aggregation

A background task runs daily at 00:30 UTC to pre-aggregate usage data into the daily_usages table. This speeds up period-based usage queries for invoice generation and threshold checking.