Hybrid Pricing Quick Start

This guide is intended to take you from no payment processing to a simple, but functional, hybrid billing system combining multiple pricing models.

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.

Following this short guide will take you from zero to being up-and-running with a hybrid pricing model that combines flat-rate, per-seat, and usage-based billing in your application.

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.

You will need to create a product, the plans that you want the users to be able to subscribe to, and any entitlements your users 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 component of your hybrid pricing, you'll need to create a group that represents your team.

const response = await fetch('https://beta.salable.app/api/groups', {
    method: 'POST',
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        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' }
        ]
    })
});
 
const { data: group } = await response.json();

When creating a checkout for a hybrid pricing plan, specify the group and ensure the quantity matches the number of grantees.

const response = await fetch('https://beta.salable.app/api/checkout', {
    method: 'POST',
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        planId: 'YOUR_PLAN_ID',
        owner: 'company_acme',
        grantee: group.id,
        interval: 'YOUR_INTERVAL', // 'month' or 'year'
        intervalCount: 1,
        currency: 'YOUR_PLANS_CURRENCY', // USD, GBP, EUR, etc
        successUrl: 'https://your-app.com/success',
        cancelUrl: 'https://your-app.com/cancel'
    })
});
 
const { data } = await response.json();
// 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.

async function recordUsage(owner, meterSlug, increment) {
    const response = await fetch('https://beta.salable.app/api/usage/record', {
        method: 'POST',
        headers: {
            Authorization: 'Bearer YOUR_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 usage after processing API requests
await recordUsage('company_acme', 'api_calls', 1);

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.

const response = await fetch('https://beta.salable.app/api/entitlements/check?granteeId=user_alice', {
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY'
    }
});
 
const { data } = await response.json();
const granteeHasEntitlement = data.entitlements.find(e => e.value === 'YOUR_ENTITLEMENT_NAME');
 
if (granteeHasEntitlement) {
    // Allow the user to perform the action in your system.
}

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.

// Add a new team member
await fetch(`https://beta.salable.app/api/groups/${group.id}/grantees`, {
    method: 'POST',
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify([
        {
            type: 'add',
            granteeId: 'user_diana',
            name: 'Diana Prince'
        }
    ])
});
 
// Update seat quantity (only for per-seat Line Items)
await fetch(`https://beta.salable.app/api/subscription-plan-line-items/${perSeatSubscriptionPlanLineItemId}`, {
    method: 'PUT',
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        quantity: 4 // New seat count
    })
});
 
// Retrieve current usage (only for metered Line Items)
const usageResponse = await fetch('https://beta.salable.app/api/usage-records?owner=company_acme&meterSlug=api_calls&status=current', {
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY'
    }
});
 
const { data: usageData } = await usageResponse.json();
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: