Offline licences
Your master offline licence, and short-lived licences for your own clients.
The Licensing object
Attributes
idrequired Type:stringkindrequired Type:"licence""trial"issued_torequired Type:stringYour organisation
issued_byrequired Type:"Unforged"issued_onrequired Type:stringvalid_fromrequired Type:stringvalid_untilrequired Type:stringworks_untilrequired Type:stringThe last day it works offline: 14 days after
valid_untilfor a licence, while you renew.includesrequired Type:"verify""extract""loupe"[]tokenoptional Type:stringThe licence text (
GET /licensing/masteronly).short_livedrequired Type:objectnullWhat you may give your own clients; null when your plan doesn't include short-lived licences.
The ShortLivedLicence object
Attributes
idrequired Type:stringforrequired Type:stringWho you gave it to. Their licence shows this name.
includesrequired Type:"verify""extract""loupe"[]valid_fromrequired Type:stringvalid_untilrequired Type:stringThe last day it works.
statusrequired Type:"scheduled""active""ended""revoked"countsrequired Type:booleanIt counts towards your limit (it can still be used offline).
created_byrequired Type:stringcreated_atrequired Type:stringrevoked_atrequired Type:stringnullrevoked_byrequired Type:stringnulltokenoptional Type:stringThe licence text (when it is given, and from
GET /licensing/licences/{licence_id}).
Your offline licensing
GET /licensing
Needs org:read: See org, members, usage
Your master offline licence (without its text) and, when your plan includes them, the short-lived licences you may give your own clients. 404 when your plan has no offline licence.
Returns
200Type:LicensingYour offline licensing401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/licensing" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/licensing",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json()); Your master offline licence
GET /licensing/master
Needs org:settings:manage: Retention, org-wide settings, the API version pin
Your master offline licence with its text, to install or download.
Returns
200Type:LicensingYour master offline licence401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/licensing/master" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/licensing/master",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing/master', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json()); Short-lived licences
GET /licensing/licences
Needs org:read: See org, members, usage
The short-lived licences you have given, newest first, without their text.
Returns
200Type:ShortLivedLicenceListShort-lived licences401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/licensing/licences" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/licensing/licences",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing/licences', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json()); Give a short-lived licence
POST /licensing/licences
Needs org:settings:manage: Retention, org-wide settings, the API version pin
A short-lived licence for one of your clients, with its text. Once your client has it, it keeps working offline until valid_until, even if you revoke it, and it counts towards your limit until then.
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
Request body
forrequired Type:stringWho it is for, such as your client's business name.
valid_fromrequired Type:stringToday or later.
valid_untilrequired Type:stringThe last day it works.
includesrequired Type:"verify""extract""loupe"[]Only what your plan includes.
Returns
201Type:ShortLivedLicenceGive a short-lived licence400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable413Type:Problemtoo_large421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/licensing/licences" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Content-Type: application/json" \
-d '{}' import requests
r = requests.post(
"https://api.unforged.sh/licensing/licences",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
json={},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing/licences', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
body: JSON.stringify({}),
});
console.log(await res.json()); A short-lived licence
GET /licensing/licences/{licence_id}
Needs org:settings:manage: Retention, org-wide settings, the API version pin
One short-lived licence, with its text.
Parameters
licence_idpathrequired Type:stringA short-lived licence's id.
Returns
200Type:ShortLivedLicenceA short-lived licence401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/licensing/licences/{licence_id}" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/licensing/licences/{licence_id}",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing/licences/{licence_id}', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json()); Revoke a short-lived licence
POST /licensing/licences/{licence_id}/revoke
Needs org:settings:manage: Retention, org-wide settings, the API version pin
Register lookups stop accepting the licence straight away. A copy on a computer that stays offline keeps working until valid_until, so it still counts towards your limit until then.
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
licence_idpathrequired Type:stringA short-lived licence's id.
Returns
200Type:ShortLivedLicenceRevoke a short-lived licence401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/licensing/licences/{licence_id}/revoke" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.post(
"https://api.unforged.sh/licensing/licences/{licence_id}/revoke",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/licensing/licences/{licence_id}/revoke', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());