Sign in →

Billable Units

Define what you charge for — API calls, tokens, sessions, data, or any custom metric — with Aforo's billable units.

Updated 2026-07-29Suggest edits

Billable Units

Billable Units (internally called metrics) define what you charge for. They are the atomic measurement your usage events report against and your rate plans price.

Every charge in Aforo traces back to a billable unit — an API call, an LLM token, an active session, a volume of data, or a custom dimension you define.

Built-in templates

When you create a product, Aforo seeds a set of standard billable units for that product type. The tables below list what each type seeds.

ℹ

These templates are generated from the product-type descriptors — the same source the create wizard reads at runtime. If a name here ever looks off, the create wizard's list is authoritative.

Standard API

UnitAggregationMeasures
API CallsCOUNTTotal HTTP requests
Data TransferSUMOutbound response bytes (MB)
Active UsersCOUNT_DISTINCTDistinct callers
Compute TimeSUMTotal request latency (ms)
Error RequestsCOUNTFailed calls

AI Agent

UnitAggregationMeasures
Agent SessionsCOUNTDistinct agent runs
Agent StepsSUMReasoning / action steps
Tokens ConsumedSUMLLM tokens (a single combined token meter)
Agent Tool CallsCOUNTExternal tool invocations
Execution MinutesSUMAgent run time (minutes)
GPU HoursSUMGPU compute (GPU-hours)
Knowledge QueriesCOUNTKnowledge-base lookups
Tasks CompletedCOUNTCompleted tasks
Active AgentsMAXPeak concurrent agents
ℹ

AI Agent seeds a single Tokens Consumed meter, not separate input/output token meters. If you price prompt and completion tokens differently, add custom units for each — the split isn't a default.

MCP Server

UnitAggregationMeasures
MCP Tool CallsCOUNTtools/call requests
MCP Session DurationSUMSession time (minutes)
MCP Active SessionsMAXPeak concurrent sessions
MCP Connected AgentsCOUNT_DISTINCTDistinct agent identities
MCP Input TokensSUMPrompt tokens
MCP Output TokensSUMCompletion tokens
MCP ErrorsCOUNTFailed calls
MCP P95 LatencyPERCENTILE_95Tail latency (ms)

Agentic API

UnitAggregationMeasures
Agentic RequestsCOUNTAPI calls from agents
Agentic StepsSUMMulti-step sequence steps
Agentic Tool CallsCOUNTTool invocations
Agentic Input TokensSUMPrompt tokens
Agentic Output TokensSUMCompletion tokens
Agentic Compute TimeSUMRequest latency (ms)
Agentic Data TransferSUMResponse bytes (MB)
Agentic Active UsersCOUNT_DISTINCTDistinct callers

Aggregation types

How a unit rolls up the events it counts:

TypeDescriptionExample
COUNTNumber of eventsAPI calls
SUMTotal of a numeric fieldBytes transferred
COUNT_DISTINCTDistinct values of a fieldUnique users
MAXPeak value in the periodMax concurrent sessions
MINLowest value in the periodMin available capacity
AVGAverage of a numeric fieldAverage latency
LASTMost recent value seenLatest gauge reading
PERCENTILE_9595th percentileP95 response time

Unit type

Beyond how events aggregate, each billable unit has a unit type that says what its value measures:

TypeMeaningExample
COUNTCounts somethingAPI calls, requests, records
MONETARYA currency amount — transaction value / GMVOrder value, payment amount
DATAA volume of dataBytes, KB, MB, GB
TIMEA durationMilliseconds, seconds, compute time

Unit type defaults to COUNT. The one that changes pricing behavior is MONETARY: it marks the unit as a currency amount and carries a currency (e.g. USD). This is what Revenue Share (Percentage) pricing charges against — it bills a percentage of a MONETARY unit summed over the period (your GMV). Set the unit type to Monetary + a currency, and aggregate with SUM, before binding it to a Revenue Share rate plan.

⚠

Revenue Share on a non-monetary unit bills a percentage of a count, which is meaningless. Mark the unit MONETARY with a currency and SUM aggregation so the percentage applies to real money.

Custom billable units

Create a custom unit when a template doesn't fit your pricing model:

  1. Go to Catalog → Billable Units.
  2. Click New Billable Unit.
  3. Set:
    • Name — e.g. "Compute Minutes"
    • Unit Label — e.g. "minutes"
    • Unit Type — Count / Monetary / Data / Time (pick Monetary + a currency for Revenue Share units)
    • Aggregation — how events roll up (COUNT, SUM, COUNT_DISTINCT, …)
    • Event Field — the numeric field from your event payload to aggregate
    • Product Types — which product types can use this unit
⚠

You cannot change a unit's aggregation type once it's used in a rate plan — that would silently change what every bound plan bills. Create a new unit if you need a different aggregation.

Filtering

Custom units support filter conditions to narrow which events count. For example, count only API calls where status_code < 400:

{
  "filterConditions": [
    {
      "field": "status_code",
      "operator": "LESS_THAN",
      "value": "400"
    }
  ]
}

Supported operators: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, CONTAINS, NOT_CONTAINS, IN, NOT_IN, EXISTS, NOT_EXISTS.

Product associations

Billable units are associated with products many-to-many (product_metrics junction). A single unit like "Tokens Consumed" can price both your AI Agent product and your Agentic API product — change its definition once and every product using it picks it up.

Deletion protection

Like products, billable units are protected from deletion when they're referenced by active rate plans. The GET /api/v1/metrics/{id}/deletion-check returns ALLOW, WARN, or BLOCK; a BLOCK means you must migrate subscribers off the referencing plans first.

Archived units can be restored (POST /api/v1/metrics/{id}/restore), and any unit can be cloned (POST /api/v1/metrics/{id}/clone) as the starting point for a variant — cloning is a billable-unit feature, not a product one.

Bulk operations

Bulk create from templates

curl -X POST https://catalog.aforo.ai/api/v1/metrics/bulk \
  -H "Authorization: Bearer $AFORO_API_KEY" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -d '{ "productType": "AI_AGENT" }'

This seeds the standard templates for the product type in one call (nine for AI Agent, five for Standard API, eight each for MCP Server and Agentic API).

Export / import

Use export to back up your custom units or move them between workspaces. Export returns your custom, non-archived units only — the built-in templates are seeded fresh in every workspace (nothing to carry over), and archived units are left out since you're moving live configuration.

curl https://catalog.aforo.ai/api/v1/metrics/export \
  -H "Authorization: Bearer $AFORO_API_KEY" \
  -H "X-Tenant-Id: $TENANT_ID" > units.json

In the console (Billable Units → All Units) you can narrow what you export before downloading: check specific rows to export just those, export everything matching your current filters, or export all custom units. System defaults are never included.

Import is all-or-nothing. If any unit in the file collides with an existing name (active or archived), repeats another name in the same file, or fails validation, the whole import stops and nothing is written — the response lists every problem so you can fix the file and retry:

curl -X POST https://catalog.aforo.ai/api/v1/metrics/import \
  -H "Authorization: Bearer $AFORO_API_KEY" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -H "Content-Type: application/json" \
  --data @units.json

There's no skip-and-continue mode: a partial import would leave you guessing which units landed. Rename or remove the conflicts in the file, then import again.