Licensing & seats
Per-seat pricing by billable role, signed license tokens, expiry, and revocation.
Updated
Paid plugins are licensed per seat, billed monthly or yearly. This page explains what a seat is, what a license is, and how your instance enforces it.
What counts as a seat
A seat is a user who holds a billable role in a plugin — not every user.
- Billable — operator- and approver-style roles that do the work (post a journal entry, approve a requisition, manage stock).
- Free — viewers, self-service users, and public/customer roles never consume a seat.
Each plugin declares its own roles and marks which are billable; the core
learns them when the plugin registers (see How plugins work).
seats(plugin) is simply the number of users with at least one billable role in
that plugin. A plugin's detail page on this site lists which roles are billable.

Note
Seats are counted per plugin. A user who operates two plugins is a seat in each. This is why adding a plugin to an existing team is priced on that plugin's billable users, not your whole user base.
What a license is
On payment, the vendor issues a short, signed license token bound to your project. On the wire it looks like:
lic1.<base64url(payload)>.<base64url(signature)>
The payload is deliberately tiny — { project, plugin, seats, roles, kid, iat, exp }
— so it can be stored and passed around cheaply. (A license may also carry an
optional node_lock that binds it to one machine's hardware fingerprint, and a
trial flag for self-serve trials.) Your instance verifies the Ed25519
signature against the pinned vendor public key, then reads the seat count
and expiry locally. No call to the vendor is needed to check a license;
verification is offline and fast.
Note
The bound seat count is enforced as a turnstile at role assignment. Once
the distinct holders of a billable role reach your licensed count (per-role,
or the aggregate pool on older tokens), granting that role to one more user is
refused — the API returns 409 seat_limit_reached. To add a seat you must
free one (revoke the role from someone) or buy more from Manage billing;
you can't simply add past the limit and reconcile later. An over state (the
Marketplace seat view showing X / N over) only arises when a license
downgrade drops the count below existing holders, or via an operator override
— and in that case the plugin keeps running rather than bricking mid-month.
The teeth are on expiry and revocation, below.
Expiry, renewal, and grace
Your instance periodically re-checks the license with the vendor (a heartbeat). This is how renewals, seat changes, and revocations propagate without you doing anything:
- A renewed license rotates in automatically — the heartbeat re-binds the new seat count and expiry on the next tick.
- A lapsed license (the subscription expired and no renewal re-issued one) puts the plugin dormant once grace runs out: it stops, but your data is preserved untouched. Paying again issues a fresh license with a future expiry, and reinstalling brings the plugin back with its data intact.
- An explicitly revoked license stops the plugin immediately, bypassing grace — a revoke means stop now. Data is still preserved.
- A refund or chargeback revokes the license the same way — immediately, with no grace. Reversing the payment reverses the entitlement; your data is still preserved, and re-subscribing brings the plugin back.
- A grace window (14 days by default) covers an in-flight renewal — e.g. a webhook still settling, a payment retry over a weekend, or a box that was briefly offline — so a transient lapse doesn't suspend production. The Marketplace seat view surfaces an in grace banner while the clock runs.
Key rotation
The vendor can rotate its signing key; the token's kid (key id) records which
key signed it. To keep already-shipped binaries working across a rotation, your
Railbase build pins a set of trusted vendor keys (the active key plus
retired ones), and a license verifies if any pinned key accepts its signature.
New licenses are signed by the current active key. A brand-new signing key is
added to the pinned set in the next Railbase release — the trust root is fixed
at build time, so it can't be swapped at runtime.
Managing your subscription
Change seats, switch billing cycle, or cancel from Manage billing in either the in-app marketplace or your account on this site — both open the vendor's secure billing portal. Details in Managing billing.