Per-Seat Billing Quick Start

This guide is intended to take you from no payment processing to a simple, but functional, per-seat billing system.

Introduction

Per-seat billing means charging based on the number of grantees. £10 per user per month, £99 per seat per year, and £5 per seat per week are all examples of this billing model.

Following this short guide will take you from zero to being up-and-running with a per-seat billing model 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 project management tool, you may offer "Team" and "Enterprise" plans, with "Advanced Reporting", "Custom Fields", and "API Access" as your entitlements.

To charge for seats on your "Team" plan, set up a Line Item with a Pricing Type of "Per Seat".

When creating a checkout for per-seat billing, you can optionally specify a group (or let Salable create one automatically on purchase). The checkout will automatically calculate the quantity based on the number of group members.

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',
        // if group id (starts with grp_) -> group is re-used
        // if any other grantee -> new group with grantee added as first member
        // if undefined -> new group created with no members
        grantee: 'test-user-123', // optional
        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

Creating a group upfront (optional)

If you need to create a group with specific team members before checkout, you can do so:

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' }
        ]
    })
});
 
const { data: group } = await response.json();
 
// Then use the group ID in checkout
const checkoutResponse = 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, // Specify the pre-created group
        interval: 'month',
        intervalCount: 1,
        currency: 'USD',
        successUrl: 'https://your-app.com/success',
        cancelUrl: 'https://your-app.com/cancel'
    })
});

3. 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.
}

4. Managing team members

As your team grows, you can add or remove grantees from the group.

// 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_charlie',
            name: 'Charlie Brown'
        }
    ])
});
 
// Update seat quantity
await fetch(`https://beta.salable.app/api/subscription-plan-line-items/${subscriptionPlanLineItemId}`, {
    method: 'PUT',
    headers: {
        Authorization: 'Bearer YOUR_SECRET_KEY',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        quantity: 3 // New seat count
    })
});

5. Next steps

Now that you have per-seat payment processing and entitlement checking set up in your application, there are some further things you should set up to enable full subscription handling: