A game pass is bought once, from its own page on Roblox. This guide is for sellers who want to sell a product that way: linking the pass to your product, recording it from your game so the buyer gets their license, and what passes can't do.
Before you start
The product's license type must be One purchase. Set it under How buying works on the product's Pricing page.
You need an API key with the Grant and revoke licenses (licenses:write) scope. See API keys.
Your game needs Allow HTTP Requests switched on, under Game Settings → Security in Studio.
Your game needs a script that records the pass (below). The in-game hub only sells developer products, so it doesn't record passes. If you use the hub, you can add the script to the same place.
Create the pass and link it
Create a game pass for your experience on Roblox, and put it on sale.
Copy its ID: the number in the pass's URL.
On Enviglo, open the product and go to Delivery.
Paste the ID into Game pass ID, then press Save delivery.
Enviglo checks the pass with Roblox when you save. If something's wrong, the field says so:
"Roblox has no game pass with that ID. Check the number in the pass's URL."
"Game passes can only be bought once on Roblox. Use a developer product for this kind of license." The product's license type isn't One purchase.
"Another product in this store uses that game pass ID, or a deleted one that people still own."
Roblox decides the price. Enviglo reads it from the pass and shows it on your product page, so to change it, change the pass on Roblox.
How a buyer gets their license
On your product's page, they press Buy on Roblox. It opens the pass's page on Roblox, where they buy it.
They join your game. Your script sees they own the pass and records it with Enviglo.
Enviglo puts the license on the Enviglo account their Roblox account is linked to. If they haven't linked one, it waits on a placeholder account and moves to them when they link.
The product page tells buyers the same thing: buy the pass on Roblox, then join your game, and it lands in their library once their Roblox account is linked. There's nothing else to press on Enviglo. Point buyers who haven't linked Roblox to Link your Roblox account.
Record the pass from your game
When a player joins, the script asks Roblox whether they own each pass, and records the ones they do with POST /api/v1/licenses. It also records a pass bought while the player is in your game.
Put this in a Script in ServerScriptService. Replace YOUR_API_KEY with your key, and fill in PASSES with each game pass ID and the Enviglo product it gives. The product's Enviglo ID is the id that GET /api/v1/products returns for it.
-- EnvigloGamePasses: 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 MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local API_URL = "https://enviglo.com/api/v1"local API_KEY = "YOUR_API_KEY"-- a key with the licenses:write scope-- Each game pass, and the Enviglo product it gives: the product's id from GET /api/v1/products.local PASSES = {
[123456789] = "YOUR_PRODUCT_ID",
}
-- Tells Enviglo this player owns a pass. Safe to repeat: Enviglo records a pass once per player.localfunctionrecordPass(player, productId)local sent, response = pcall(function()return HttpService:RequestAsync({
Url = API_URL .. "/licenses",
Method = "POST",
Headers = {
["Authorization"] = "Bearer " .. API_KEY,
["Content-Type"] = "application/json",
},
-- No receiptId: a game pass isn't a receipt.
Body = HttpService:JSONEncode({
robloxId = tostring(player.UserId),
productId = productId,
}),
})
end)
ifnot sent then
warn("Enviglo: couldn't send the game pass:", response)
elseifnot response.Success then
warn("Enviglo: HTTP " .. response.StatusCode .. ": " .. response.Body)
endendlocalfunctioncheckPasses(player)for gamePassId, productId inpairs(PASSES) dolocal ok, owns = pcall(function()return MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamePassId)
end)
if ok and owns then
recordPass(player, productId)
endendend
Players.PlayerAdded:Connect(checkPasses)
for _, player inipairs(Players:GetPlayers()) do
task.spawn(checkPasses, player)
end-- A pass bought while the player is in this game.
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, gamePassId, wasPurchased)local productId = PASSES[gamePassId]
if wasPurchased and productId then
recordPass(player, productId)
endend)
Send no receiptId for a game pass. Enviglo keeps one record per player for each pass, so recording it every time they join is safe:
The first time, Enviglo answers 201 with "created": true, and the purchase shows under Orders → Purchases with the game pass's ID.
After that, it answers 200 with "created": false and the license it already has.
Revokes, transfers and passes
A pass is recorded once per player, and registering it again isn't a new purchase. So:
If you revoke the license, the player still has the pass on Roblox, but joining again doesn't bring the license back. Enviglo answers with the revoked license. The same happens if their license for the product was revoked before they bought the pass. To give it back, restore the license: see Give, revoke, restore and transfer licenses.
If the player gives their license to someone else, joining again doesn't bring it back, and neither does buying the pass after giving a license for the product away. Enviglo answers 409: "This player gave their license for this product to someone else. A new purchase, with its receiptId, gives them another." A pass can't be bought twice, so there's no new purchase for them to make.
The new owner holds the license on Enviglo, but not the pass on Roblox. If your game unlocks things by checking the pass itself, it won't agree with Enviglo. Check licenses through Enviglo instead: see Check licenses in your game.
To keep pass licenses with the people who bought them, turn on Block customer transfers for this product on the product's Pricing page. Your team can still move a license.
Limits
One purchase only. A pass can't be bought twice on Roblox, so Buy more than once and Subscription products need a developer product. See Sell with developer products.
Not in the in-game hub. The hub sells developer products only.
Sales need game-pass access. To run a sale on a pass, your Roblox experience must be connected with an API key that has game-pass write. See Discounts and sales.
Both on one product. If a product has a developer product and a game pass, Buy on Roblox opens the pass's page.
Troubleshooting
Nothing is recorded. Check Allow HTTP Requests is on, the key has Grant and revoke licenses, and the ID in PASSES is the product's Enviglo ID. A wrong ID answers 404: "Product not found in this store. Pass productId or robloxProductId."
Enviglo answers "created": false with a revoked license. Your store revoked this player's license. Restore it if they should have it.
429 "Too many licenses recorded in the last minute. Wait a moment and retry." A key can record 300 a minute, repeats included. In a busy game, ask GET /api/v1/licenses/check first, which has no fixed limit, and only record passes Enviglo doesn't have yet. That needs the Check licenses scope on the key as well.
The product page shows Off-sale on Roblox. Put the pass back on sale on Roblox, then press Check Roblox at the top of the product's Delivery page.