Usage-based pricing

Charge customers based on actual consumption by tracking usage events and billing at the end of each period.
View as Markdown

Overview

Use usage-based pricing (metered billing) to charge customers based on how much they consume rather than a fixed recurring amount. Instead of paying $50/month regardless of activity, a customer pays based on actual usage — a light user pays less, a heavy user pays more.

Common use cases:

  • API calls or compute tokens
  • Cloud storage or bandwidth
  • Email or SMS delivery
  • Utility-style services

Core concepts

Usage-based billing is built on three concepts:

ConceptDescription
MeterDefines what to track and how to count it. For example, a meter named “Tokens Processed” with aggregation sum adds up all token values over a billing period.
EventsRaw usage data. Each time something billable happens, your application sends an event with a customer identifier, a numeric value, and a timestamp.
Usage aggregationAt billing time, PaymentKit computes the total usage per customer and meter over the billing period, then calculates the charge based on your pricing model.

Before you begin

  • Create at least one product in your catalog
  • Create a customer in the account
  • Have an API key with account-level access

Create a meter

A meter defines the usage metric you want to track. Each meter has an event name (a unique identifier your application uses when sending events) and an aggregation formula that controls how events are combined.

FieldDescription
display_nameHuman-readable name (e.g., “Tokens Processed”)
event_nameUnique identifier used when sending events. Must be unique within the account. Alphanumeric characters, hyphens, and underscores only.
aggregation_formulaHow events are combined: sum (total value) or count (number of events)
event_payload_customer_mapping_keyField in the event payload that identifies the customer. Default: customer_id
event_payload_value_keyField in the event payload that contains the usage quantity. Default: value
$curl -X POST https://api.paymentkit.com/api/{account_id}/meters \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "display_name": "Tokens Processed",
> "event_name": "tokens_processed",
> "aggregation_formula": "sum"
> }'

Response:

1{
2 "id": "mtr_live_a1b2c3d4e5f6g7h8",
3 "account_id": "acc_live_1a2b3c4d5e6f7g8h",
4 "display_name": "Tokens Processed",
5 "event_name": "tokens_processed",
6 "aggregation_formula": "sum",
7 "event_payload_customer_mapping_key": "customer_id",
8 "event_payload_value_key": "value",
9 "is_active": true,
10 "created_at": "2026-01-15T10:30:00Z",
11 "updated_at": "2026-01-15T10:30:00Z"
12}

Use sum when the event value represents a quantity (e.g., tokens, bytes, seconds). Use count when each event represents one billable action regardless of the value field.

Create a metered price

Link a meter to a product by creating a price with usage_type: "metered". Metered prices support three pricing patterns:

Per-unit pricing

Charge a flat rate per unit of usage. Set a quantity_divisor to bill per batch of units (e.g., per 100 tokens).

$curl -X POST https://api.paymentkit.com/api/{account_id}/prices \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "product_id": "prod_live_abc123",
> "currency": "usd",
> "pricing_type": "recurring",
> "recurring_interval": "month",
> "recurring_interval_count": 1,
> "usage_type": "metered",
> "metered_id": "mtr_live_a1b2c3d4e5f6g7h8",
> "billing_scheme": "per_unit",
> "unit_amount_atom": 4,
> "quantity_divisor": 100
> }'

This charges $0.04 per 100 tokens (4 atoms per batch, where 1 atom = $0.01). A customer who uses 15,000 tokens in a month pays ceil(15,000 / 100) × $0.04 = $6.00.

Free tier + overage (graduated tiered)

Offer a free allowance by setting the first tier’s unit amount to $0:

$curl -X POST https://api.paymentkit.com/api/{account_id}/prices \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "product_id": "prod_live_abc123",
> "currency": "usd",
> "pricing_type": "recurring",
> "recurring_interval": "month",
> "recurring_interval_count": 1,
> "usage_type": "metered",
> "metered_id": "mtr_live_a1b2c3d4e5f6g7h8",
> "billing_scheme": "tiered",
> "tier_amount_info": {
> "mode": "graduated",
> "amount_atoms": [
> { "units_upto": 1000, "unit_amount_atom": 0, "flat_amount_atom": 0 },
> { "units_upto": null, "unit_amount_atom": 1, "flat_amount_atom": 0 }
> ]
> }
> }'

The first 1,000 units are free. Usage beyond that is $0.01/unit. A customer who uses 3,000 units pays (1,000 × $0) + (2,000 × $0.01) = $20.00.

Flat fee + included allowance

Charge a base fee that includes a usage allowance, with per-unit charges for overage:

$curl -X POST https://api.paymentkit.com/api/{account_id}/prices \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "product_id": "prod_live_abc123",
> "currency": "usd",
> "pricing_type": "recurring",
> "recurring_interval": "month",
> "recurring_interval_count": 1,
> "usage_type": "metered",
> "metered_id": "mtr_live_a1b2c3d4e5f6g7h8",
> "billing_scheme": "tiered",
> "tier_amount_info": {
> "mode": "graduated",
> "amount_atoms": [
> { "units_upto": 100000, "unit_amount_atom": 0, "flat_amount_atom": 20000 },
> { "units_upto": null, "unit_amount_atom": 1, "flat_amount_atom": 0 }
> ]
> }
> }'

This charges $200/month (the flat fee of 20,000 atoms) which includes 100,000 units. Overage is $0.01/unit. A customer who uses 150,000 units pays $200 + (50,000 × $0.01) = $700.00. Zero usage still charges the $200 flat fee.

All pricing patterns — per-unit, free tier, and flat fee + allowance — are built on the same graduated tiered pricing engine. Free tiers are just tiers with a $0 unit amount, and flat fees are just tiers with a flat_amount_atom.

Send usage events

Report usage by sending events to the meter events endpoint. Each event includes the meter’s event_name, a payload with the customer ID and usage value, and an optional timestamp.

Single event

$curl -X POST https://api.paymentkit.com/api/{account_id}/meter-events \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "event_name": "tokens_processed",
> "payload": {
> "customer_id": "cus_live_abc123",
> "value": 500
> }
> }'

Batch events

Send up to 100 events in a single request for higher throughput:

$curl -X POST https://api.paymentkit.com/api/{account_id}/meter-events/batch \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "events": [
> {
> "event_name": "tokens_processed",
> "payload": { "customer_id": "cus_live_abc123", "value": 500 }
> },
> {
> "event_name": "tokens_processed",
> "payload": { "customer_id": "cus_live_abc123", "value": 300 }
> }
> ]
> }'

The batch response reports how many events were accepted and lists any per-event errors:

1{
2 "received": 2,
3 "errors": []
4}

If some events fail validation, valid events are still ingested:

1{
2 "received": 1,
3 "errors": [
4 { "index": 1, "error": "Customer not found" }
5 ]
6}

Event validation rules

RuleDetail
Meter must exist and be activeEvents referencing an unknown or deactivated meter are rejected
Customer must existThe customer ID in the payload must match an existing customer in the account
Value must be a positive integerZero, negative, and float values are rejected
Timestamp within allowed windowMust be within the past 35 days and no more than 5 minutes in the future. Defaults to now if omitted.
Events are immutableCorrections are made by sending additional events, not by modifying existing ones

For high-throughput use cases, batch events and send them periodically rather than one at a time. You can also pre-aggregate usage on your side and send periodic summary events.

Subscribe a customer to a metered price

Create a subscription that includes a metered price. Metered items have no upfront charge — the customer is billed based on usage at the end of each billing period.

$curl -X POST https://api.paymentkit.com/api/{account_id}/subscriptions \
> -H "Authorization: Bearer sk_live_..." \
> -H "Content-Type: application/json" \
> -d '{
> "customer_id": "cus_live_abc123",
> "currency": "usd",
> "period_start": "2026-02-01T00:00:00Z",
> "billing_interval": "month",
> "billing_interval_count": 1,
> "collection_method": "charge_automatically",
> "items": [
> { "price_id": "price_live_pro_plan", "quantity": 1 },
> { "price_id": "price_live_tokens_metered", "quantity": 1 }
> ]
> }'

A subscription can include both fixed and metered prices. Fixed-price items are invoiced at the beginning of each billing period (at renewal). Metered-price items accumulate usage during the period and are invoiced at the end (at the next renewal), based on actual usage.

How billing works at renewal

When a billing period ends:

  1. PaymentKit aggregates usage events for each metered item over the completed period
  2. The aggregated usage is run through the pricing model (per-unit or tiered) to calculate the charge
  3. Metered charges appear as line items on the renewal invoice alongside any fixed charges
  4. The invoice is finalized and payment is collected

For zero usage: if the price has a flat fee (e.g., a base subscription fee), the flat fee is still charged. If there is no flat fee, a $0 line item is created.

Query usage

Meter-level usage

Get the aggregated usage for a specific meter and customer over a time range:

$curl "https://api.paymentkit.com/api/{account_id}/meters/{meter_id}/usage-summary?customer_id=cus_live_abc123&start_time=2026-01-01T00:00:00Z&end_time=2026-02-01T00:00:00Z" \
> -H "Authorization: Bearer sk_live_..."
1{
2 "meter_id": "mtr_live_a1b2c3d4e5f6g7h8",
3 "customer_id": "cus_live_abc123",
4 "aggregation_formula": "sum",
5 "start_time": "2026-01-01T00:00:00Z",
6 "end_time": "2026-02-01T00:00:00Z",
7 "aggregated_value": 15000
8}

Subscription-level usage

Get the current-period usage for all metered items in a subscription:

$curl "https://api.paymentkit.com/api/{account_id}/subscriptions/{subscription_id}/usage" \
> -H "Authorization: Bearer sk_live_..."
1{
2 "subscription_id": "sub_live_xyz789",
3 "current_period_start": "2026-01-01T00:00:00Z",
4 "current_period_end": "2026-02-01T00:00:00Z",
5 "items": [
6 {
7 "subscription_item_id": "si_live_item1",
8 "meter_id": "mtr_live_a1b2c3d4e5f6g7h8",
9 "meter_display_name": "Tokens Processed",
10 "aggregated_value": 15000,
11 "price_id": "price_live_tokens_metered"
12 }
13 ]
14}

Manage meters

Deactivate a meter

Deactivate a meter to stop accepting new events. Existing prices linked to the meter continue to function for billing purposes.

$curl -X POST https://api.paymentkit.com/api/{account_id}/meters/{meter_id}/deactivate \
> -H "Authorization: Bearer sk_live_..."

Reactivate a meter

$curl -X POST https://api.paymentkit.com/api/{account_id}/meters/{meter_id}/reactivate \
> -H "Authorization: Bearer sk_live_..."

End-to-end example

A complete walkthrough of usage-based billing for an AI token processing service:

  1. Create a meter for token tracking:

    $POST /api/{account_id}/meters
    ${ "display_name": "Tokens Processed", "event_name": "tokens_processed", "aggregation_formula": "sum" }
  2. Create a metered price at $0.04 per 100 tokens:

    $POST /api/{account_id}/prices
    ${ "product_id": "prod_live_ai_service", "currency": "usd", "pricing_type": "recurring",
    > "recurring_interval": "month", "recurring_interval_count": 1, "usage_type": "metered",
    > "metered_id": "mtr_live_abc123", "billing_scheme": "per_unit",
    > "unit_amount_atom": 4, "quantity_divisor": 100 }
  3. Subscribe a customer — no upfront charge for the metered item:

    $POST /api/{account_id}/subscriptions
    ${ "customer_id": "cus_live_abc123", "currency": "usd", "period_start": "2026-01-01T00:00:00Z",
    > "billing_interval": "month", "billing_interval_count": 1,
    > "collection_method": "charge_automatically",
    > "items": [{ "price_id": "price_live_tokens_metered", "quantity": 1 }] }
  4. Send usage events throughout the month:

    $POST /api/{account_id}/meter-events
    ${ "event_name": "tokens_processed", "payload": { "customer_id": "cus_live_abc123", "value": 500 } }
  5. At month-end, PaymentKit aggregates: 15,000 total tokens. Charge: ceil(15,000 / 100) × $0.04 = $6.00. An invoice is generated with a $6.00 line item for “Tokens Processed”.