Free during the beta
Roblox, meet Solana.

One API key and one Luau module. Your players link a wallet, your servers read balances, hear about payments live and send tokens.

Link wallets
Players connect Phantom, Solflare or Backpack with one free signed message.

Read the chain
SOL, tokens and NFTs for any player, from any Roblox server.

Pay in SOL
Send SOL and tokens from the game's own wallet, inside your limits.
Works with the wallets your players already have
- Phantom
- Solflare
- Backpack
- + any Wallet Standard wallet
Platform
One key for the whole chain. Wallets, balances, live events and payments, from a single Luau module on your game servers.

rolink:GetWallet(userId)Link wallets
Every game gets a linking page we host. Players sign in with Roblox through your game's own OAuth app and sign a free message. Nothing is sent on-chain.

rolink:GetTokenBalance(address, mint)Read the chain
SOL, SPL and Token-2022 balances, NFTs and collections for any player, on devnet or mainnet. Cached by the API.

rolink.WalletLinked:Connect(...)Hear it live
Links, unlinks, transaction results and activity on addresses you watch reach every live server through Open Cloud.

rolink:TransferToken({ ... })Send tokens
Send SOL, send or mint tokens from your project's managed wallet, inside the limits you set. Idempotent, so a reward is never paid twice.
Made with Rolink
Rolink Tycoon pays real SOL. A live Roblox game on Rolink: players build a factory, link a wallet and earn SOL while they play.
27 upgradesDroppers, belts and a two-storey base that goes up piece by piece.
0.013 SOL an hourThe SOL Mine pays players at a finished base, every 15 minutes of play.
Never paid twiceEvery payout has its own idempotency key, inside a daily budget.
Linking page
A linking page for every game. Players open it in any browser, sign in on both sides and jump back in. The game never sees their keys.
Hosted at api.rolink.tech/link/your-game. You add your game's Roblox app once, and nothing is sent on-chain.
Sign in with Roblox
Official Roblox OAuth through your game's own Roblox app. Rolink reads the user ID, then revokes the token.
Pick a wallet and sign a free message
Phantom, Solflare, Backpack or any Wallet Standard wallet. Signing proves ownership and can't move funds.
Back in the game, live
Every live server gets
WalletLinkedwithin seconds, andGetWalletreturns the address.
Luau SDK
A few lines of Luau. Pass your key from Roblox Secrets and call it from any server script.
- Server-only:
Rolink.newrefuses to run on the client. - Every call raises a coded error you can branch on with
Rolink.errorCode. - Amounts are decimal strings, so large token amounts stay exact.
- Wallet lookups are cached and refreshed by live events.

local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local Rolink = require(game:GetService("ServerScriptService").Rolink)
local MY_MINT = "YourTokenMintAddress"
-- The project key from the dashboard, stored as a Roblox Secret.
local rolink = Rolink.new({
apiKey = HttpService:GetSecret("rolink_api_key"),
})
-- Your game's hosted linking page, to show players.
local LINK_URL = rolink:GetProject().linkUrl
Players.PlayerAdded:Connect(function(player)
local address = rolink:GetWallet(player.UserId) -- nil until linked
if address then
print(rolink:GetSolBalance(address)) -- "1.5"
print(rolink:GetTokenBalance(address, MY_MINT)) -- "12.5"
else
print(`{player.Name} can link a wallet at {LINK_URL}`)
end
end)-- `rolink` is the client from Rolink.new({ apiKey }). Live events need your
-- universe ID and an Open Cloud key in the dashboard.
-- Fires on every live server, seconds after a player links.
rolink.WalletLinked:Connect(function(userId, address, player)
if player then -- set only on the server the player is in
print(`{player.Name} linked {address}`)
end
end)
-- Also fires when another Roblox account claims the wallet.
rolink.WalletUnlinked:Connect(function(userId, address, player)
print(`{userId} unlinked {address}`)
end)
rolink.TransactionUpdated:Connect(function(update)
print(update.idempotencyKey, update.status, update.signature or update.error)
end)
-- New transactions on the addresses your project watches.
rolink.ChainActivity:Connect(function(activity)
print(`new transaction on "{activity.name}": {activity.signature}`)
end)-- Sent from your project's managed wallet. Allow the mint in the dashboard first.
local function claimDaily(player: Player)
local ok, result = pcall(rolink.TransferToken, rolink, {
to = player.UserId,
mint = MY_MINT,
amount = "1",
-- One payment per player per UTC day, even if this runs twice.
idempotencyKey = `daily:{player.UserId}:{os.date("!%Y-%m-%d")}`,
})
if not ok then
local code = Rolink.errorCode(result)
if code == "wallet_not_linked" then
-- ask the player to link a wallet first
elseif code == "player_rate_limited" or code == "hourly_budget_exceeded" then
-- your project's limits stopped it, try again later
end
return
end
print(result.status, result.signature) -- "confirmed" | "submitted" | "failed"
end# In the Rolink dashboard
01 Sign in with a Solana wallet free signature, no funds
02 Create a project devnet or mainnet
03 Add your Roblox OAuth app client ID + secret
04 Create an API key rlk_live_…, shown once
05 Store it as a Roblox Secret rolink_api_key
06 Create and fund the wallet SOL for fees, plus your tokens
07 Set transaction limits SOL cap, mints, hourly limits
08 Optional: live events universe ID + Open Cloud key
# Players then link at api.rolink.tech/link/<your-game>
Architecture
Why there's an API in the middle. Roblox can't do this part safely, so the hosted API does it for you.
Events return to every live server through Open Cloud
01Roblox can't open a wallet
A game can't talk to Phantom or any other wallet, so players link from a page we host for your game instead.
02Servers can't keep a key safe
Your project wallet lives in Turnkey. Rolink checks your limits before it ever asks Turnkey to sign.
03One key, nothing else to sign up for
Your servers send one project key. We run the RPC connections, cache reads and apply quotas.
Security
Careful with money by default. Transactions stay off until you allow SOL or a token, then only move inside your limits.
Read the security model
Keys stay in Turnkey
Your project wallet signs inside Turnkey's secure enclaves. We only store its ID and address, and players' keys never leave their wallet.
Turnkey
Projects stay apart
Every request is scoped to the project its key belongs to. Keys are stored as SHA-256 hashes, shown once and revocable.
x-api-key
Never paid twice
Reusing a key returns the original result instead of sending again. A failed one can be retried safely.
idempotencyKey
Honest expiry
A transaction is only reported expired once the finalized chain is past its blockhash and no up-to-date node knows it.
lastValidBlockHeight
Limits you set
Only mints you allow can move, with a per-transaction cap, hourly limits per wallet and per player, and optional budgets.
hourly_budget_exceeded
Secrets encrypted
Open Cloud keys are encrypted at rest and only decrypted to publish your project's events.
AES-256-GCM
Pricing
Free during the beta. Every project gets the full API with the same quotas. All you need to sign in is a Solana wallet.

$0while the beta lasts
- Hosted linking page for each game
- On-chain reads, cached
- Live events through Open Cloud
- Managed wallet and transactions
- Dashboard with keys, limits and usage
| Quota | Limit | Scope |
|---|---|---|
| Requests | 100,000 | per project, per UTC day |
| Burst | 600 | requests per minute, per project |
| Transactions | 1,000 | per project, rolling 24 hours |
| Projects | 5 | per developer |
What you pay yourself
Solana network fees and the SOL or tokens you send come from your project's managed wallet, which you fund from any wallet.
Limits reference

Plug your game into Solana. Sign in with a Solana wallet, create a project and drop the Luau module into your game.











