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".
2. Generate a checkout link
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.urlCreating 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: