Revocation & Status
Quick summary
A signed token is not a permanent license. The server checks the live license row on guarded calls, so suspension and revocation can deny subsequent use.
For an incident, confirm the license status, change it through an authorized seller action, then verify a previously valid request is rejected.
The rule
The live license row is re-queried on every guarded call. A still-valid entitlement signature never overrides the row: revoke the license and the next capability/execute/status call fails — bounded only by the check itself, not by the 120-second token TTL.
Status values & effects
licenses.status accepts: active · revoked · suspended · expired · (anything else → INVALID_STATUS).
| Status | Activation | Guarded calls (capability/execute/status) | Public verify verdict |
|---|---|---|---|
active | allowed | allowed | valid:true, code:OK |
revoked | 403 REVOKED | denied | code:REVOKED |
suspended | 403 SUSPENDED | denied | code:SUSPENDED |
expired | 403 EXPIRED | denied | code:EXPIRED |
| unknown value | 403 INVALID_STATUS | denied (SDK maps to REVOKED — fail closed) | code:INVALID_STATUS |
expires_at passed | treated expired | denied | code:EXPIRED |
On the execute/capability guard path, any non-INVALID_STATUS gate verdict collapses to 403 FORBIDDEN — the specific code survives only in the license_blocked security event. /activate returns the gate verdict code verbatim (matrix §2 footnote).
How to revoke / suspend / restore
PATCH /api/v1/licenses/:id (seller-owner)
{ "status": "revoked" } // or "suspended", "active" (restore)
{ "expires_at": "…" } // can also force expiry2
3
Legacy plane: POST /licenses issues (lic_… id + NG-… key); PATCH /licenses/:id mutates status/expires_at.
Checking state
- Public (no auth, both backends):
POST /api/v1/licenses/verify{key[, product_id, device_id]}→{valid, code, status, product_id, product_name, expires_at, max_devices, activated_devices, device_registered, checked_at}. Lookup-only — does not consume a slot. Also exposed asyp license verify <key>and gateway toolyetdapay_license_verify. - Entitled client (Worker PoP):
GET /api/v1/licenses/status(entitlement + DPoP) →{license:{product_id, product_name, status, expires_at, max_devices, bound_devices, activated_devices, features, entitlement_exp}}. - Seller:
GET /api/v1/licenses(scoped list — keys not exposed),GET /licenses/:id/bindings,GET /licenses/:id/usage,GET /security-events?lic_id=— all reachable via the gateway'syetdapay_license_*tools or the seller console.
Incident posture
Revocation is the primary incident lever for a leaked/abused license — follow it with a security-events review for that lic_id (replay attempts, jkt anomalies, license_blocked rows). See Incident Response.