Scroll
EvoraDocs
Get started
C++ SDK
REST API
Manage
Endpoint reference
All endpoints
GETPlan quota and current usage
GETList applicationsPOSTCreate an applicationGETGet an applicationPUTUpdate an applicationDELETEDelete an application
GETApplication statisticsGETExtended overviewGETLogin activity by dayGETUser growth over timeGETLicense status breakdownGETSession trends
GETList licensesPOSTGenerate licensesGETGet a licensePUTUpdate a licenseDELETEDelete a licensePOSTBan a licensePOSTUnban a licensePOSTReset a license HWIDPOSTFreeze a licensePOSTResume a frozen licensePOSTAdjust license expiry by a signed deltaPOSTBulk license actions
GETLook up a customer by usernameGETList customersPOSTCreate a customerGETGet a customerPUTUpdate a customerDELETEDelete a customerPOSTMint a password-reset tokenPOSTConsume a reset token and set the new passwordPOSTBan a customerPOSTUnban a customerPOSTReset a customer's HWIDGETRead a customer's two-factor stateDELETEReset a customer's two-factor authenticationPOSTReset a customer's device bindingPOSTMint a one-time SDK login token (panel SSO)POSTRedeem a license key on a customer's behalfPOSTBulk customer actions
POSTAuthenticate a customer by license keyPOSTAuthenticate a customer by username and password
GETList a customer's subscriptionsPOSTGrant a subscription directlyDELETERemove a subscriptionPOSTFreeze a subscriptionPOSTResume a frozen subscriptionPOSTExtend a subscription by days
GETList tiersPOSTCreate a tierPUTUpdate a tierDELETEDelete a tier
GETList app variablesPOSTCreate or update a variableDELETEDelete all app variablesGETGet a variablePUTUpdate a variableDELETEDelete a variableGETList every user variable in the applicationGETList one customer's variablesPOSTSet a customer variableDELETEDelete all of a customer's variablesDELETEDelete a customer variable
GETList webhooksPOSTCreate a webhookGETGet a webhookPUTUpdate a webhookDELETEDelete a webhookPOSTFire a test deliveryGETRead the event stream (catch-up)
GETList blacklist entriesPOSTAdd a blacklist entryDELETERemove a blacklist entryGETList whitelist entriesPOSTAdd a whitelist entryDELETERemove a whitelist entry
GETList live sessionsDELETEKill a sessionPOSTKill every live session
GETList logsGETLog statistics
GETList sellersPOSTCreate a sellerGETGet a sellerPUTUpdate a sellerDELETEDelete a sellerPOSTAdd seller balance
GETList clientsPOSTCreate a clientPUTUpdate a clientDELETEDelete a clientGETList a client's application accessPOSTGrant application accessDELETERevoke application access
GETList entitlementsPOSTCreate an entitlementPUTUpdate an entitlementDELETEDelete an entitlementGETList entitlements attached to a tierPOSTAttach an entitlement to a tierGETResolve a customer's entitlements
GETList geo rulesPOSTAdd a geo ruleDELETERemove a geo rulePUTEnable or disable geo restrictions
GETList active leasesDELETERevoke a leaseGETSeat usage for a customer
Docs/API reference/Users

Redeem a license key on a customer's behalf

POSThttps://api.evora.lol/api/developer-api/users/{userId}/redeem
Requires scopelicenses:write

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.

Path parameters
userIdrequired
string (uuid)
End-user UUID.
Body
licenseKeyrequired
string
Length: 4–512
Request
{
  "licenseKey": "ABCD-EFGH-IJKL-MNOP"
}
Responses
200Redeemed.
json
{
  "success": true,
  "message": "Subscription updated",
  "data": {
    "appId": "864a...",
    "appName": "Lunar",
    "extended": true,
    "subscriptionLevel": 2,
    "subscriptionName": "Pro",
    "expiresAt": "2026-10-01T00:00:00.000Z"
  }
}
400Rejected without consuming the key. code is one of INVALID_KEY, ALREADY_REDEEMED, ALREADY_REDEEMED_BY_YOU, NO_BENEFIT, TIER_DOWNGRADE, TIER_CONFLICT.
Nothing to gain
json
{
  "error": "This key provides no additional benefit for the current subscription",
  "code": "NO_BENEFIT"
}
Lower tier while the current one is still active
json
{
  "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"
}
Timed key against a lifetime subscription
json
{
  "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"
}
403KEY_BANNED, KEY_PAUSED, NOT_FOR_THIS_USER, HWID_MISMATCH, or QUOTA_EXCEEDED.
json
{
  "error": "This license key is locked to different hardware",
  "code": "HWID_MISMATCH"
}
409Another request claimed the key first.
json
{
  "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