Redeem a license key on a customer's behalf
Server-to-server redemption — the primitive behind a Discord /redeem command or a panel's "add time" box. Identical semantics to redeeming in the loader: the same validation, the same protection against consuming a key that grants nothing, and the same license.used webhook.
Renewal works even when the subscription has already lapsed; time is added from now rather than from the old expiry.
### Tiers
A subscription is a single record with one level and one clock, so a key is only applied when the result is unambiguous:
- Higher tier — upgrades, and keeps the remaining time. - Same tier — extends. - Lower tier, subscription still active — refused as TIER_DOWNGRADE and *not consumed*. Extending at the higher tier would let cheap keys renew an expensive tier; dropping the tier would take away something already paid for. The key stays valid and works once the current subscription lapses. - Lower tier, subscription lapsed — accepted, and the key's tier applies from scratch. - Timed key against a lifetime subscription — refused as TIER_CONFLICT and not consumed, since "higher tier for 30 days, then back to lifetime" cannot be represented.
| userIdrequired string (uuid) | End-user UUID. |
| licenseKeyrequired string | Length: 4–512 |
{ "licenseKey": "ABCD-EFGH-IJKL-MNOP" }
{ "success": true, "message": "Subscription updated", "data": { "appId": "864a...", "appName": "Lunar", "extended": true, "subscriptionLevel": 2, "subscriptionName": "Pro", "expiresAt": "2026-10-01T00:00:00.000Z" } }
code is one of INVALID_KEY,
ALREADY_REDEEMED, ALREADY_REDEEMED_BY_YOU, NO_BENEFIT,
TIER_DOWNGRADE, TIER_CONFLICT.
{ "error": "This key provides no additional benefit for the current subscription", "code": "NO_BENEFIT" }
{ "error": "This key is for a lower tier than the current subscription. It has not been used — redeem it once the current subscription expires.", "code": "TIER_DOWNGRADE" }
{ "error": "A timed key cannot upgrade a lifetime subscription. It has not been used — a lifetime key of the higher tier is required.", "code": "TIER_CONFLICT" }
KEY_BANNED, KEY_PAUSED, NOT_FOR_THIS_USER, HWID_MISMATCH, or QUOTA_EXCEEDED.{ "error": "This license key is locked to different hardware", "code": "HWID_MISMATCH" }
{ "error": "License already redeemed", "code": "RACE_LOST" }
More in Users
- getLook up a customer by username
- getList customers
- postCreate a customer
- getGet a customer
- putUpdate a customer
- deleteDelete a customer
- postMint a password-reset token
- postConsume a reset token and set the new password
- postBan a customer
- postUnban a customer
- postReset a customer's HWID
- getRead a customer's two-factor state
- deleteReset a customer's two-factor authentication
- postReset a customer's device binding
- postMint a one-time SDK login token (panel SSO)
- postBulk customer actions
Base URL https://api.evora.lol/api/developer-api · full spec at developer-api.yaml · back to the docs