Rate Plans
Configure usage-based pricing with eight pricing models — pay per use, flat rate, percentage, included quota, graduated, volume-tiered, staircase, and outcome-based — plus per-dimension pricing for tools and endpoints.
Rate Plans
Rate Plans (also called Rate Cards) define how much you charge for each billable unit. A single rate plan can price multiple products and multiple billable units, each with its own pricing model, tiers, limits, and rollover settings.
Pricing Models
Aforo supports eight pricing models:
Pay Per Use
The simplest model (API value PER_UNIT). Charge a fixed price per unit consumed, after subtracting any included free quota.
charge = max(0, quantity - includedFree) × ratePerUnit
Best for: API call charging, token metering, event counting.
Flat Rate
A fixed charge regardless of usage. Typically used as a base fee on top of usage charges.
charge = flatRate
Best for: Platform access fees, monthly minimums.
Percentage (Revenue Share)
Best when you take a cut of money that flows through your product — payments, marketplaces, commissions. You charge a percentage of a transaction amount, with an optional minimum floor.
charge = max(minFee, transactionAmount × ratePercent / 100)
The ratePercent is a percent, not a multiplier: 2.9 means 2.9%, and it's validated to be between 0 and 100. A single order of $500 at 2.9% bills $14.50.
How the amount reaches Aforo. Revenue Share prices a monetary quantity, so you send the transaction amount as the event quantity, and the metric aggregates it with SUM over the billing period — the period total is your GMV. Your monthly charge is ratePercent% of that GMV.
# Each transaction reports its dollar value as quantity:
curl -X POST https://api.aforo.ai/v1/ingest \
-H "X-API-Key: $AFORO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"cus_123","metricName":"transaction_value","quantity":500.00,"occurredAt":"2026-07-01T10:00:00Z","idempotencyKey":"order_8841"}'
# Period GMV = SUM of all quantities. 2.9% of a $250,000 month = $7,250.
Revenue Share charges a percent of a money amount, not of a count. Put 2.9% on a count metric like "API Calls" and you'd bill 2.9% of a call count — a meaningless number. Bind Revenue Share to a Monetary billable unit aggregated with SUM (mark the unit's type as Monetary and give it a currency). The rate-plan builder warns you when the bound unit isn't Monetary + Sum.
Best for: Payment processing, revenue share, marketplace commissions.
Included Quota
Free up to a quota, then charge for overages. Supports both per-unit and block pricing for overages.
Per-unit overage:
charge = max(0, quantity - includedFree) × overageRate
Block overage (when blockSize is set):
charge = ceil(max(0, quantity - includedFree) / blockSize) × overageRate
Best for: Freemium tiers, API plans with monthly credits.
Graduated
Each tier is priced independently. Units in tier 1 are charged at tier 1's rate, units in tier 2 at tier 2's rate, etc.
For 15,000 units: (1,000 × $0.010) + (9,000 × $0.008) + (5,000 × $0.005) = $10 + $72 + $25 = $107
Best for: Volume-sensitive pricing where large consumers should pay a blended rate.
Volume Tiered
The entire volume is charged at the rate of the tier where the total falls.
For 15,000 units (falls in tier 3): 15,000 × $0.005 = $75
Best for: Simple quantity discounts, wholesale pricing.
Staircase
A flat package price for whichever tier the total lands in — you pay the tier's fixed amount outright, not a per-unit rate. (Contrast with Volume Tiered, which multiplies the whole volume by the tier's unit rate.)
Best for: Packaged plans where each tier is a named bundle — "up to 10k calls = $99, up to 100k = $499".
Outcome-Based
Charge by the outcome of the work, not the raw count. Each event carries an execution outcome (e.g. SUCCESS, ERROR, TIMEOUT, PARTIAL) and you assign a weight (0.0–1.0) per outcome, so a failed call can bill at a fraction — or nothing.
Best for: AI agents and workflows where you only want to charge for work that actually succeeded.
In the rate plan wizard, pick Outcome-Based on a billable unit's Pricing tab, set the rate per billed unit, then set a weight per outcome. The wizard lists the outcomes integrations report most often — SUCCESS, PARTIAL, TIMEOUT, ERROR, VALIDATION_FAILED, BLOCKED and CANCELLED — and starts them at 1.0 for success, 0.5 for partial and 0 for the rest. More outcomes holds the remaining four (FAILED, FAILURE, PENDING, HITL_REQUIRED), blank by default. A blank weight isn't saved, so that status bills at full price (1.0). At least one saved weight must be above 0. Billing multiplies each outcome's units by its weight, adds them up, and prices the total like Pay Per Use, so included free units, block size and minimum fee all still apply.
Outcome weighting needs a billable unit aggregated with SUM or COUNT. A COUNT unit weights the number of events per outcome; a SUM unit weights the summed quantity. Saving an Outcome-Based plan on a MAX, AVG or UNIQUE unit is rejected with 400 Outcome-based pricing needs a SUM or COUNT billable unit; <name> uses <AGG>.
For example, 1,000 agent calls in a month, weighted success 1.0, partial 0.5, timeout 0.25, error 0:
At $0.02 per billed unit, that's $18.55 instead of $20.00.
Weights are read from each event's executionStatus. An event sent without a status, or with a status you didn't give a weight, bills at full price (1.0). If your integration doesn't set executionStatus, outcome-based pricing behaves exactly like Pay Per Use — see Sending outcomes. Gateways report BLOCKED for 401, 403 and 429 and CANCELLED for 499. The wizard starts both at 0, but a plan saved before they were added to the wizard (September 30, 2026) has no weight for them, so those calls bill at 1.0 until you open the plan and enter a weight, or set one through the API (below).
Every weight must be between 0 and 1, and at least one must be above 0. To make a billable unit free, use Pay Per Use with a $0 rate instead. Status keys are case-insensitive; Aforo stores them upper-cased.
Reading the invoice line
Each Outcome-Based charge shows the billed units, the raw units and the split, so a customer can check the bill against their own call counts:
Agent calls usage — 927.5 billed of 1000 (SUCCESS 900 × 1, PARTIAL 40 × 0.5, TIMEOUT 30 × 0.25, ERROR 30 × 0)
Events that arrived without a status appear as no status 20 × 1. To reconcile: add up the units × weight products — that's the first number — then subtract included free units and multiply by the rate. Very long breakdowns are cut at 512 characters and end in …).
Previewing a plan
Your invoice uses the real split of outcomes, but a preview can't know it yet:
- Bill simulator (wizard). Enter the share of calls you expect for each weighted outcome other than success, for example 5% timeout and 3% error; success takes whatever is left. With nothing entered, the preview treats every call as
SUCCESS. - AI Pricing Architect. Its cost estimates are computed by Aforo, not written by the model. Tell it your expected mix ("90% succeed, 5% error, 5% time out"); without one, an Outcome-Based estimate counts every call in full and says it is an upper bound.
- Live revenue and Current Spend. These weight each call by its actual status as it arrives. They exclude tax, and they apply included free units, block size and minimum fee to each event rather than once per period — so when an Outcome-Based unit uses any of those three, Current Spend marks it approximate and the invoice is the figure to trust.
Sending outcomes
Set executionStatus on each usage event. Accepted values: SUCCESS, PARTIAL, TIMEOUT, ERROR, VALIDATION_FAILED, FAILED, FAILURE, CANCELLED, PENDING, BLOCKED, HITL_REQUIRED — any case, stored upper-cased. The ingest API rejects an event with any other value: POST /v1/ingest returns 400, and POST /v1/ingest/batch accepts the rest of the batch and counts that event in failed. The Execution Status filter on API, agentic API, AI agent and MCP billable units matches on this same field.
curl -X POST https://api.aforo.ai/v1/ingest \
-H "X-API-Key: $AFORO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"cus_123","metricName":"agent_calls","quantity":1,
"occurredAt":"2026-07-01T10:00:00Z","idempotencyKey":"run_7f3a",
"executionStatus":"TIMEOUT"}'
// Node — @aforoai/metering
aforo.track({ customerId: 'cus_123', metricName: 'agent_calls', executionStatus: 'TIMEOUT' });
# Python — aforo-metering
client.track(customer_id="cus_123", metric_name="agent_calls", execution_status="TIMEOUT")
Who sets it for you:
Every SDK checks a status you pass against the 11 values. An unknown value is logged and left off the event (the SDKs that derive a status send the derived one), so the event is still accepted instead of being rejected at ingest.
Gateway mapping. All five gateway plugins use the same default table:
- Overrides. Map any exact status code to one of the 11 values: Kong
status_outcomes, AWSSTATUS_OUTCOMES, Apigee KVMstatus_outcomes, Azure APIM context variableaforo-status-outcomes, MuleSoftstatus-outcomes. Invalid entries are ignored (Kong rejects them when you apply the plugin config). If a code is listed twice, the last valid entry wins. Each gateway guide shows the syntax. - Not metered by default. All five gateway plugins skip 401, 403 and 429 entirely, along with requests to
/health,/readyand/metrics— those produce no event. The status list isexclude_status_codeson Kong,EXCLUDE_STATUS_CODESon AWS Lambda, the KVM entryexclude_status_codeson Apigee, the context variableaforo-exclude-status-codeson Azure APIM and the policy parameterexclude-status-codeson MuleSoft. A list you set replaces the default; remove a code to meter it asBLOCKED. To meter every status, give Kong an empty array, AWS Lambda an empty value, and Apigee, Azure APIM and MuleSoft the wordnone. Each gateway guide lists the matching path setting. - gRPC (Kong only). Kong reads
grpc-statusfrom the header or the trailer: 0 →SUCCESS, 1 →CANCELLED, 3, 9 and 11 →VALIDATION_FAILED, 4 →TIMEOUT, 7, 8 and 16 →BLOCKED, anything else (including codes above 16) →ERROR. Each code maps through an HTTP equivalent (5 → 404, 14 → 503, 7 → 403, 8 → 429, 16 → 401, …), so overrides and the exclude list apply to gRPC too — by default 7, 8 and 16 produce no event. If Kong can't read a gRPC status it uses the HTTP status.
To configure the plan through the API instead of the wizard, send "model": "OUTCOME_BASED" and an outcomeWeights map on the billable unit. Any of the 11 statuses can be a key:
{
"metricId": "metric_agent_calls",
"model": "OUTCOME_BASED",
"rate": 0.02,
"outcomeWeights": { "SUCCESS": 1.0, "PARTIAL": 0.5, "TIMEOUT": 0.25, "ERROR": 0, "VALIDATION_FAILED": 0, "BLOCKED": 0, "CANCELLED": 0 }
}
Model names are case-insensitive ("outcome_based" works) and come back upper-cased.
Configuring a Rate Plan
Multi-Product, Multi-Metric
A single rate plan links to:
- Multiple products — one rate plan can cover an entire product family
- Multiple billable units — each with its own independent pricing model and tier structure
{
"name": "Growth Plan — Q2 2026",
"productIds": ["prod_api_v2", "prod_agentic_v1"],
"metricConfigs": [
{
"metricId": "metric_api_calls",
"model": "GRADUATED",
"tiers": [
{ "tierStart": 0, "tierEnd": 1000, "unitPrice": 0.010 },
{ "tierStart": 1001, "unitPrice": 0.005 }
]
},
{
"metricId": "metric_input_tokens",
"model": "PER_UNIT",
"rate": 0.000002,
"includedFree": 100000
}
]
}
Per-dimension pricing
Beyond the per-metric config, a rate plan can weight individual dimensions of a metric with their own multipliers via its dimensionPricing map — per-tool pricing on an MCP Server, per-endpoint pricing on an Agentic API, or per-capability pricing on an AI Agent. Keys are the dimension names; values are multipliers applied to the metric's base rate:
{
"pricingModel": "PER_UNIT",
"dimensionPricing": { "web_search": 1.5, "generate_image": 3.0, "summarize": 0.5 },
"metricConfigs": [{ "metricName": "Tool Invocations", "model": "PER_UNIT", "rate": 0.01, "includedFree": 0 }]
}
Multipliers only fan out into separate line items on a PER_UNIT metric with no included free tier — on other models the plan bills the aggregate as one line at the base rate. See MCP Server for the per-tool walk-through and the reasoning behind that rule.
Limits and Guardrails
Each metric config can have limits that enforce usage thresholds:
Included Quota & Rollover
Set includedFree to give customers a monthly free allowance. Enable rollover: true to let unused quota carry forward to the next billing period, up to rolloverMax units.
Rollover is tracked per-subscription. Unused quota from the current period is applied before charging overages next period.
Version Pinning
When you update pricing on a rate plan that has active subscriptions, Aforo automatically creates a new rate plan version. Existing subscribers are pinned to the version they signed up with — they will not see price changes until explicitly migrated.
This gives you safe price updates without surprise bills for existing customers.
Billing Timing
Per metric config, set billingTiming:
ARREARS— Charge at end of billing period (postpaid, default)ADVANCE— Charge at start of period (prepaid credit burn)