Hybrid Pricing Quick Start

Hybrid pricing combines flat-rate, per-seat, and metered line items in any combination on a single subscription. This guide walks through setting it up with Salable, where Stripe webhooks are handled out of the box and entitlements stay in sync across every plan on the subscription.

Introduction

Hybrid pricing means combining multiple billing models in a single plan. £50 base fee + £10 per user per month + £0.01 per API call is an example of this billing model.

1. Create and configure your product

Before you can start implementing Salable into your codebase, you need to sign up for an account and create a product in the Salable dashboard.

Create a product, the plans that you want your users to be able to subscribe to, and any entitlements they should be able to access depending on their subscription.

As an example, if your application was a team collaboration platform, you may offer a "Professional" plan with advanced_analytics, custom_integrations, and priority_support as your entitlements.

To create hybrid pricing on your "Professional" plan, you'll add multiple Line Items:

  1. A "Platform Fee" Line Item with a Pricing Type of "Flat Rate" (e.g., £50/month)
  2. A "Team Members" Line Item with a Pricing Type of "Per Seat" (e.g., £10/user/month)
  3. An "API Usage" Line Item with a Pricing Type of "Metered" using a meter like api_calls (e.g., £0.01/call)

2. Create a group with team members

For the per-seat line item of your hybrid pricing, you'll need to create a group that represents a team.

import { Salable } from '@salable/sdk';
const salable = new Salable('your-secret-key');
 
const { data: group } = await salable.api.groups.post({
    owner: 'company_acme',
    name: 'Development Team',
    grantees: [
        { granteeId: 'user_alice', name: 'Alice Smith' },
        { granteeId: 'user_bob', name: 'Bob Johnson' },
        { granteeId: 'user_charlie', name: 'Charlie Brown' }
    ]
});

When creating a checkout for a hybrid pricing plan, specify the Group ID as the grantee value. As soon as the subscription is active, every user in the group inherits the plan's entitlements. If an explicit quantity isn't provided, we calculate it based on the group's size.

import { Salable } from '@salable/sdk';
const salable = new Salable('your-secret-key');
 
const { data } = await salable.api.checkout.post({
    planId: 'plan_01KJWF3VM5HNQ3YRS27K06J64T',
    owner: 'company_acme',
    grantee: group.id,
    interval: 'month',
    intervalCount: 1,
    currency: 'USD',
    successUrl: 'https://your-app.com/success',
    cancelUrl: 'https://your-app.com/cancel'
});
// Redirect user to data.url

Once the customer completes checkout, they'll be charged for all Line Items: the base platform fee, the per-seat charges, and Salable will begin tracking usage for metered billing.

4. Record usage in your application

As users consume your metered services, record their usage to the appropriate meter. Usage recording returns immediately and processes in the background.

import { Salable } from '@salable/sdk';
const salable = new Salable('your-secret-key');
 
await salable.api.usage.record.post({
    owner: 'company_acme',
    meterSlug: 'api_calls',
    increment: 1
});

Passing owner scopes consumption to a specific tenant. All users belonging to that owner contribute to the same meter, this is useful for plans that combine metered with per-seat line items. It also handles users who belong to multiple tenants: pass the right owner, and Salable applies the usage to the right meter.

5. Add entitlement checks to your application

In your application, you'll want to check if each individual grantee has access through their group membership.

import { Salable } from '@salable/sdk';
const salable = new Salable('your-secret-key');
 
const { data } = await salable.api.entitlements.check.get({
    queryParameters: {
        granteeId: 'user_alice'
    }
});
 
const granteeHasEntitlement = data.entitlements.find(e => e.value === 'advanced_analytics');
 
if (granteeHasEntitlement) {
    // Allow the user to perform the action in your system.
}

Setting up Entitlements allows you to easily create tailored plans for your customers requirements. Copy any existing Plan, adjust its Entitlements and cost based on the agreed terms with the customer, and they immediately get the exact feature set you agreed without any code change. Now everything flows through Entitlements, sales can be instant.

6. Managing team members and usage

As your team grows, you can add or remove grantees and update seat quantities for your per-seat Line Items. You can also retrieve usage data for your metered Line Items to display in your dashboard.

import { Salable } from '@salable/sdk';
const salable = new Salable('your-secret-key');
 
// Add a new team member
await salable.api.groups.byId(group.id).grantees.post([
    {
        type: 'add',
        granteeId: 'user_diana',
        name: 'Diana Prince'
    }
]);
 
// Update seat quantity (only for per-seat Line Items)
await salable.api.subscriptionPlanLineItems.byId('spli_01KHRQ6CRK2HW7CHXMYFGXFSNX').put({
    quantity: 4 // New seat count
});
 
// Retrieve current usage (only for metered Line Items)
const { data: usageData } = await salable.api.usageRecords.get({
    queryParameters: {
        owner: 'company_acme',
        meterSlug: 'api_calls',
        status: ['current']
    }
});
 
const currentUsage = usageData[0]?.count || 0;

7. Next steps

Now that you have hybrid payment processing with multiple line items set up in your application, there are some further things you should set up to enable full subscription handling: