*** title: Usage-based pricing subtitle: >- Charge customers based on actual consumption by tracking usage events and billing at the end of each period. ---------------------------------- # 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: | Concept | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Meter** | Defines *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. | | **Events** | Raw usage data. Each time something billable happens, your application sends an event with a customer identifier, a numeric value, and a timestamp. | | **Usage aggregation** | At 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](/guides/product-catalog) in your catalog * Create a [customer](/api-reference) 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. | Field | Description | | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | | `display_name` | Human-readable name (e.g., "Tokens Processed") | | `event_name` | Unique identifier used when sending events. Must be unique within the account. Alphanumeric characters, hyphens, and underscores only. | | `aggregation_formula` | How events are combined: `sum` (total value) or `count` (number of events) | | `event_payload_customer_mapping_key` | Field in the event payload that identifies the customer. Default: `customer_id` | | `event_payload_value_key` | Field in the event payload that contains the usage quantity. Default: `value` | ```bash 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: ```json { "id": "mtr_live_a1b2c3d4e5f6g7h8", "account_id": "acc_live_1a2b3c4d5e6f7g8h", "display_name": "Tokens Processed", "event_name": "tokens_processed", "aggregation_formula": "sum", "event_payload_customer_mapping_key": "customer_id", "event_payload_value_key": "value", "is_active": true, "created_at": "2026-01-15T10:30:00Z", "updated_at": "2026-01-15T10:30:00Z" } ``` 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). ```bash 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: ```bash 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: ```bash 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 ```bash 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: ```bash 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: ```json { "received": 2, "errors": [] } ``` If some events fail validation, valid events are still ingested: ```json { "received": 1, "errors": [ { "index": 1, "error": "Customer not found" } ] } ``` ## Event validation rules | Rule | Detail | | -------------------------------- | ----------------------------------------------------------------------------------------------------- | | Meter must exist and be active | Events referencing an unknown or deactivated meter are rejected | | Customer must exist | The customer ID in the payload must match an existing customer in the account | | Value must be a positive integer | Zero, negative, and float values are rejected | | Timestamp within allowed window | Must be within the past 35 days and no more than 5 minutes in the future. Defaults to now if omitted. | | Events are immutable | Corrections 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. ```bash 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: ```bash 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_..." ``` ```json { "meter_id": "mtr_live_a1b2c3d4e5f6g7h8", "customer_id": "cus_live_abc123", "aggregation_formula": "sum", "start_time": "2026-01-01T00:00:00Z", "end_time": "2026-02-01T00:00:00Z", "aggregated_value": 15000 } ``` ## Subscription-level usage Get the current-period usage for all metered items in a subscription: ```bash curl "https://api.paymentkit.com/api/{account_id}/subscriptions/{subscription_id}/usage" \ -H "Authorization: Bearer sk_live_..." ``` ```json { "subscription_id": "sub_live_xyz789", "current_period_start": "2026-01-01T00:00:00Z", "current_period_end": "2026-02-01T00:00:00Z", "items": [ { "subscription_item_id": "si_live_item1", "meter_id": "mtr_live_a1b2c3d4e5f6g7h8", "meter_display_name": "Tokens Processed", "aggregated_value": 15000, "price_id": "price_live_tokens_metered" } ] } ``` # 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. ```bash curl -X POST https://api.paymentkit.com/api/{account_id}/meters/{meter_id}/deactivate \ -H "Authorization: Bearer sk_live_..." ``` ## Reactivate a meter ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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".