Metered Usage
Charge customers based on what they actually consume. Track API calls, storage, messages, or any measurable activity in your application. Salable calculates charges at the end of each billing cycle and adds them to the invoice automatically.
How Metered Billing Works
You define a Meter for each type of usage you want to track—api_calls, storage_gb, messages_sent. Meters belong to your organisation and can be reused across Plans at different rates: your Basic Plan might charge $0.01 per API call, while Pro charges $0.005.
When a customer subscribes to a Plan with a Metered Line Item, Salable creates a Usage Record to track their consumption. Throughout the billing period, you record usage via the API using the Owner identifier and Meter slug. At period end, Salable finalises the count, calculates charges, and generates an Invoice.
Subscription Created
└─ Usage Record created (count: 0)
│
├─ You record usage → count increments
├─ You record usage → count increments
│
Billing Period Ends
└─ Usage Record finalised
└─ Charge calculated → Invoice generated
└─ New Usage Record created (count: 0)
The Owner is typically a user ID for individual Subscriptions, or an organisation/team ID for shared Subscriptions. Usage is tracked at the Owner level regardless of how many Grantees access the Subscription.
Setting Up Metered Billing
Adding Metered Line Items to Plans
You can create Meters inline while building Plans. In the Product editor, navigate to the Plan and click Add Line Item.
Fill in a descriptive Line Item Name, such as "API Usage". This appears on Stripe Invoices, so use customer-facing language. Leave Interval Type set to Recurring since metered charges repeat each billing cycle.
Under Pricing Type, select Metered. Choose your Billing Scheme: Per Unit multiplies the Price by the usage quantity, while Tiered offers volume-based or graduated pricing based on usage levels.
In Select Meter, choose an existing Meter or create one by typing the slug you want (like api_calls or photo_generations) and clicking Create. The Meter registers with Salable and Stripe immediately.
Configuring Metered Pricing
After selecting your Meter, set up pricing for each billing Interval and Currency.
Click Add Price and select your Billing Interval (Month, Year, etc.). Click Add Currency and choose your Currency (USD, GBP, EUR, etc.).
For per-unit pricing, enter the Unit Amount as Price per unit. To charge $0.01 per API call, enter 0.01.
For tiered pricing, configure each tier with its range and pricing: First Unit is auto-calculated from the previous tier, Last Unit is the upper limit or inf for the final tier, and Unit Amount is the Price per unit. Optionally add a Flat Amount as a base fee for reaching each tier.
Example Per-Unit Pricing:
Meter: api_calls
Price: 0.01 (= $0.01 per call)
Usage: 5,000 calls
Charge: 5,000 × $0.01 = $50.00
Example Graduated Tiered Pricing:
Tier 1: 1–10,000 calls at $0.01 each
Tier 2: 10,001–50,000 calls at $0.008 each
Tier 3: 50,001+ calls at $0.005 each
Usage: 60,000 calls
Charge: (10,000 × $0.01) + (40,000 × $0.008) + (10,000 × $0.005) = $470.00
Recording Usage
API: Record Usage
Record usage returns 204 immediately while processing happens in the background, so you can track millions of events without impacting your application's performance.
Endpoint: POST /api/usage/record
Request Body:
{
"owner": "company_acme",
"meterSlug": "api_calls",
"increment": 50
}Parameters:
- owner: identifier for the entity being charged (user ID, organisation ID, or team ID)
- meterSlug: Meter identifier to increment (must match a Meter in the customer's Subscription)
- increment: amount to add to the usage counter (minimum 1)
- idempotencyKey (optional): unique key to prevent duplicate increments; requests with the same key are deduplicated
Response:
Returns 204 No Content on success. No response body. Absence of an error means success.
Note The Usage Record must exist, which happens automatically when a customer subscribes to a Plan with that Metered Line Item. Recording usage for an
ownerandmeterSlugcombination without an active Subscription returns404 Not Found.
Implementation Example
async function recordUsage(owner, meterSlug, increment) {
const response = await fetch('https://api.salable.app/api/usage/record', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SALABLE_SECRET_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ owner, meterSlug, increment })
});
if (!response.ok) throw new Error(`Failed to record usage: ${response.status}`);
}
// Record after processing a request
app.post('/api/analyze-image', async (req, res) => {
const result = await analyzeImage(req.body.imageUrl);
await recordUsage(req.user.organizationId, 'api_calls', 1);
res.json(result);
});For high-volume scenarios, increment batches locally (every minute or every 100 calls), then record the accumulated total.
Retrieving Usage Data
API: List Usage Records
Endpoint: GET /api/usage/count
Query Parameters:
owner(required): Owner identifiermeterSlug(required): Meter slug to querystatus(required): One or more statuses, comma-separated (recorded,current,final)before(optional): Cursor for pagination (previous page)after(optional): Cursor for pagination (next page)
Example Request:
GET /api/usage-records?owner=company_acme&meterSlug=api_calls&status=currentExample Response:
{
"type": "list",
"data": [
{
"id": "UsageRecord_01HXXX",
"organisation": "org_xxx",
"ownerId": "Owner_01HYYY",
"usageId": "Usage_01HZZZ",
"status": "current",
"count": 5432,
"recordedAt": null,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T14:23:11Z"
}
],
"previousCursor": null,
"nextCursor": null,
"hasMore": false
}Response Fields:
- status: record state (
recorded,current, orfinal) - count: accumulated usage for this period
- recordedAt: null for current records; set when finalised
Query with status=current for real-time usage dashboards, or status=final to retrieve historical billing periods. Results are sorted by creation date in ascending order; use nextCursor and previousCursor for pagination.
Billing Cycle Behaviour
Metered usage operates on the Subscription's billing cycle. If a customer subscribes on January 15th with monthly billing, usage periods run January 15th to February 15th, then February 15th to March 15th.
At period end, Usage Records transition from current to final status. The accumulated count is used to calculate charges and generate an Invoice. The counter resets to zero, and a new Usage Record is created for the next period.
Immediate Finalisation
Certain mid-cycle changes trigger immediate finalisation and a prorated Invoice:
- A Plan with Metered Line Items is removed from a Subscription
- A Subscription is cancelled immediately (not at period end)
- A Subscription's billing anchor changes
For end-of-period cancellation, usage accumulates normally until period end, then finalises on schedule.
You've now seen how to set up Meters, attach them to Plans with per-unit or tiered pricing, record usage via the API, and retrieve usage data for dashboards or historical analysis. Salable handles the billing cycle, finalisation, and Invoice generation automatically.
For more on configuring Products and pricing models, see the Products & Pricing guide. For managing team access and understanding how Owners scope usage data, see Grantees & Groups.