Moving from licenses to subscriptions
Overview
We have made several important updates to how ad hoc licenses are handled within the API to improve consistency and enable new functionality. This guide outlines the changes, new patterns, and any deprecations you need to be aware of.
Key Changes
Subscriptions
Every ad hoc license is now grouped under a parent subscription, allowing:
- Consistent license management via subscription endpoints.
- Full support for per-seat ad hoc licensing models.
- Ad hoc licenses to change plan.
Unified API Access Pattern
All subscriptions are managed the same way, whether they use payment integrations or not. This means developers will no longer have to determine which endpoint to based on if its a license or subscription.
New Support: Per-seat subscriptions without payment
Per-seat subscriptions no longer require a payment integration. They can now be created and managed without requiring a payment through a checkout link.
Subscription changes
Create a subscription
This is only for creating subscriptions that do not require a payment. If you require payment, create a checkout link.
await salable.subscriptions.create({
granteeId: 'userId_1', // The ID of the entity that will get access.
owner: 'orgId_1' // The ID of the organisation or user who will manage the subscription.
planUuid: '{PLAN_UUID}' // The ID of the plan the subscription will be created on.
})
License changes
Deprecated endpoints
While v1 and v2 will maintain backward compatibility, the following endpoints are now deprecated:
- Create license(s)
POST /licenses
- List licenses
GET /licenses
- Get license count
GET /licenses/count
- Update many licenses
POST /licenses
- Update a license
PUT /licenses/:uuid
- Cancel a license
DELETE /licenses/:uuid
- Cancel many licenses
PUT /licenses/cancel
We recommend migrating to the new subscription-based APIs to future-proof your integration.
Create license(s)
The endpoint POST /licenses
has been deprecated. Use subscription create.
Create many licenses has been deprecated. To create many licenses on a per-seat subscription use the quantity parameter.
Previous implementation
await salable.licenses.create({
granteeId: 'userId_1',
member: 'orgId_1'
planUuid: '{PLAN_UUID}'
})
New implementation
await salable.subscriptions.create({
granteeId: 'userId_1', // The ID of the entity that will get access.
owner: 'orgId_1' // The ID of the organisation or user who will manage the subscription.
planUuid: '{PLAN_UUID}' // The ID of the plan the subscription will be created on.
quantity: 3 // The amount of seats to create. Only applicable to per-seat plans.
})
List licenses
The endpoint GET /licenses
has been deprecated. Use list subscriptions.
Previous implementation
await salable.licenses.getAll();
New implementation
await salable.subscriptions.getAll();
List per-seat subscription's seats
The endpoint GET /licenses
has been deprecated. Use get seats
to get all seats on a subscription.
Previous implementation
await salable.licenses.getAll({
subscriptionUuid: '{SUBSCRIPTION_UUID}',
status: 'ACTIVE'
});
New implementation
await salable.subscriptions.getSeats();
Get license count
The endpoint GET /licenses/count
has been deprecated. Use
get seat count.
Previous implementation
await salable.licenses.getCount({
subscriptionUuid: '{SUBSCRIPTION_UUID}',
status: 'ACTIVE'
});
New implementation
await salable.subscriptions.getSeatCount('{SUBSCRIPTION_UUID}');
Update license(s)
The endpoints PUT /licenses
and PUT /licenses/:uuid
have now been deprecated. Use
subscription update. Updating a property on a subscription will cascade to its licenses. For
example updating a subscription's expiryDate
will also update the license endTime
value.
Previous implementation
await salable.licenses.update('{LICENSE_UUID}', {
endTime: '2025-05-28T11:43:14.381Z',
})
New implementation
await salable.subscriptions.update('{SUBSCRIPTION_UUID}', {
expiryDate: '2025-05-28T11:43:14.381Z',
})
Update license grantee
The endpoints PUT /licenses
and PUT /licenses/:uuid
have now been deprecated.
Use manage seats for updating a grantee on a seat. Grantees on seats can
be assigned, unassigned or replaced.
Previous implementation
await salable.licenses.update('{LICENSE_UUID}', {
granteeId: 'new-grantee-id',
})
New implementation
await salable.subscriptions.manageSeats('{SUBSCRIPTION_UUID}', [
{ type: 'assign', granteeId: 'new-grantee-id' }
])
Cancel a license
The endpoint DELETE /licenses
has been deprecated. Use
subscription cancel.
Previous implementation
await salable.licenses.cancel('{LICENSE_UUID}')
New implementation
await salable.subscriptions.cancel('{SUBSCRIPTION_UUID}', {
when: 'now'
})