Per-seat billingthat knows who's in every seat
Charge teams per seat, assign those seats to real people and give them the correct access the moment they join. Salable keeps subscriptions, seat counts, and memberships in sync, so your application never has to handle a Stripe webhook.
Stripe tracks payments. Salable tracks people.
Stripe knows a payment was made for a quantity, but that’s it. Which users belong to that subscription, what they can access, what happens when someone joins or leaves: none of that exists in Stripe.
Salable assigns people to subscriptions and tracks membership in real time. Add, remove, or swap someone, and their access updates instantly. You don't build any of it.
click a member to toggle access
A seat can be anything
Users are the obvious seat, but not the only one. With Salable, a seat can be filled by anything in your product with a unique ID.
Projects
Charge per project, the way a GitLab integration can. A seat is a project your app is connected to, and the team working on it all share it.
$3/mo per project
Workspaces
Charge per workspace, the way an app installed into Jira does. Every member of that workspace is covered by the one seat it holds.
$5/mo per workspace
Sites
Charge per site, the way a WordPress plugin licence does. A customer buys five sites, and each one they activate takes one of the five.
$4/mo per site
Orgs
Charge per Salesforce org your package is installed into. The org is the thing you are connected to, not the people inside it.
$20/mo per org
Portals
Charge per HubSpot portal. One customer with three portals is three seats, however many of their team log in.
$12/mo per portal
Clusters
Charge per Kubernetes cluster your operator runs in. A cluster is a container you are installed into, so it is what a seat counts.
$30/mo per cluster
Servers
Charge per Discord server your bot joins. The server holds the entitlements; its members come and go without touching the count.
$2/mo per server
Multiple teams. One invoice.
When every team buys its own subscription, your customer’s finance team juggles different renewal dates, payment cards, and invoices. Salable’s cart functionality lets them buy several plans in one checkout, assign each to a different team, and get one invoice.
Add or remove plans from an existing subscription with a single API call. No new checkout required, and changes and entitlements take effect immediately.
- Developer PlanEngineering$240/mo8 seatsVisa ···· 4417Renews 3 Nov
- Analytics PlanFinance$120/mo4 seatsAmex ···· 1002Renews 18 Nov
- Support PlanService Desk$90/mo3 seatsVisa ···· 8890Renews 27 Nov
- Design PlanBrand$60/mo2 seatsVisa ···· 2310Renews 2 Dec
The infrastructure you don't build
Auto team onboarding
Onboard teams to your plans by attaching their group ID in Salable to the Stripe checkout. On purchase, every user in the group gets instant the plan's entitlements, you handle nothing.
Tenant switching
When one user belongs to several tenants on different plans, they should only ever get what that tenant paid for. Scope each entitlement check to the owner (the tenant who made the purchase), and Salable returns the right entitlements. Nothing leaks between tenants.
Manage seats
Add, remove, or replace users as the team changes. A group can never hold more users than it has seats, and spare seats are left empty, ready to fill whenever the team grows.
Seat limits per plan
Optionally set a minimum and maximum seat count for each plan. When a team fills every seat, prompt them to upgrade for more.
Combine pricing models with seats
Seats don't have to stand alone. Combine them with flat fees, one-off charges, metered usage, and tokens on the same plan and the same invoice.
Integrate in minutes
Per-seat billing only requires three API calls.
const response = await fetch('https://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();
const checkoutResponse = await fetch('https://salable.app/api/checkout', { method: 'POST', headers: { Authorization: 'Bearer YOUR_SECRET_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ 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' }) }); const { data } = await checkoutResponse.json();
const response = await fetch('https://salable.app/api/entitlements/check?granteeId=user_alice&owner=company_acme', { headers: { Authorization: 'Bearer YOUR_SECRET_KEY' } }); const { data } = await response.json(); const hasAccess = data.entitlements.find(e => e.value === 'advanced_reporting');






