Licensing
Not in
openapi.json. The activation and update routes are anonymous by design (a WordPress plugin has no API key) and are served bysrc/ResilientLang.Licensing. Written from itssrc/ResilientLang.Licensing/docs/LICENSING.md; a test checks the routes against the source.
The principle#
When a licence lapses, already-published translations keep serving. Only new work stops.
| Action | Active | Grace (term end plus 14 days, configurable) | Lapsed or revoked |
|---|---|---|---|
| Serve published bundles | yes | yes | yes, always |
| Export, view the dashboard | yes | yes | yes, always |
| Translate, add a language, publish, install plugin updates | yes, within plan limits | yes | no |
| Deactivate a site (free a slot) | yes | yes | yes |
| Activate a new site | yes | yes | no |
The serving path never calls licensing. State is computed from a signed token and the clock, so a failed refresh never changes it. Keeping CDN copies after a lapse (the pricing proposal suggests 12 months) is an owner decision that the publisher does not read yet.
Objects#
- Licence key
rl_lic_{live|test}_...: the purchase credential, shown once, stored as a keyed hash. It is sent only to activate or deactivate. - Activation: one licence and one normalised domain. Development hosts (
localhost,*.local,*.test,*.invalid) never use a slot (verify with the owner). - Licence token
rll1.<claims>.<Ed25519 signature>, bound to the domain, verified offline by the plugin.
Protocol (/v1/licensing, anonymous, throttled)#
| Call | Body | Result |
|---|---|---|
POST /v1/licensing/activate | { key, domain, instanceId? } | { token }, or a problem: invalid_key 401, activation_limit, licence_revoked or licence_lapsed 403, bad_domain 400, throttled 429 |
POST /v1/licensing/deactivate | { key, domain } | { deactivated: true }, or not_activated 404 |
POST /v1/licensing/refresh | { token } | a new token with the current term and status |
GET /v1/licensing/updates/{slug}/check?version=&domain= | header X-RL-Licence: <token> | 204 up to date, or 200 with a WordPress-shaped offer (a package link only when entitled) |
GET /v1/licensing/updates/{slug}/info | none | public plugin metadata for "View details" |
GET /v1/licensing/updates/{slug}/download/{version} | signed query | the zip; the link is signed, valid 10 minutes and bound to licence, version and domain |
Failures are throttled per IP (10 per 15 minutes by default).
Customer key management#
Keys are never e-mailed. The owner of a tenant with an active paid plan creates or rotates the key in the dashboard.
| Route | Who | Purpose |
|---|---|---|
POST /v1/licensing/keys | owner | Create or rotate the licence key and show it once. The previous key keeps working for new activations for 60 minutes. Five rotations per tenant per hour. 402 if the licence has lapsed |
GET /v1/licensing/status | any member | Plan, state (active, grace, lapsed, revoked), caps, term end, grace days, key prefix, active activations. Never the key |
Operator routes under /v1/licensing/admin/... exist for support staff and are not described here.
Shopify merchants are billed through Shopify, not licence keys; see the Shopify quick start.