Integration API
Build your own in-app unlock UI. Your script asks for the key, AegisLoader checks it and binds it to the device.
How Custom mode works
In Custom mode the loader is bare: it never draws a key prompt. Your script owns the unlock — your ScreenGui, your branding, your copy — and hands the key to the loader before running it. A TextBox, a key saved from last session, or an ad unlock you trigger yourself all work.
The loader still does the real check. It computes the device’s HWID, verifies the key with AegisLoader and binds it to that device on first use. Validating from your UI is for a friendly error message, not for security.
- Your UI gets a keyFrom a TextBox, a saved file, or the ad unlock.
- Optional: validate itCall validate so you can say “expired” or “locked to another device” in your own words.
- Set
getgenv().KeyThe loader reads it once when it starts. - Run the loader lineIt checks the key, binds the HWID and runs your protected build. A bad key stops it before any of your code executes.
Endpoints
Base URL https://api.aegisloader.com. Every endpoint here is public and called from the client — no API key. Never put your account key in a script you ship. Responses are JSON.
{id} is a key system ID or a Custom script ID — a short code like gu93Zx0LH3 (it’s in your script’s loader line). The samples on this page use .
Rate limits
Limits are per IP, so one user hammering a button can’t lock out everyone else. There’s no 429 — over the limit the endpoints fail soft: validate answers 200 with "ok": false and "reason": "key unavailable" (back off — don’t validate on a loop), and /gate/…/wait returns {} — the same as “not ready yet” — so just reconnect.
| Endpoint | Limit | Per | Notes |
|---|---|---|---|
| /api/validate | ~120 / min | IP | Validate once when the user submits a key, not on a loop. |
| /gate/…/wait | ~60 / min | IP | Each call long-polls ~25s, so one covers a long wait — reconnect when it returns {}. |
Errors
A bad key is not an HTTP error: validate answers 200 with "ok": false and a reason. A non-200 means the request itself was wrong or we couldn’t answer it.
| Status | reason | Meaning |
|---|---|---|
| 200 | ok: true | The key is good for this device — see validate for the fields. |
| 200 | key unavailable | Too many validate calls from this IP. Back off — don’t validate on a loop. |
| 400 | bad id | The {id} is malformed. Check you copied it from this page. |
| 404 | unknown project | No key system or Custom script has that {id}. |
One key, every script
A key system groups Custom scripts behind one set of keys. A key issued by the key system — by hand or earned through its ad unlock — runs every attached script that takes the system key. Your users unlock once; you ship as many scripts as you like.
Key source, per script
Each attached script chooses which keys it accepts. Change it from the script’s row in Projects.
- System key
- Accepts keys issued by the key system, including ad-earned ones. This is the default when you attach a script.
- Own keys
- Ignores system keys and only accepts keys created for this script. Use it for a premium script that sits next to free ones in the same hub.
Running several scripts
getgenv() lives for the whole session, so set getgenv().Key once and every loader you run after it picks the key up. A script on its own keys needs its own key set before its loader runs.
Each connected script decides whether it takes the system key or its own. To check whether this key unlocks a particular script, call validate with that script’s own {id}.
The getgenv().Key convention
The loader reads getgenv().Key once, when it starts (a plain global Key works too). Set it, then run the loader line — in that order, in the same script.
| Value | What the loader does |
|---|---|
| "A3KP9-…" | Trims whitespace, verifies the key and binds it to this device on first use. Runs your script if it’s valid. |
| nil | Stops and warns [Aegis] no key set in the console. Your script never runs. |
| invalid key | Stops and warns [AegisLoader] with the server reason — invalid key, key expired, key banned or key locked to another device. |
You don’t send the HWID
Keys bind to the first device that runs them. If a user moves to a new PC, reset the key’s device from Users & Keys — don’t hand out a second key.
Full example: key prompt with a saved key
A minimal prompt in a ScreenGui. It remembers the last key with writefile so returning users skip the prompt, and falls back to asking when the executor has no file functions.
Validate a key
Checks a key for one device without running anything. Doesn’t bind the key — the loader does that on first run.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | path · string | required | Key system or Custom script ID. Yours: |
| key | query · string | required | The license key the user entered, URL-encoded. Format XXXXX-XXXXX-XXXXX-XXXXX. |
| hwid | query · string | optional | RbxAnalyticsService:GetClientId() — the device the loader binds keys to. Omit it and the check can’t evaluate device binding: ok then reflects only the key’s stored state (expiry, ban, activated) and key locked to another device is never returned. Send it to learn whether this key would actually run on this device. |
Request
Responses
| Field | Type | Description |
|---|---|---|
| ok | boolean | Whether the loader would run with this key on this device. |
| mode | string | The project’s delivery mode — free, ad, paid, api or keysystem. (A Custom-mode script reports api — “Custom” is only the dashboard label; ad-earned keys report ad.) |
| expires | number | Unix timestamp in seconds when the key stops working. 0 for keys that never expire. |
| activated | boolean | Whether the key is already bound to a device. The raw device ID is never returned. |
| rt | string · optional | A sealed resume credential (ar1.…). Returned only when the project has resume enabled and the submitted key is valid. Persist it instead of the raw key and replay it on the next launch to skip the prompt; absent otherwise. |
| reason | string | Only when ok is false. One of the reasons below. |
Reasons
| reason | What happened | Tell the user |
|---|---|---|
| key expired | The key’s duration ran out. Ad-earned keys always expire. | “Your key expired. Get a new one.” |
| key banned | You banned the key or the device in Users & Keys. | “This key has been revoked.” |
| key locked to another device | The key is bound to a different device. | “This key is locked to another device.” |
| invalid key | No such key for this ID — typo, wrong format, or a key from another script. | “That key doesn’t exist. Check for typos.” |
| key required | The request reached validate with an empty key parameter. | “Enter your key.” |
| key unavailable | Transient server read error, or you hit the ~120/min per-IP rate limit. Retry. | “Try again in a moment.” |
Validate, then run
Wrap the request in pcall — HttpGet throws on network errors and on non-200 responses.
~120 requests a minute per IP. Validate when the user submits, not on a loop.
Ad unlock from your own UI
Same Linkvertise gate Ad-supported projects get, started from your button. You send the user a gate link; they finish a short ad step in their browser; your script long-polls until the key is ready. The link, anti-bypass check and key duration come from Ad Rewards — set those up first.
- Make a tokenAny random string, unique to this user this run. It ties their browser unlock to your waiting script.
- Send them the linkExecutors can’t open a browser, so
setclipboardthe gate link…/gate/{id}={token}and tell them to paste it. They pass a human check and the ad step. - Wait for the key
GET …/gate/{id}={token}/waitholds open ~25s and returns{"key":…}the moment they finish — or{}on timeout, so just call it again. - Run with the earned keyThe key is already bound to this device. Set
getgenv().Keyand run the loader.
The gate link
The URL the user opens in a browser. For a connected script that rides its key system’s ad, use the key system’s {id} here — that’s the authority that mints the key.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | path · string | required | Key system or Custom script ID. Yours: |
| token | path · string | required | Appended after =. You generate it — 16 hex chars is plenty. Use a fresh one each attempt. |
Offer a provider choice in your UI
With two or more ad providers enabled (Linkvertise, LootLabs, Work.ink), you can let users pick in your own UI instead of on the gate page. Turn on “Let users choose the ad in your own UI” in Ad Rewards, read the enabled providers, and show a button per provider that opens its gate link.
Public, read-only. Lists the ad providers enabled for this key system. Yours:
{
"providers": [
{ "id": "linkvertise", "name": "Linkvertise" },
{ "id": "lootlabs", "name": "LootLabs" },
{ "id": "workink", "name": "Work.ink" }
],
"gate": "https://api.aegisloader.com/gate/{id}",
"ttl": 86400,
"pick_in_ui": true
}Send the user to the gate link for their choice — the same gate link, with ?provider={id} appended:
Goes straight to that provider’s ad. If pick_in_ui is false, or a user reaches the gate without a ?provider= (opened it directly, didn’t pick in your UI), the gate shows its own chooser — so a bare /gate/{id}={token} always works too.
After they finish, poll /gate/{id}={token}/wait for the key exactly as below — the flow from here is identical no matter which provider they chose.
Wait for the key
A long-poll: one request is held open until the unlock completes (up to ~25s), then returns the key. On timeout it returns {} — reconnect and it keeps waiting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | path · string | required | Same ID you built the link with. |
| token | path · string | required | The same {token} you built the link with. |
Luau: “Get key” button
Make a token, copy the gate link for the user, then long-poll /wait with game:HttpGet until the key arrives — no executor request needed, since the whole flow is plain GETs.
Each /wait covers a ~25s wait — loop the reconnect, not a tight poll. The gate link stays valid a few minutes.