Saved Sep 23, 2026 by @enviglo: Settings tabs, your own Discord bot, custom domains, and giving products by Discord ID or email
Licenses belong to Enviglo accounts, and the check finds them through the account a player's Roblox account is linked to.- - **They bought it in game.** The check finds it even if they've never visited Enviglo. The license waits on a placeholder account that belongs to their Roblox ID, and moves to their own account when they link.+ - **They bought it in game.** The check finds it even if they've never visited Enviglo. The license waits for their Roblox ID, and moves to their Enviglo account when they link.- **They got it on Enviglo.** A free product, a code, or a license your team gave to their username sits on their Enviglo account. Your game can't see it until they link the Roblox account they play on, so `owned` is `false` until then.If a player says they own something your game can't see, ask them to link Roblox in **Settings** → **Connections** on Enviglo. [Link your Roblox account](/wiki/link-your-roblox-account) shows them how. Once they have, the next check finds it.…
Your game can ask Enviglo whether a player owns one of your products, and unlock it if they do. This guide is for sellers who script their own games. The check covers everything a player owns from your store, however they got it, as long as it's on the Enviglo account their Roblox account is linked to.
licenses:read) scope. New keys have it ticked. See API keys. The in-game hub's key won't do: it has no API scopes.GET /api/v1/products lists both, as id and robloxProductId.Send a GET to https://enviglo.com/api/v1/licenses/check with your key and these query parameters:
| Parameter | What it is |
|---|---|
robloxId | Required. The player's Roblox user ID. |
productId | The product's Enviglo ID. Send this or robloxProductId. |
robloxProductId | The product's developer product ID. |
To try it outside Roblox:
curl "https://enviglo.com/api/v1/licenses/check?robloxId=1002&robloxProductId=1234567890" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"owned": true,
"banned": false,
"copies": 1,
"product": { "id": "clx7a1b2c", "name": "Advanced Admin", "licenseType": "SUBSCRIPTION" },
"license": {
"id": "clx8f2k0a0001",
"source": "ROBLOX_PURCHASE",
"quantity": 1,
"expiresAt": "2026-10-18T04:12:09.000Z",
"createdAt": "2026-09-18T04:12:09.000Z"
}
}
owned: whether they have it right now. A revoked license or a subscription that has run out doesn't count.banned: whether you've banned this player, or the Enviglo account they linked. A banned player never owns anything from your store, so check this before offering a purchase.copies: how many they hold. Every purchase of a Buy more than once product is a license of its own, and this counts them. It's 0 for a banned player.product: the product's id, name and licenseType. The license types are SINGLE, MULTIPLE and SUBSCRIPTION: One purchase, Buy more than once and Subscription in the dashboard.license: their live license, or null if they have none. source says how they got it, such as ROBLOX_PURCHASE, GRANT or TRANSFER. expiresAt is when a subscription runs out, and null for everything else.This script checks one product for each player who joins, and keeps the answer while they're in the server. Put it in a Script in ServerScriptService, and fill in your key and the product's Enviglo ID.
-- EnvigloOwnership: a Script in ServerScriptService.
-- It holds your API key, so keep it a server Script. Never a LocalScript, and never in ReplicatedStorage.
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local API_URL = "https://enviglo.com/api/v1"
local API_KEY = "YOUR_API_KEY" -- a key with the licenses:read scope
local PRODUCT_ID = "YOUR_PRODUCT_ID" -- the product's id from GET /api/v1/products
-- Each player's answer, kept while they're in this server.
local answers = {}
-- Asks Enviglo whether a player owns the product. Returns the answer, or nil if it couldn't ask.
local function checkLicense(player)
local url = API_URL .. "/licenses/check?robloxId=" .. tostring(player.UserId)
.. "&productId=" .. HttpService:UrlEncode(PRODUCT_ID)
local sent, response = pcall(function()
return HttpService:RequestAsync({
Url = url,
Method = "GET",
Headers = { ["Authorization"] = "Bearer " .. API_KEY },
})
end)
if not sent then
warn("Enviglo: couldn't check a license:", response)
return nil
end
if response.Success
warn( .. response.StatusCode .. .. response.Body)
decoded, answer = (
HttpService:JSONDecode(response.Body)
)
decoded
answer
answer = checkLicense(player)
answer
answers[player] = answer
answer.banned
(player.Name .. )
answer.owned
(player.Name .. .. answer.product.name .. .. answer.copies .. )
answer.license answer.license.expiresAt
( .. answer.license.expiresAt)
(player.Name .. .. answer.product.name)
Players.PlayerAdded:Connect(onPlayerAdded)
_, player (Players:GetPlayers())
task.spawn(onPlayerAdded, player)
Players.PlayerRemoving:Connect(
answers[player] =
)
If you sell several products, one call can fetch them all. GET /api/v1/licenses?robloxId= answers with banned and a licenses list: every license that gives the player access right now, each with its product. A banned player comes back with an empty list. Add this to the script above:
-- Every product a player owns in your store, as a set of Enviglo product ids.
-- Returns nil if it couldn't ask. Uses API_URL and API_KEY from the script above.
local function ownedProducts(player)
local sent, response = pcall(function()
return HttpService:RequestAsync({
Url = API_URL .. "/licenses?robloxId=" .. tostring(player.UserId),
Method = "GET",
Headers = { ["Authorization"] = "Bearer " .. API_KEY },
})
end)
if not sent or not response.Success then
return nil
end
local decoded, data = pcall(function()
return HttpService:JSONDecode(response.Body)
end)
if not decoded then
return nil
end
local owned = {}
for _, license in ipairs(data.licenses) do
owned[license.product.id] = true
end
return owned
end
A product bought more than once appears once for each purchase. The full details are in the API reference.
Licenses belong to Enviglo accounts, and the check finds them through the account a player's Roblox account is linked to.
owned is false until then.If a player says they own something your game can't see, ask them to link Roblox in Settings → Connections on Enviglo. Link your Roblox account shows them how. Once they have, the next check finds it.
UserId.