# Panda Key System — Full Documentation > Complete documentation for the Panda Key System (PandaAuth), concatenated as > Markdown for LLMs / AI agents. Source: https://pandauth.com/docs --- Getting Started # Welcome to Panda Auth Panda Auth is a universal authentication and licensing platform. It lets you lock any software behind a license key (a Roblox script, a desktop app, a Discord bot, a SaaS dashboard) and control who can run it. This guide explains what it does and how to start. Tap for sound ## What you get At its core, Panda Auth checks a key before your code runs. Around that check, it gives you the tools to create keys, share them, protect your script, and grow your project. - Generate and manage license keys from a dashboard. - Put your Roblox script behind a GetKey page, or skip the page with instant access. - Add licensing to desktop apps with the Panda-SDK V5 (C# and C++ only). - Store and obfuscate your script with Virtual Storage (VSS). - Connect Discord for roles, verification, and webhook alerts. ## Pick your path Not sure where to start? Choose the track that matches what you build. I make Roblox scripts Protect your script behind a key. Use a GetKey page or instant access. Start I build desktop apps Add licensing to a C# or C++ desktop app with the Panda-SDK V5. Start Just show me the basics Create a service, generate a key, and validate it in minutes. Start ## How this guide is organized The sidebar groups the docs by who you are and what you're trying to do: - **Getting Started** — what Panda Auth is, why it helps, and a quick first run. - **For Users** — if you just need to redeem and manage a key to use someone's software. - **For Developers** — build and configure a service from the dashboard, monetize and grow it, integrate the client libraries, and use Virtual Storage. - **API Reference** — endpoints, authentication, and permissions for direct API use. New here? Read What is Panda Auth next for the full picture, then jump to Quick Start when you want to build. --- Getting Started # What is Panda Auth Panda Auth R3 is a universal authentication and licensing platform. It controls who is allowed to use the software you ship, without you having to build login systems, license servers, or anti-piracy tooling yourself. Tap for sound ## The short version You point your app at our API, and we handle the rest: issuing keys, verifying users, locking access to specific devices, blocking abusers, and, if you want, monetizing the key handout through ads or subscriptions. The public name is **Panda Auth**. The "R3" marks the third generation, a ground-up rewrite of the older Panda Key System with a faster dashboard, a cleaner API, and modern security. ## What you can build with it Panda Auth is universal. It is not tied to one language or platform. If your software can make an HTTPS request, it can talk to Panda Auth. - Roblox scripts and game hubs (the largest community using us today) - Roblox executors and loaders (full session control via our WebSocket layer) - Discord bots (premium command unlocks, per-server licensing) - Windows desktop apps (installers, paid tools, internal utilities) - Websites and SaaS dashboards (gating premium pages or API access) - Mobile apps, CLI tools, browser extensions, game mods: anything that can hit a URL The underlying contract is just HTTP, so any language works. We ship documentation and sample code for `Lua`, `JavaScript`, `Python`, and `C#`. ## Roblox-specific features A few features only make sense for Roblox Lua and only work there. They're clearly labeled in the dashboard. The main one is the **Virtual Storage System (VSS)**. It lets you ship encrypted Lua scripts that only execute inside a verified session. We also integrate with Lua obfuscators like Luraph and IronBrew. Everything else is platform-neutral Keys, HWID locking, checkpoints, monetization, captchas, and analytics work the same no matter what you build. Only VSS and the Lua obfuscators are Roblox-only. ## The core pieces - **Keys** — license keys you generate and hand out. Format looks like `PANDA-XXXX-XXXX-XXXX-XXXX`. - **HWID locking** — bind a key to a single device so it can't be shared. - **Checkpoints** — make users clear 1 to 10 ad steps before they get a key (optional). - **GetKey page** — the public page where your users obtain a key. - **VSS** — encrypted Lua script hosting (Roblox only). - **Dashboard** — real-time stats, analytics, webhooks, branding, and team permissions. We've been building in this space for years. Panda Auth R3 is the result of everything we learned from the earlier versions. --- Getting Started # Why Panda Auth What makes Panda Auth different from rolling your own auth, or from other key systems. ## Why people pick it - **Built-in monetization, optional.** Route free users through ad walls (Linkvertise, Lootlabs, Workink, ShortJambo and more) before they get a key. We handle the integrations, callback verification, and anti-bypass logic. You collect the ad revenue directly, and we don't take a cut. - **Real anti-abuse.** HWID locking, VPN detection, ASN blocklists, multi-account caps, ad-block detection, bot detection, IP packet inspection, and a configurable security gate are all built in. - **Checkpoints, not just keys.** Require 1 to 10 monetization checkpoints before a key, with different ad providers per checkpoint and per-duration tiers (e.g. a 6-hour key needs 1 step, a 48-hour key needs 4). - **A dashboard people actually use.** Real-time stats, per-service analytics, Discord webhooks, contributor permissions for teams, and custom branding for the key page. - **Universal API.** One auth platform across every project you ship, regardless of language or runtime. - **A free tier that's actually usable.** Your keys work, your users get through checkpoints, your monetization pays out, without being rate-limited into uselessness. ## Plan tiers There are five tiers. Three are free, two are paid. Free plans are enough to build, learn, and earn. Paid plans add scale, polish, and premium features. FREE free The entry plan. Create a service, hand out keys, monetize through ad checkpoints, and use the core API. A real plan, not a demo. Best for: First-time users, hobbyists, a single small project. BASIC free The default tier for new signups. Slightly higher limits than FREE, with more services, more keys, and broader features. No payment required. Best for: Regular hobbyist developers shipping a few projects. SPECIAL free Granted by us to high-traffic operators, not bought. Feature-identical to PREMIUM. The recognition path for creators whose traffic already justifies that level. Best for: High-traffic services and large hubs, recognized by us. PREMIUM paid The everyday paid plan. Higher limits across the board, active-monetization features, faster HWID reset cooldowns, expanded VSS quota, and priority support. Best for: Developers earning real money who want headroom on their own timing. ENTERPRISE paid The top tier. Highest limits, every feature unlocked, custom domain support for the key page, and white-glove support. Best for: Large-scale projects, businesses, anyone who has outgrown PREMIUM. SPECIAL vs PREMIUM They are feature-identical, with the same toolset and the same ceilings. The only difference is the path: PREMIUM is the paid route you choose anytime; SPECIAL is granted by us when your traffic crosses into "big users" scale, at no cost. ## When to upgrade You won't be artificially crippled on the free tier. You'll just hit ceilings on volume and miss the bells-and-whistles: custom domains, expanded analytics windows, premium ad-provider integrations, and higher quotas. The moment a free-tier limit costs you more than the paid plan would, that's when it's time to upgrade. Not before. --- Getting Started # How It Works From your user clicking 'get key' to your code letting them in, here's the full flow. ## The big picture Your software asks Panda Auth one question: "is this key allowed to run here, right now?" Everything else (handing out the key, making users pass ad checkpoints, locking the key to a device) happens around that one check. ## The GetKey flow 1 Your app sends the user to the GetKey page The user opens your GetKey link, which carries their device id: /getkey/{identifier}?hwid={user-hwid} . Your client library detects the HWID automatically. 2 The user clears the checkpoints If you've enabled monetization, the user passes your configured checkpoints (1 to 10), one ad provider at a time. 3 A key is generated After the last checkpoint, Panda Auth issues a key (for example PANDA-A8F3-K9X2-M7B4 ) bound to that HWID, with whatever expiry you set (e.g. 24 hours). 4 The user pastes the key into your software Your script or app takes the key from the user. 5 Your code validates the key Your client library sends the key + HWID to Panda Auth. The result is one of: Valid , Expired , Invalid , or Blacklisted . You let the user in only on Valid. ## Why HWID matters A key is tied to the device that requested it. If someone copies the key to another machine, the HWID won't match and validation fails. This is what stops one paid (or ad-earned) key from being shared with a whole server. Instant Access skips the page You don't have to use a GetKey page at all. With Instant Access mode you grant access by HWID directly, with no checkpoints and no key to paste. See Instant Access Mode under For Developers for setup. ## What you configure The flow above is the default. From the dashboard you decide how many checkpoints, which ad providers, how long keys last, what the GetKey page looks like, and which security checks run. The next page walks you through your first run end to end. --- Getting Started # Quick Start Creating a Panda Auth R3 account takes about two minutes. Pick the account type that fits how you'll use the platform, fill in the form, verify your email, and you land in your dashboard ready to create your first service. This page walks through the full registration flow for a Developer account — the path most operators take. ## Step 1 — Open Panda Auth R3 Go to [pandauth.com](https://pandauth.com/). You land on the marketing site. In the top-right of the navbar (or behind the hamburger menu on mobile), click **Get Started**. Panda Auth R3 landing page The Get Started button in the navbar ## Step 2 — Pick an account type Two options appear: **User / Client** and **Developer**. Pick the one that matches what you want to do: Account type selection - **User / Client** — for users who just want our dashboard to track the keys they have collected from various services. No service creation, no API access. Use this if you're an end user. - **Developer** — for developers who want to monetize scripts, software, or anything else through Panda Auth. Full dashboard, service creation, API access. Use this if you're a creator. **This is what the rest of this page covers.** ## Step 3 — Pass the captcha After selecting Developer, you're prompted to solve a captcha to confirm you're a real person before continuing. Captcha challenge If the captcha doesn't load Refresh the page. Captcha widgets occasionally fail to load on first paint and a simple refresh fixes it. ## Step 4 — Fill in the registration form The form asks for username, email, password, and a confirmation. If you already have a Panda Auth account, click the **Sign in** link instead to log in. For a fresh account, fill in every field, solve the captcha, then click **Continue**. Registration form ## Step 5 — Accept Terms and Privacy Before continuing, you're asked to accept our Terms of Service and Privacy Policy. Terms and Privacy acceptance Actually read them The Terms and Privacy Policy cover what you can and cannot do on the platform, how data is handled, and what rights you retain over your services and content. Worth a real read before accepting. ## Step 6 — Verify your email We send a verification code to the email you registered with. Open your inbox, find the email from Panda Auth, and copy the numeric code. Email verification prompt Paste the code into the verification input and click **Verify Email**. Enter the verification code If the email never arrives Check your spam folder. If it's not there either, click Resend code on the verification screen. If it still doesn't arrive after a couple of minutes, double-check you typed the email correctly. ## Step 7 — Land in your dashboard After verification, you're walked through a brief onboarding and dropped into your account dashboard. Brief onboarding Account dashboard Done — you're registered You now have a Developer account on Panda Auth R3. The next step is creating your first service — head to Create Your First Service in the For Developers section to continue. --- For Users # Redeeming a Key Got sent to a 'Get Key' page? Here's how to earn your key and unlock the software. ## What a key is A key is a short code, like `PANDA-A8F3-K9X2-M7B4`, that proves you're allowed to run a piece of software. You earn it once on the Get Key page, paste it into the app or script, and you're in. Your key is locked to **your device**. It won't work if someone else copies it onto a different machine, so there's no point sharing it. ## Getting your key 1 Open the Get Key link The creator gives you a link, or your software opens it for you. It knows your device automatically, so you don't enter anything. 2 Clear the checkpoints Most services ask you to pass a few ad steps (usually 1–5). Follow each one, then come back to the Get Key page. This is how free services stay free. 3 Copy the key After the last checkpoint your key appears. Tap Copy . 4 Paste it into the software Drop the key into the app or script where it asks for one. If it's valid, you're let straight in. Some services skip the page A few creators turn on instant access, with no checkpoints and no code to paste. The software just works the first time you run it. If you never saw a Get Key page, that's why. ## Keys expire Keys usually last a set time (for example 24 hours) decided by the creator. When yours runs out, just go back to the Get Key page and earn a fresh one, same steps as before. ## Common problems **"Invalid key"** — you may have a typo, or the key was for a different device. Re-copy it, or earn a new one. **"Expired"** — the key ran out. Get a new one. **"Blacklisted"** — that key was blocked. Contact the creator (usually via their Discord) if you think it's a mistake. Stuck on a checkpoint? Ad checkpoints are run by third-party providers, not by the software itself. If one won't complete, try a different browser or disable aggressive ad blockers for that step, then retry. --- For Users # Managing My Keys Every key you've earned lives in one place: your My Keys page. ## Where your keys live When you sign in as a regular user, you land on **My Keys**. It lists every key you've redeemed across the services you use, so you don't have to hunt for them again. That's the whole dashboard for you: My Keys plus your account Settings. Building services, monetization, and the rest are creator tools and stay out of your way. ## What you can do here **View a key** — see the service it belongs to, the key itself, and when it expires. **Copy a key** — grab it again to paste into the software without re-earning it (as long as it hasn't expired). **Remove a key** — delete one you no longer need to keep the list tidy. This only removes it from your list; it doesn't punish you with the creator. ## Expired keys An expired key can't unlock anything anymore. Remove it, then head back to that service's Get Key page to earn a fresh one. See **Redeeming a Key** for the steps. Keys are per-device A key in your list still only works on the device that earned it. If you switch computers, earn a new key on the new device rather than copying the old one. ## Your account settings Under Settings you can manage your profile and see your referral code. Inviting friends who sign up and use the platform earns you rewards. The Referral Program page (in the creator guide) covers how that pays out. --- For Developers · Dashboard # Create Your First Service A service is the unit of work in Panda Auth — it represents one piece of software you ship, with its own keys, settings, get-key page, monetization, and analytics. You can run multiple services from a single account, but every service starts here. This page walks through creating your first one and getting it ready for users. ## Step 1 — Create the service From your dashboard, click **Create Service** (or the new service button). The form asks for a few essentials: Create service form - **Service Name** — the public-facing name. Shows up on your get-key page header. Use whatever name your community already knows you by. - **Service ID (Identifier)** — the slug that identifies your service in every URL, API call, and library integration. Pick something short and lowercase. This is hard to change later, so get it right the first time. See **General Settings** for the full rationale. - **Discord URL** — optional. The invite link to your community server. - **Website URL** — optional. Your project's main website if you have one outside Panda Auth. The Identifier is permanent (for practical purposes) Once you start handing out get-key links and library integrations tied to a Service ID, changing it later breaks every existing link, bookmark, and script. Spend an extra 30 seconds picking a name you can live with. ## Step 2 — Configure the basics With the service created, you land on its settings page. The first things worth setting: Service settings — basic config - **Key Prefix** — a short brand string prepended to every key generated for this service. Example: setting it to **PANDA** produces keys like **PANDA_a8sdnwj...**. Pure cosmetic, but useful for branding and for distinguishing keys from different services in your support logs. - **Webhook URL** — if you want real-time notifications about key activity (validations, generations, HWID resets, blacklist actions), paste a Discord webhook URL here. Full configuration is in **Webhooks & Analytics**. - **Discord Server / Website URLs** — confirm or update the values you set during creation. ## Step 3 — Your service dashboard Once the basics are in, your service dashboard looks something like this: Service dashboard From here you have everything Panda Auth offers — Security, Monetization, Appearance, Key Management, the Vault, Client Connect, and more. The other pages in this section walk through each one in detail. ## What to configure next A few sensible next steps before you launch: - **Appearance** — upload your logo, set the button gradient, pick a background. A branded get-key page converts way better than a default one. - **Monetization → Revenue Settings** — connect at least one ad provider. Without this you won't earn anything from checkpoints. - **Security → Protection** — turn on the basics: Bot Bypass Lockdown and the Precheck Captcha Layer. The defaults are sensible; verify them before launch. - **Security → Checkpoints** — pick Variable mode and set the per-duration checkpoint counts. Or pick Standard if you want every user to follow the same flow. - **Webhooks & Analytics** — wire up a Discord webhook so you get notified when keys validate. You're ready to ship With the service created, branded, monetized, and protected, you have everything you need to start handing out keys. Share your get-key URL — https://ads.pandauth.com/getkey/ — with your community and watch the first completions come in. Open Client Connect in another tab if you want to watch users in real time. There's a lot here — take it section by section Panda Auth has many features and Service Settings is dense. Don't try to configure everything on day one. Get the basics live, hand out a few keys, learn what your real users do, and tune accordingly. The defaults are sensible for most cases — most operators only end up customizing 10-20% of the settings. --- For Developers · Dashboard # Dashboard Overview What each part of your service dashboard shows you. ## Stats cards The top of your service dashboard shows four numbers at a glance: Total Keys All keys ever created for this service. Active Keys Currently valid, non-expired keys. Validations Today Key validations in the last 24 hours. Unique Users Distinct HWIDs that have used the service. Service dashboard ## API key Each service has its own API key for external integrations (Discord bots, custom dashboards). There's a copy icon to grab it, and a regenerate button. Regenerating invalidates the old key immediately if it's ever compromised. ## GetKey link The public URL your users visit to obtain a key, in the form `/getkey/{identifier}`. Share it directly, or have your script open it automatically. ## Charts & analytics Graphs show validation trends, key-generation history, and a geographic map of your users. Toggle between 7, 14, and 30-day views. Tip Watch "Validations Today" against "Active Keys" to spot abuse. A spike in validations with flat active keys can mean key sharing. --- For Developers · Dashboard # General Settings General Settings is the Hub Details tab — the foundational config for your service. Service name, identifier, key prefix, key format, the API key for our public API, and the on/off switches for permanent links and key extension. Most of these settings only need to be set once, but the Identifier in particular is critical and worth getting right the first time. General Settings · Hub Details tab ## Service Name The display name for your service. It shows up as the header on your get-key page and in any branded surfaces (webhooks, Discord messages, key emails). Pick the public-facing name you want users to associate with your service — it can be changed later if you rebrand, but consistency is worth more than perfection here. Best practice Use the same name on your get-key page that your community already knows you by. If users find you in Discord as "MyHub" and land on a get-key page that says "EpicScripts Inc.", they will assume the link is phishing and bounce. ## Identifier The single most important field on this page. The Identifier is your service's slug — it identifies your service everywhere: the get-key URL, HWID reset endpoints, key validation, library integrations, our public API, webhook payloads. Treat it like a username — short, lowercase-friendly, and stable. Example: if your Identifier is `encryptedscriptss`, your get-key URL becomes `https://ads.pandauth.com/getkey/encryptedscriptss`. Set it carefully Changing the Identifier later breaks every link, every saved key page bookmark, every integration that uses the old slug, and every script your users have already loaded. Pick a name you can live with for the long haul. ## Discord URL **Optional.** The invite link to your Discord server. When set, it appears on your get-key page as a "Join Discord" link and on the key page so users can reach you for support. Leave blank if you do not have a Discord server or do not want to expose it. ## Key Prefix The string prepended to every generated key. For example, a Key Prefix of `PANDA` produces keys like `PANDA_a8sdnwj... long-random-tail`. The prefix is purely cosmetic — it does not affect validation or security. Use it for branding, for distinguishing keys from different services in your support tickets, or just to make keys look distinctly yours. ## Key Format How the random portion of the key is laid out. Two options: - **Randomized** — a single long random string. Example: `PANDA_a8sdnwjjdlasdjlkajsdkaljsdklgokilj`. More compact but harder to read or type by hand. - **Segmented** — random tokens split by dashes. Example: `PANDA_a8sd-nwjj-dlas-djlk-ajsd-kalj-sdkl`. Easier to read and type, looks more like a traditional license key. The dashes add no security, just readability. Pick what your users will see most If users always copy-paste their key, Randomized is fine. If they ever need to read or type it out (Discord support, manual entry on a different device), Segmented is much friendlier. ## Custom Button **Optional.** A button that appears on your get-key page below the "Continue" button. The most common use is selling permanent keys — set the button label to "Buy Permanent Key" with a link to your purchase page, and users see both the free flow and the paid option side by side. The button has two fields: - **Button Label** — the visible text on the button. Keep it under 30 characters so it fits on mobile. - **Button URL** — where it links. External payment pages, Discord boost links, your own website — any URL works. Leave both fields blank to hide the button entirely. ## API Key Your service's API Key for Panda Auth's public API. Use it when you build something that needs to talk to your service from outside the get-key flow — a custom Discord bot that validates keys, a license-management dashboard you build yourself, an analytics tool that pulls completion data. Security rules - **Never share this key publicly.** Not on GitHub, not in client-side code that ships to users, not in screenshots, not in support tickets. - **If it leaks, regenerate immediately.** The dashboard has a regenerate option that invalidates the old key the moment a new one is created. - **Use it server-side only.** Anything that runs in a user's browser or in a Lua script they load can read what is in front of it — the API Key does not belong there. ## Allow Permanent Link When this is on, users can reach your get-key page without their HWID being baked into the URL. The link becomes simpler — for example, `https://ads.pandauth.com/getkey/encryptedscriptss` without the `?hwid=...` parameter. The tradeoff is that your service depends on the get-key page collecting the HWID itself rather than receiving it from the referring script. - **Turn it on if:** You want a clean, shareable get-key URL — for Discord embeds, link bios, marketing materials. - **Turn it off if:** Your script or executor always provides the HWID in the URL and you want to enforce that contract. ## Allow Key Extend When on, users with an existing key can extend their key's expiration by completing extra checkpoints. For example, a user with a 6-hour key can run through one more checkpoint to add another 6 hours to it — no need to wait until expiration and start from scratch. Two related fields control the extension behavior: - **Addon Checkpoints** — how many extra checkpoints the user must complete to earn the extension. 1 is a common starting value. - **Addon Time** — how many extra hours the extension adds. Common values mirror your duration tiers (6, 12, 24). Why this matters Key extension is a major retention lever. Without it, a user whose key just expired has to start the full checkpoint flow over again, and many bounce instead of redoing the work. With extension on, a single extra checkpoint keeps them engaged and earns you another payout per session. Recommended defaults - Service Name: **Your public brand name** - Identifier: **Short, lowercase, stable** - Discord URL: **Your server invite** (or blank) - Key Prefix: **Your brand or a short identifier** - Key Format: **Segmented** (more user-friendly) - Custom Button: **Blank** until you have a paid offer - Allow Permanent Link: **On** (cleaner URLs for marketing) - Allow Key Extend: **On** with addon checkpoints = 1 and addon time matching your shortest tier --- For Developers · Dashboard # Appearance The Appearance tab lets you brand your get-key page with your own logo, colors, and background. Everything here is visual — none of it changes how the key flow works, only how it looks. A well-styled get-key page builds trust with new users and reinforces your brand for returning ones. Appearance · the configuration panel ## Service Logo The logo that appears in the top-left of your get-key page (and on the key-issued page, and in any branded webhook embeds). Upload a square PNG or JPG — anything roughly square works, but tall logos will be cropped to fit the slot. Best practice Use the same logo your community already recognizes. A newly-designed logo on your get-key page can read as suspicious to users who clicked through a link expecting your familiar branding. ## Button Gradient Two color pickers define the gradient for your primary action buttons — the "Get Key" button on the landing screen and the checkpoint progression buttons throughout the flow. The first color is the gradient's start (top-left), the second is the end (bottom-right). Below the pickers are five preset palettes: Purple, Blue, Green, Orange, Pink, Red. Click any preset to apply both colors at once — useful when you want a clean look without picking values yourself. ## Navbar Background The background color of the top navigation bar on your get-key page. Four built-in presets: - **Dark** — neutral near-black, the default for most services. - **Darker** — pure black, maximum contrast against light content. - **Navy** — deep blue, pairs well with cool brand palettes. - **Slate** — warm-gray, softer than pure black. Pick whichever harmonizes with the rest of your appearance config. ## Background The full-page background behind the get-key card. Two modes: ### Image Upload a static image — a screenshot from your software, custom artwork, a Discord-style banner. Upload PNG or JPG. Large images are scaled to fill the viewport. **Opacity** — a slider that controls how visible the background is behind the get-key card. 100% shows the image at full intensity; lower values fade it toward the navbar background color for better readability of the foreground. ### YouTube Video Paste a YouTube URL and the video plays on loop in the background, muted, no controls. Works great for animated banners, game footage, or atmospheric video that would feel awkward as a static screenshot. The same **Opacity** slider applies — fading the video improves readability of the get-key card on top. ## What the result looks like A configured Appearance setup produces a get-key page like this: The result on your get-key page Test on mobile too Most ad-checkpoint completions happen on mobile devices. After configuring Appearance, open your get-key page on a phone and confirm the layout reads well at narrow widths — backgrounds that look great on desktop sometimes crop awkwardly on mobile portrait. --- For Developers · Dashboard # Security The Security configuration page is split into five sub-tabs — Protection, Trust List, Vanguard, Authentication, and Checkpoints. Each one handles a different layer of how visitors reach your get-key page and how your keys behave once issued. Tune the dials up if you are being actively bypassed, down if real users are getting blocked. ## Protection Protection is where you decide how strict you want to be about who can reach your get-key page. Every setting here is a trade-off between blocking more bad traffic and making legitimate users wait or click more. The defaults are balanced; tune from there based on what your analytics show. Security Configuration · Protection tab ### Block AdBlock **What it does:** Detects visitors who have an ad-blocking browser extension installed and blocks them from continuing past your key page. They are shown a message asking them to disable their ad blocker before going further. **Why it matters:** Most of the ad providers we integrate with (Linkvertise, Lootlabs, Work.ink, Short-Jambo, and others) cannot show ads to users running an ad blocker. No ad shown means no payout to you, even if the user clicks through the rest of the checkpoint flow. - **Turn it on if:** You monetize through ads and want every checkpoint to actually count toward your payout. - **Turn it off if:** Your software is free with no monetization, or you would rather accept some lost revenue than turn away the segment of users who always run an ad blocker. ### Advanced Bot Bypass Lockdown Anti-Bot **What it does:** This is the browser-side equivalent of a network-level check. Instead of checking the visitor's IP, it scores their browser fingerprint — graphics card details, screen size, time zone, installed fonts, automation flags, and other signals that headless bots cannot easily fake. Tools like Playwright, Puppeteer, and headless Chrome leave specific hardware tells even when they spoof their user-agent string. Real users pass through invisibly with no extra clicks. Lockdown is OFF When this toggle is off, the dashboard shows a yellow warning. That means your service is exposed to automated bypass bots. Keep this on unless a real user is being incorrectly flagged and you are actively debugging it. - **Turn it on if:** You suspect automated bypass tools are hitting your key page. The dead giveaway is checkpoint completions with no actual ad views in your analytics. - **Turn it off if:** A specific legitimate user is being blocked incorrectly and you need to let them through temporarily. ### Captcha Type **What it does:** Picks which captcha is shown to visitors on the main checkpoint flow. This is separate from the precheck captcha below. - **hCaptcha** (default). Privacy-focused captcha with the "I am human" checkbox. - **Cloudflare Turnstile** — invisible most of the time, lightweight, modern. - **No Captcha**. No captcha shown, fastest user experience. Removed providers Geetest and Panda Captcha have been removed. Services that were set to either one were migrated to hCaptcha. They were not switched to No Captcha, so no service lost protection it had turned on. Best practice Use hCaptcha or Turnstile if you want strong protection without slowing real users down. Use No Captcha if you already have multiple other layers active (Anti-Bot, IP Inspection) and want the smoothest possible flow. ### Enable Precheck Captcha Layer /security_getkey **What it does:** Adds an extra captcha that appears before the user even reaches your main key page, on a dedicated security check screen. This is your first line of defense — bots that fail this never even get the chance to attempt your real key flow. **How the off state works:** When this is turned off, the precheck screen still loads, but instead of showing a captcha it just waits 10 seconds before letting the user through. The 10-second wait is useful as a fallback when a captcha provider is having outages or its CDN is slow — your users still get through, just with a brief delay instead of a broken widget. - **Turn it on if:** You want maximum bot protection right at the front door. - **Turn it off if:** Your captcha provider is being unreliable and you would rather have users wait 10 seconds than get stuck on a broken captcha. ### Precheck Captcha Type **What it does:** If the Precheck Captcha Layer is on, the security check screen shows **hCaptcha**. This is no longer a choice. Geetest was the only other option and has been removed, so the layer is either on (hCaptcha) or off (10-second wait). The token is verified on our servers before the gate opens. Recommended starting setup - Block AdBlock: **On** (if you monetize through ads) - Advanced Bot Bypass Lockdown: **On** - Captcha Type: **hCaptcha** or **Turnstile** - Enable Precheck Captcha Layer: **On** ## Trust List **What it does:** Enables manual whitelist and blacklist management at the device (HWID) level. When this is on, you get a searchable table where you can add specific HWIDs to either a whitelist (always allowed) or a blacklist (always blocked), along with notes about why each entry is there. The Trust List is its own tab and works on its own. Vanguard does not have to be on for it to take effect. - **Whitelist:** Trusted users you want to bypass certain restrictions for. Your own test device, a teammate's machine, or a verified premium user. - **Blacklist:** Specific devices you want permanently banned from your service. Devices you have caught attempting bypass exploits. - **Turn it on if:** You want hands-on per-device control. - **Turn it off if:** You would rather let the automatic systems handle device-level decisions. Most services do not need this. These lists also gate Kryptic Vault scripts The whitelist and blacklist you manage here are the same lists the Kryptic Vault Trust List reads. Turn Trust List on for a Vault script (Upload, or Edit → Trust List), link it to this service, and a blacklisted device is kicked with "You're Blacklisted from the Service (Your Service)" before the script is ever delivered. Pick Whitelist Only on the script to flip it around — only devices on the whitelist run it. One blacklist entry therefore covers your get-key page and every Vault script at once. ## Vanguard Advanced Vanguard is one master toggle. When it is off, the tab is effectively empty — that is the safe default and most services have no reason to flip it on. When it is on, one additional advanced setting appears underneath: **Protect Checkpoint Pages**. The HWID whitelist and blacklist used to live here too; they now have their own **Trust List** tab and no longer need Vanguard on. Think of Vanguard as a power-user layer. The Protection tab covers the vast majority of services. Vanguard exists for operators who want more granular control over who reaches their key page and who is allowed or banned at the device level. Security Configuration · Vanguard tab ### Enable Vanguard **What it does:** Activates the advanced protection system and reveals the sub-setting below it. With this off, your service still has full access to everything in the Protection tab — Vanguard does not replace those protections, it adds to them. **Default:** Off. This is intentional. Vanguard is opt-in because the controls it exposes are aggressive and best left untouched until you have a specific reason to use them. - **Turn it on if:** You want to enable Protect Checkpoint Pages. - **Turn it off if:** You have not run into a problem that the standard Protection tab cannot already solve. There is no downside to leaving Vanguard off — your service will not be less secure, it will just stay on the default configuration. ### Protect Checkpoint Pages **What it does:** Scans every incoming visitor before the get-key page is even rendered. Visitors that fail the scan never see your key page at all — they hit a security check first. This is a stricter gate than the toggles in the Protection tab, which run their checks as part of the get-key flow rather than before it. - **Turn it on if:** You are seeing checkpoint manipulation attempts that slip past the Protection-tab filters, and you want every visitor pre-screened at the door before anything renders. - **Turn it off if:** You want the standard get-key flow without the extra pre-render scan. Recommended default — Vanguard: Off Most services should leave this tab alone. The Protection tab handles 99% of real-world threats. Flip Vanguard on when you are an unusually attractive target for bypass tools and want the pre-render checkpoint scan as an extra layer. Banning or whitelisting a specific device does not need Vanguard: that lives on the Trust List tab. ## Authentication Authentication controls how your keys behave once they exist — how they are tied to a user, whether keys are required at all, how many accounts and devices each key can cover, and how sessions are enforced. These settings shape the actual licensing model of your service. Security Configuration · Authentication tab ### HWID Verification **What it does:** When this is on, every key issued by your service is bound to the hardware fingerprint (HWID) of the device that first redeemed it. After that, the key only works on that specific machine. Move it to another device and validation fails. **Why it matters:** This is the single biggest anti-piracy lever in the platform. Without HWID Verification, a key is just a string — anyone who gets a copy of it can use your software. With it on, the key is welded to one device, so leaks have zero value to anyone else. **Default:** On. Almost every service should keep this on. ### Keyless Mode **What it does:** Switches your service from "key-based" to "HWID-only" authentication. Instead of users redeeming a key, you maintain a whitelist of approved HWIDs and anyone on that list is allowed in automatically. **Use cases:** Closed beta groups, paid customer rosters where you manage the whitelist directly, internal team tools where everyone is hand-added. Note This is the always-on whitelist mode. We also offer a separate scheduled keyless mode for time-windowed access, which lives in its own configuration area. ### Multi-Account per Key **What it does:** Lets a single key be redeemed on more than one user account on the same device. The dashboard copy mentions Roblox accounts because that is the most common scenario, but the concept applies wherever your software interacts with platform accounts — Roblox usernames, Discord IDs, game profiles, and so on. **When this toggle is off:** One key, one platform account, no exceptions. **When this toggle is on:** Two sub-limits appear underneath: - **Free Users Limit:** Max accounts that can share a single key for users on your free tier. - **Premium Users Limit:** Max accounts that can share a single key for users on your premium tier (usually higher than the free limit, as a perk). - **Turn it on if:** Your users legitimately have multiple accounts on the same device (alts, household members, family-sharing) and you do not want to force them to buy or earn multiple keys. - **Turn it off if:** You want strict one-account-per-key licensing. The most piracy-resistant setup. ### Multi-HWID per Key Cross-device **What it does:** Allows a single key to be used across multiple devices. Without this, a key is locked to the first HWID that redeems it. With this on, the same key can be moved between, say, a user's desktop and laptop. Trade-off to be aware of Turning this on weakens HWID Verification. If a key gets leaked, anyone who has it can use it on their own device. Only turn this on if convenience matters more to your users than piracy resistance. - **Turn it on if:** Your audience legitimately uses multiple devices (a gaming PC and a work laptop) and you want to give them the convenience of one key across all of them. - **Turn it off if:** You want strict one-key-per-device licensing. Recommended for most services. Combined with HWID Verification on, this is the strongest anti-piracy setup. ### Session Limit Lock **What it does:** Restricts each key to one active session at a time. If a key is currently in use on one device and the same key tries to start a second session somewhere else, the new attempt is blocked (or the old one is kicked, depending on configuration). **Why this exists:** Even with HWID Verification on, users with multiple devices or with Multi-HWID turned on can run your software in two places simultaneously. Session Limit prevents that. - **Turn it on if:** You want to prevent simultaneous use of the same key, especially if you have Multi-HWID per Key turned on. Useful for paid services where one purchase should mean one concurrent user. - **Turn it off if:** Simultaneous use across the user's own devices is fine in your model. Recommended defaults For most services: - HWID Verification: **On** - Keyless Mode: **Off** - Multi-Account per Key: **Off** (turn on only if your users genuinely need it) - Multi-HWID per Key: **Off** - Session Limit: **Off** For a generous paid product (you sell licenses and want to treat customers well): - HWID Verification: **On** - Multi-HWID per Key: **On** (customers can use it on their desktop and laptop) - Session Limit: **On** (one license still means one concurrent use) ## Checkpoints The Checkpoints tab is where you decide how users earn a key. A checkpoint is one step of the monetization flow — typically one ad-wall visit, captcha, or task that the user has to complete before moving to the next step. More checkpoints means more revenue per user, but also more friction. Security Configuration · Checkpoints tab ### Checkpoint Mode This is the single most important decision in the tab. Two modes — Standard and Variable — work very differently. - **Standard:** Every key issued by your service requires the same number of checkpoints, no matter what. The user does not get a choice. Best for simplicity — one configuration, same flow for everyone. - **Variable:** Lets users choose their key duration on the get-key page, with different checkpoint counts for each duration. A shorter key requires fewer checkpoints. A longer key requires more. Best for monetization — users self-select into whichever tier matches what they actually need. ### 6 Hours Key Short duration option. The shortest tier, designed for users who just need access briefly. Typically configured with the fewest checkpoints (1 is the standard) so casual users are not turned away by friction. **Default checkpoints:** 1 ### 12 Hours Key Half day duration. The middle-short tier. A good in-between option for users who want more than a quick session without committing to a full day. **Default checkpoints:** 2 ### 24 Hours Key Full day duration. The most commonly chosen tier in most services — a 24-hour key is the sweet spot for users who want to use your software across a session without renewing. **Default checkpoints:** 3 ### 48 Hours Key Extended duration. The longest tier. Designed for users willing to spend the most upfront effort in exchange for a key that lasts the rest of the weekend. **Default checkpoints:** 4 ### How to set checkpoint counts Each duration card has a Checkpoints number input next to its toggle. You decide how many ad-wall or task steps a user must clear to earn that duration. The standard ramp is: - 6 hours → 1 checkpoint - 12 hours → 2 checkpoints - 24 hours → 3 checkpoints - 48 hours → 4 checkpoints This curve is what most services use because it scales effort in line with reward. Go more aggressive (5+ checkpoints on the longer tiers) if your audience converts well and you want to maximize revenue per user. Go gentler if your audience is sensitive to friction and you would rather have more completions. Why Variable Mode usually wins Variable Mode tends to outperform Standard Mode on payout for one reason — choice. When a user picks the 48-hour option themselves, they have already mentally committed to four checkpoints before they start. Friction feels like a fair trade because they chose it. The same user forced into four checkpoints under Standard Mode is far more likely to bounce halfway through. Letting them pick their own pain threshold is one of the cheapest revenue improvements you can make. Recommended setup For a new service: - Checkpoint Mode: **Variable** - 6 Hours Key: **On**, 1 checkpoint - 12 Hours Key: **On**, 2 checkpoints - 24 Hours Key: **On**, 3 checkpoints - 48 Hours Key: **On**, 4 checkpoints For maximum monetization (audience is loyal enough to accept friction): - 6 Hours Key: **Off** (force users into longer tiers) - 12 Hours Key: **On**, 3 checkpoints - 24 Hours Key: **On**, 4 checkpoints - 48 Hours Key: **On**, 5 checkpoints --- For Developers · Dashboard # Anti-Bypass Panda Anti-Bypass is our native, self-hosted defense against ad-link bypassers — no third-party middleman, no injected ads. It shows a short verification page before your ad, detects skipped ads and bypass tools, and can log the attempts and/or block them. It runs on top of Deep-BYPASS, so you can use both together. ## How it works When a user reaches a checkpoint, Panda sends them to a lightweight verification page (hosted by us — styled to your service) with a short timer, then on to your ad. The link the user completes points back to a Panda endpoint that verifies the completion **server-side**, using multiple independent checks that a real completion satisfies on its own. From those it produces a verdict and, depending on your settings, logs it and/or withholds the key. Panda checks the result — whether the ad was genuinely completed — rather than fingerprinting individual tools. That means it keeps working against new bypass services without needing an update for each one. ## The three controls - **Enable** — the master switch for this service. Off means the normal getkey flow, with no verification page. - **Logging** — record every verdict and fire your webhook. Observe-only; it never blocks. Leave this on for a while first to see your real traffic before enabling blocking. - **Blocking** — deny the key when a bypass is detected. The user sees a Blocked page instead of their key. Turn this on only after your logs look clean, so you don't block real users. If both Logging and Blocking are off, anti-bypass turns itself off (back to normal) — there's nothing to do with a verdict, so the page is skipped. ## Verification timer The timer (default **10 seconds**, adjustable 5–60s) is how long the user waits on the verification page before continuing to your ad. Keep it short for a good user experience — verification does not depend on the user waiting longer. ## Your Discord webhook Set a Discord webhook on the Anti-Bypass page and every verdict (or every blocked attempt) posts to your channel. This is separate from the platform-wide webhook the Panda team configures — if both are set,**both receive the log**. ## Working alongside Deep-BYPASS Panda Anti-Bypass runs **on top of** Deep-BYPASS. When both are enabled and the revenue mode is Deep-BYPASS-compatible, the ad the user is sent to (after the Panda page) is the Deep-BYPASS-protected link. If Deep-BYPASS is unavailable or errors, Panda falls back to its own protection so the flow never breaks. Configure both on the same **Anti-Bypass** page in your service settings — Panda on top, Deep-BYPASS below. ## Reading the logs Beyond the webhook, verdicts are stored and shown in the dashboard. Each record includes the score, the signals that fired, the action (allow / challenge / block), and the country · browser · device segment, so you can spot false positives per segment before turning on blocking. ## Defaults - Anti-Bypass: **off** per service (you opt in). - Logging: **on** once enabled. - Blocking: **off** — enable deliberately after reviewing logs. --- For Developers · Dashboard # Deep Bypass Deep Bypass is one of our most advanced anti-bypass features, built for developers who refuse to let their checkpoint flow be bypassed by Chrome extensions, userscripts, or specialty bypass tools. We collaborated with the Deep Bypass team to add a layer of protection that goes far beyond standard adblock detection — so you can maximize revenue without worrying about the bypass-tool arms race. Deep Bypass configuration ## Why Deep Bypass exists Bypass methods have evolved fast. A Chrome extension that automatically completes Linkvertise checkpoints is something a user can install in five seconds, and traditional protections (basic adblock detection, simple checksum validation) cannot catch it because the extension acts after the page loads and pretends to be a legitimate user. Specialty tools like userscripts, bypass services, and headless browser farms add layers on top of that. Deep Bypass tackles the problem at a different level — it monitors visitor behavior, browser internals, and completion patterns that bypass tools cannot easily fake. When a bypass tool tries to spoof completion, Deep Bypass catches the inconsistency and either blocks the user, drops them into a fallback flow, or flags them for additional friction. ## What you can configure The Deep Bypass tab has multiple categories of settings. Tune each to match how aggressively you want to defend your service. ### Invisible Mode Runs all detections silently in the background. Bypass tools think they succeeded — the page accepts their fake completion — but Panda Auth invalidates the result on the backend without telling the bypass tool why. The user gets stuck in a loop and eventually gives up; the bypass tool author never gets a clear error message to debug against. ### Time and Task Settings Controls how long a user must spend on a checkpoint before completion counts, and what activity Deep Bypass expects to see during that time. Bypass tools tend to skip directly from "page loaded" to "checkpoint complete" in milliseconds — Deep Bypass measures the gap and rejects unrealistic timing. - **Minimum Time** — minimum seconds before a checkpoint can be marked complete. 15–25 seconds is the sweet spot for most flows. - **Maximum Tasks** — caps the number of tasks Deep Bypass requires a user to clear, useful when balancing protection against user friction. ### Security Detections A set of toggles for specific bypass techniques. Each detection catches a different category of bypass tool: - **Referer Check** — verifies the user came from a legitimate referer, not a direct API call. - **Userscript Detection** — flags userscript managers (Tampermonkey, Greasemonkey) when active. - **AdBlock Detection** — flags users running ad blockers (independent of the simpler Block AdBlock toggle in Security → Protection). - **Unicode Detection** — catches bypass tools that inject zero-width or invisible Unicode characters to spoof input. - **Spoof Completion** — detects when a "completed" event was triggered programmatically rather than from a real user action. ### Bypass Service Presets Pre-built detection profiles for known bypass services. Toggle on the ones you want to actively block. Updated regularly as new bypass services appear. ### Revenue Booster A set of opt-in settings that increase ad payout at the cost of tighter user filtering: - **Block VPNs** — rejects VPN traffic entirely. - **Block Incognito** — rejects private/incognito browser sessions. - **Block Ad-Blockers** — harder version of the standard adblock toggle. - **Extra Wall** — adds an additional verification gate. - **Captcha Required** — forces captcha even when other layers would allow passthrough. - **Revenue Forcer** — disables the "Skip Ads" option on Linkvertise (~+30% CPM, Linkvertise-only). ### Fallback Mode Instead of hard-blocking a flagged user, Fallback Mode quietly redirects them to re-attempt the checkpoint. This is gentler than a hard block — legitimate users who got falsely flagged (false positives) get another chance, while bypass tools end up in an infinite loop they cannot escape. Maximum protection setup Turn on all five Security Detections, enable every Bypass Service Preset, turn on Fallback Mode, and enable every Revenue Booster you are comfortable with. Pair with the Security → Protection settings (Advanced Bot Bypass Lockdown + Detect Abnormal Session) for full-stack anti-bypass coverage. Test after every change Deep Bypass settings can sometimes catch legitimate users as false positives. After tightening any setting, walk through your own get-key flow in a fresh incognito window to confirm legitimate users still pass through. If you see drops in completion rate after a change, loosen the most recently changed setting first. --- For Developers · Dashboard # Key Management Key Management is where you generate, edit, and revoke keys for your service. The page is split into three tabs — Generated Keys (keys you have created but not yet been validated by a user), Active Keys (keys that have been validated and bound to a device), and Keyless/Whitelisted (HWID-only access for users without a key). Each tab has different operations available based on the key's lifecycle stage. The key lifecycle in one paragraph You generate a key in Generated Keys . The key has no HWID attached yet. A user enters the key on your get-key flow, which validates it against their device. On validation, the key moves from Generated Keys to Active Keys with the user's HWID bound to it. From that point forward, only that device can use the key. ## Generated Keys The Generated Keys tab is your key creation and pre-validation inventory. Every key you generate yourself (or through our API) lands here first. From this tab you can create new keys, edit their settings, and delete unused keys before they have been claimed by a user. Generated Keys list ### Generating a new key Click **Generate New Key** to open the creation form. You configure the key's attributes here; once saved the key is added to the Generated Keys list and is ready to be handed to a user. Generate new key form ### Prefix **Optional.** A custom prefix prepended to this specific key, overriding your service's default Key Prefix from General Settings. Useful for distinguishing batches — for example, generating a batch of giveaway keys with prefix **GIVEAWAY_** so your support workflow can tell them apart from sold keys at a glance. ### Number of Keys How many keys to generate at once. Generate one for a single user, or batch-generate hundreds for a giveaway or paid keystore export. ### Expiration Type Two ways the key can expire. You pick which one applies: Expiration Type — By Date vs By Days - **By Date** — a fixed calendar date. The key expires at that exact moment regardless of when the user validated it. Example: you generate a key on 06/04/2026 with expiration set to 06/06/2026. If the user redeems it on 06/05, they only get 1 day of use. If they redeem it on 06/06, the key is already expired and validation fails. - **By Days** — a duration that starts counting from validation. Example: 7 days expiration. The user redeems the key on day 4 after you generated it — the key still works for the full 7 days from the day they redeemed, expiring at day 11 from your generation date. The user always gets the full duration regardless of how long it sat unredeemed. Which to pick Use By Date for time-limited promotions where the offer ends at a fixed moment (Black Friday weekend, holiday event). Use By Days for sold keys where every customer should get the same usable time regardless of when they redeem. ### Premium Key A boolean toggle. When on, the key returns **isPremium: true** on validation. Your script or software can check that value and unlock premium features for those users. When off, the key returns isPremium: false and unlocks only the standard tier. What "premium" actually means is up to you — Panda Auth does not enforce a specific premium feature set. You decide what premium unlocks in your software, and this flag tells your code whether the validating key has earned that tier. ### Number of Accounts Limits how many platform accounts can use this single key on the same device. Common scenario: a Roblox executor where one HWID may have multiple Roblox accounts. Set to 1 for the strictest one-account-per-key flow, or higher to allow household-style sharing. Account limits and HWID Validation ### HWID Validation When enabled, the key is bound to the first device that validates it. When disabled, the key validates anywhere — the HWID is ignored. Disabling is rare and weakens anti-piracy significantly; use only when you specifically need a transferable key (a giveaway prize, a key sold with explicit device-transfer rights). ### Editing and deleting generated keys Every row in the Generated Keys list has edit and delete actions. You can adjust any of the key's settings before it has been validated, or delete the key entirely if you want to cancel it before the user redeems. Edit a generated key Why generated keys have no HWID yet A Generated Key has no device bound to it. It exists in the Generated Keys table, holding its prefix, expiration, premium flag, and other config — but no HWID. The moment a user enters the key on your get-key flow and validation succeeds, the system moves the key from Generated Keys to Active Keys and attaches the user's HWID to it. ## Active Keys The Active Keys tab is your post-validation key inventory. Every key here has been redeemed by a user and is bound to their device. The settings you configured at generation came along with the key — prefix, expiration, premium flag, account limits — and you can still edit, delete, blacklist, or suspend any individual key from this page. Active Keys list ### Available actions - **Edit** — adjust the key's settings post-validation. Useful for extending an expiration for a specific user as a goodwill gesture, or fixing a setting you got wrong at generation time. - **Delete** — remove the key entirely. The user loses access immediately on next validation attempt. - **Blacklist** — bans the HWID associated with this key. The user cannot generate or redeem any new keys for your service until the blacklist is lifted. - **Suspend** — temporarily disables the key without deleting it. The user gets "invalid" on validation, but you can re-enable it later if the suspension was a mistake or the issue is resolved. Active Key edit panel Blacklist vs Suspend vs Delete — pick the right one - **Delete** when the key was a mistake or a test. - **Suspend** when you suspect abuse but want to be able to undo it (chargeback in progress, customer complaint under investigation). - **Blacklist** when you have caught the user attempting bypass exploits and want them locked out of your service permanently. ## Keyless / Whitelisted The Keyless / Whitelisted tab is for HWID-only access — no keys, just a list of approved devices. Anyone whose HWID is on this list validates successfully without ever entering a key. This is the most stripped-down access model and pairs well with private beta groups, internal team tools, or trusted-user rosters. Keyless / Whitelisted management Library support is limited Keyless validation does not work with every client library out of the box. The V3 library supports it, but older or third-party libraries may not implement HWID-only flows. If you are using Keyless mode, double-check that the library or executor your users run actually calls our keyless validation endpoint. If not, you may need to build a custom integration or stick to the standard key flow. ### When to use Keyless - **Private beta groups** where you know every tester and want to add them by HWID. - **Paid customer rosters** where you manage purchases manually and want to bypass the get-key flow for verified customers. - **Internal team tools** where everyone using the software is on your team and frictionless access matters. ### When to use regular keys instead - **Public-facing services** where users earn or buy keys through your get-key flow. Keyless would skip your monetization entirely. - **Large user bases** where manually adding HWIDs is impractical. - **Anti-piracy is critical** — keyless gives up some flexibility because there is no key to track or revoke independently of the HWID itself. ## Mass Compensation Mass Compensation adds extra days to **every eligible key in the service at once**. It is the goodwill tool for when your script breaks, a game update ships, or you have downtime and want to give all of your users free extra time without editing thousands of keys one by one. You will find a **Compensate** button on both the Generated Keys and Active Keys tabs, and a **Compensation** page under Key Management that lists every compensation you have run. ### Running a compensation Click **Compensate**, pick how many days to add (1–365), and choose what it applies to: - **Both** — every active key and every generated key. - **Active Keys** — only keys already redeemed and bound to a device. - **Generated** — only keys created but not yet redeemed. Before you confirm, the dialog shows a live count — how many keys will be extended and how many lifetime keys are being skipped — so you know the exact impact. ### How the days are added The chosen number of days is added to each key's current expiry. A key that expires in 10 days becomes 13 after a +3 compensation. An already-expired key moves forward from its old expiry date, not from today. Lifetime keys are always skipped Keys that never expire (lifetime keys) are never touched by a compensation. Adding days to a key that already lasts forever would be meaningless, so they are left exactly as they are and counted separately in the preview. ### History and undo The **Compensation** page is a running log — think of it like a commit history. Each compensation is one entry showing when it ran, who ran it, how many days it added, how many keys it touched, and its status. Every applied compensation has a **Revert** button. Reverting subtracts the same number of days back from exactly the keys that compensation originally touched (keys deleted since are skipped), then marks the entry as reverted. A compensation can only be reverted once. Reverts stack cleanly Because each compensation only ever adds or removes its own fixed number of days, reverting an older one leaves any newer compensations intact. If you apply +3, then +5, then revert the +3, the affected keys keep the net +5. Who can run it Mass Compensation requires Key Management access — the service owner, or a contributor granted the manage-keys permission. Contributors without it cannot compensate or revert. --- For Developers · Dashboard # URL Shortener The URL Shortener turns any link into a monetized booster link — the same checkpoint-and-ad flow your get-key page uses, but pointed at any destination you choose. Use it to monetize file downloads, external content, partner links, anything you want to gate behind ad completion. Visitors clear checkpoints to reach the destination; you collect the ad revenue. URL Shortener management ## What it's for The classic example: you have a download link for something — a script file, a mod, an executable, a guide — and you want users to go through the same monetization flow they would for a key before reaching it. URL Shortener wraps that download link in a Panda Auth checkpoint flow. Users hit the short URL, complete the checkpoints, and land on the destination. Anything you can link to can be monetized this way: - **File downloads** — script files, mods, guides, executables, ZIPs. - **External content** — your YouTube video, a Discord invite, a partner page, a documentation site. - **Affiliate links** — gate access to a referral or affiliate landing page through your own checkpoint flow. - **Backup distribution links** — content you want to monetize separately from your primary get-key flow. ## How it works You provide a destination URL — anywhere on the internet, no restrictions. Panda Auth generates a short URL of the form**shrt.pandauth.com/shrt/your-alias** that wraps the destination in a checkpoint flow. When users click the short URL, they hit a checkpoint page first; once they complete the required steps, they're redirected to the destination URL. Each shortener you create has its own configuration: - **Destination URL** — where users end up after completing checkpoints. - **Alias** — the short suffix on the URL (auto-generated or custom). - **Checkpoint count** — how many steps users must clear before reaching the destination. ## Monetization on shortener links Shorteners use the same ad providers as your get-key flow. The Revenue Settings you configured in Monetization apply across both your get-key page and your shortener checkpoints — one configuration, two revenue surfaces. Effective use Pair shorteners with your normal get-key flow. A user lands on your YouTube video → completes a shortener to get a Discord invite → joins your server → eventually reaches your get-key page. Each step is monetized, each step is a chance for them to engage with your community. Way more revenue per visitor than a single get-key page alone. ## Managing shorteners The URL Shortener dashboard lists every shortener you've created with searchable filtering. Each row shows: - **Alias** — the short URL suffix. - **Shorten URL** — the full short URL, with a copy button. - **Destination URL** — where users end up. - **Click count** — total clicks on the short URL. - **Success count** — users who completed all checkpoints and reached the destination. - **Fail count** — users who started but didn't complete. From the row actions you can edit, delete, or bulk-delete shorteners. When to use it Use URL Shortener whenever you have valuable content that users ask for outside the standard get-key flow. Anything you'd otherwise give away for free can be wrapped in a shortener to capture additional ad revenue without changing your user experience much — users are already used to the checkpoint pattern from your get-key page. --- For Developers · Dashboard # Client Connect Client Connect is the live control room inside your Panda Auth dashboard. If you've ever wondered exactly who is actively using your services right this second, this is the place to be. While Key Management helps you hand out access, Client Connect lets you see those keys in action — a real-time, easy-to-read list of everyone who is online and connected to your service right now. ## What you can see at a glance When you open the Client Connect dashboard, you get a bird's-eye view of your users. Here's what you'll find: - **Active Users** — a quick count of how many people are online right now versus those who might have a lagging or stale connection. - **Device Identity** — a unique fingerprint for the device the user is playing or working on. - **License Key** — the exact key the user used to log in. - **Service Details** — which specific service or platform they are currently using. - **Time Tracking** — exactly when they logged in and when their access is scheduled to expire. - **Connection Health** — a live look at how stable their connection is, using a system of "heartbeats" (regular check-ins to say "I'm still here!"). ## Take action in real-time Client Connect isn't just for watching — it's for managing. You can interact with any active user instantly using these quick actions: - **Extend** — give a user more time on their current session without waiting for them to renew. - **Deactivate** — end the user's current session immediately without revoking their key permanently. - **Ban** — block the user's HWID from connecting at all, locking them out of your service. Live ops at a glance Spotting a user with a suspicious connection pattern, an unusual session, or someone you specifically want to reach out to is now one click away. Everything that used to require waiting for a report or sifting through logs can happen in real time from this page. ## How it keeps you connected Behind the scenes, Panda Auth works hard to keep your dashboard perfectly synced with your users, without slowing anything down. Here is the simple version of how it works: - **Secure Check-In** — when a user logs in, they establish a secure, private connection with our servers. This is the foundation; every subsequent message rides on top of this trusted channel. - **Heartbeats** — while they are online, their device sends a tiny signal (a "heartbeat") every few seconds to let us know they are still active. If we miss a heartbeat, their status changes to "Stale" so you know their connection might be dropping. - **Live Updates** — your dashboard constantly checks in with our servers so you always see the freshest data without needing to refresh the page. - **Safe Management** — before you extend, deactivate, or ban someone, the system double-checks to make sure you have the right permissions, keeping your services completely secure. ## Supported connections Client Connect works smoothly across different types of setups. Whether your users are on a platform that supports constant, live connections (WebSocket-style) or one that relies on checking in every few minutes (polling-style), they will all show up in your dashboard clearly labeled so you know exactly how they are connected. - **Live (WebSocket)** — persistent connection with sub-second updates. The most responsive view, available on modern client libraries. - **Polling** — periodic check-ins from the client. Updates happen at the polling interval (typically every 30 to 60 seconds), which is still fast enough to feel real-time for most management actions. One dashboard, every connection type You don't need to know which connection type a specific user is on — Client Connect labels each session so you can manage them uniformly. The actions (Extend, Deactivate, Ban) work the same way regardless of the underlying transport. When to use Client Connect Use Client Connect when you want eyes on your live service. It's invaluable for spotting abuse in progress, running ad-hoc support (extending a user's session while you investigate their issue), or just understanding when your service is busiest. Most operators check it once or twice a day; heavy-traffic services keep it open in a background tab. --- For Developers · Dashboard # Account Limits The Account Limits page is your view into every account and device currently using your service's keys. From here you can see exactly who has redeemed what, on which device, and how recently they used it — plus delete specific accounts or devices to revoke their access. It's a focused Roblox-side tool that pairs with the multi-account and multi-HWID toggles in Authentication. Roblox-only feature Account Limits management is currently scoped to Roblox usage. If your service is not Roblox-based, this page won't show data — the underlying account/device tracking is specifically tied to Roblox user IDs and HWIDs. Prerequisite: enable Multi-HWID or Multi-Account The Account Limits page only shows data when you have enabled either Multi-HWID per Key (for device management) or Multi-Account per Key (for account management) in Security → Authentication . With both toggles off, the page will be empty because there are no per-account or per-device limits to enforce. Account Limits — accounts and devices management ## Accounts management The accounts side shows every Roblox account that has redeemed a key on your service. Each row includes: - **Roblox User ID** — the specific Roblox account using the key. - **HWID** — the device fingerprint that account is bound to. - **Key** — the key value the account is paired with. - **Type** — Generated (key created but not yet validated) or Active (validated, in use). - **Last Used** — the most recent timestamp the account validated successfully. You can delete any account from the list. Deleting unlinks that account from the key — it can no longer use the key, even if the device or other accounts on the same device still can. ## Devices management The devices side shows every HWID that has redeemed a key on your service. Each row includes: - **HWID** — the device's unique fingerprint. - **Key** — the key value the device is paired with. - **Type** — Generated or Active. - **Created** — when the device first redeemed the key. - **Last Used** — the most recent validation timestamp. Deleting a device disconnects it from the key. The device will fail validation on its next attempt and the user will need to either redeem a new key on it or have you re-authorize the device. ## When to delete an account or device - **Account/device is suspected of abuse** — a Roblox account or device caught attempting to bypass your protections. - **User asked to free up a slot** — a paying customer wants to redeem the key on a different device and you've already hit their device limit. - **Stale entries** — devices that haven't validated in months and are taking up slots for users who actually use the service. Deletion is immediate Deleting an account or device takes effect immediately. The account/device fails validation on the next attempt with no warning to the user. Communicate with the user first if the deletion is at their request, so they aren't surprised when their script suddenly stops working. This is a Roblox-side tool, not a license management dashboard Account Limits is built specifically for Roblox-based services where keys are reused across multiple Roblox accounts on the same device. For non-Roblox services or for top-level key management (creating, editing, blacklisting whole keys), use the Key Management page instead. --- For Developers · Monetization & Growth # Monetization Monetization Settings is where you configure how your get-key page makes money. It is split into four sub-tabs — Revenue Settings, Custom Revenue, Instant Access, and PayPal Settings. Revenue Settings is what every service needs first; the other three are for advanced flows. The Monetization Settings area is split into four sub-tabs: - **Revenue Settings** — pick your main and backup ad providers, set up Multi-Revenue. - **Custom Revenue** — assign a different provider to each individual checkpoint (advanced). - **Instant Access** — let users skip the checkpoint flow entirely during a time window. Has its own dedicated docs page. - **PayPal Settings** — accept direct PayPal payments for paid-only key flows. ## Revenue Settings This tab is where you tell Panda Auth which ad networks to use, which one is your primary, and what backups to fall back to. The settings here apply to every key your service hands out, unless you override per-checkpoint in the Custom Revenue tab. Monetization Settings · Revenue Settings tab ### Enable GetKey Page Enterprise **What it does:** The master switch for your free get-key flow. When this is on, users can visit your get-key page and earn keys by completing checkpoints. When this is off, the get-key page is disabled entirely — the only way to get a key is through paid options (PayPal, granted manually, or distributed however you choose). **Default:** On. - **Turn it on if:** You want to monetize through ads. This is the standard setup for most services. - **Turn it off if:** You only sell paid keys and do not want users earning free ones. Used by paid-only services where every key is a purchase. ### Revenue Mode **What it does:** Picks your primary monetization provider — the main ad network users will go through to earn keys. Each provider is paid by visits or completions, and Panda Auth handles the integration and callback verification for you. **Available providers:** - Linkvertise (Publisher ID) - Lootlabs - Work.ink - Fly Inc / Rinku.pro - Lockr.so - Short-Jambo - Cuty.io - AdMaven (Short and Secured) - Shrink Earn - Shrtfly - Boostelar - Universal Link - Secured variants of the above (anti-bypass versions for Linkvertise and Lootlabs) Best practice Pick the provider that pays the best for your audience's geographic region. Most North American and European services start with Linkvertise. Pure mobile audiences often do better with Work.ink or Lootlabs. Try one for a week and check your payout reports. Provider-by-provider setup tutorials live under Monetization Ads Provider in the sidebar. ### Publisher ID / API Key **What it does:** The credential the provider gave you in their dashboard. The field name and exact format depend on the provider — Linkvertise calls it Publisher ID, Work.ink calls it an API Key, Lootlabs uses a different token. Whatever the field is called, paste the value the provider gave you in their account settings. **Where to find it:** Log into your provider's dashboard and look in the settings or integrations area. Every provider documents this. See the per-provider tutorials under Monetization Ads Provider for exact click paths. Heads up Make sure the ID actually belongs to your account. If you paste someone else's ID, the money goes to them, not you. ### Enable Multi-Revenue **What it does:** Turns on a secondary revenue provider that runs alongside the primary one. With this on, your users can choose between two ad networks at the checkpoint, or the system can fall back from one to the other if the primary fails. **Why it matters:** Different ad networks pay different amounts in different regions. Different users prefer different providers. Letting both networks earn from your service captures the audience that would otherwise bounce on a single-provider flow. When on, two new fields appear: - **Secondary Revenue Mode** — pick a different provider than your primary. Cannot be the same as the primary. - **Secondary API Key / Publisher ID** — paste the credential for the secondary provider. - **Turn it on if:** You want to maximize payout by offering choice and redundancy. - **Turn it off if:** You only have credentials for one provider, or you want to keep the flow simple. ### Enable Tertiary Revenue **What it does:** Adds a third revenue provider on top of the primary and secondary. Same idea — more options for users, more chances to earn, more redundancy. - **Turn it on if:** You want maximum monetization choice and have credentials for three different networks. - **Turn it off if:** Two providers are enough for your flow. Most services do not need three. ### Disable Checkpoint Fail-Safe **What it does:** Controls what happens when an ad provider fails to load or verify. By default (this toggle off), if monetization fails, the checkpoint does not count — the user has to retry. When this toggle is on, checkpoints are allowed to complete even when monetization verification fails. **Why this exists:** Sometimes ad providers go down, their CDN is slow, or their callback verification fails for reasons outside your control. Without fail-safe disabled, legitimate users get stuck and bounce. With it enabled, users get through even when the ad layer has issues — but you also lose verification of whether the ad was actually completed. **Default:** Off (fail-safe is active and protecting your revenue). - **Turn it on if:** Your provider has been unreliable and you would rather let users through than lose them entirely. Use as a temporary measure, not permanently. - **Turn it off if:** You want to enforce that every checkpoint completion comes from a verified ad view. The more revenue-protective setting and the right default. Recommended default setup For a new service: - Enable GetKey Page: **On** - Revenue Mode: **Linkvertise** (start here, swap later if your payout reports suggest otherwise) - Publisher ID: **Your real Linkvertise Publisher ID** - Enable Multi-Revenue: **On** (with Work.ink or Lootlabs as the secondary) - Enable Tertiary Revenue: **Off** - Disable Checkpoint Fail-Safe: **Off** (keep verification protection on) ## Custom Revenue Custom Revenue is the advanced version of Revenue Settings. Instead of using one set of providers for every checkpoint in your flow, this tab lets you assign a different revenue provider to each individual checkpoint. Use it when you want fine-grained control over which ad network your users hit at which step. Monetization Settings · Custom Revenue tab ### Why this exists Different providers pay differently. Some pay more for the first impression, some pay more once a user is already in the flow. Some convert better on mobile, some on desktop. Some have great geo coverage, others are weak outside the US. By assigning a specific provider per checkpoint, you can build a flow that maximizes payout at every step rather than relying on the same provider top to bottom. Custom Revenue **overrides** what you set in Revenue Settings. When this is on, the per-checkpoint configuration takes priority. ### Enable Custom Revenue Per Checkpoint **What it does:** Turns the entire Custom Revenue system on or off. When off, all checkpoints use whatever you configured in Revenue Settings (the simple flow). When on, the per-checkpoint configuration shown below takes over. **Default:** Off. Most services start with the simpler Revenue Settings flow and only switch to Custom Revenue once they have data showing a specific checkpoint underperforming. ### Per-checkpoint configuration When Custom Revenue is on, each checkpoint in your service appears as its own block with three controls: - **Revenue Provider:** Dropdown to pick which ad network this checkpoint uses. Same options as the main Revenue Mode. - **Publisher ID / API Key:** The credential field for the provider you picked. Label changes depending on the provider. - **Lock Button:** A red Locked button on the right side of each checkpoint card. Click it to lock or unlock the checkpoint. ### About Lock Checkpoint **What locking does:** When a checkpoint is locked, users cannot switch to a different revenue provider for that specific checkpoint. In the normal Multi-Revenue flow, users sometimes see a button to swap providers (an "interswitch") if they prefer a different network. Locking disables that for the locked checkpoint — they must complete the assigned monetization link, no alternative offered. **Why this matters:** Lock checkpoints when you want to force a specific provider to count. Examples: a sponsored arrangement with a particular network, A/B testing one provider's payout in isolation, or simply maximizing revenue by removing the option for users to bounce to a cheaper provider. Locked checkpoints cannot be deleted Unlock first, then delete. This is a safety guard so you do not accidentally wipe a checkpoint you intentionally pinned. ### Add Checkpoint The dashed "+ Add Checkpoint" button at the bottom adds another checkpoint block to the list. Use it when you have raised your checkpoint count and need a new entry to configure here. The checkpoint count in Custom Revenue should match the checkpoint count your service is actually issuing. If your service requires 4 checkpoints but you have only configured 3 in Custom Revenue, the 4th checkpoint falls back to whatever is in Revenue Settings. How to use Custom Revenue well - **First checkpoint = highest-converting provider.** This is the make-or-break step. If users bounce here, you get nothing. Use the provider with the smoothest first impression. - **Middle checkpoints = highest-paying provider.** Users who have made it past the first step are committed. Maximize payout per impression here. - **Last checkpoint = your sponsored or locked provider.** If you have a deal with a specific network, lock the final checkpoint to them so the user has to complete it before getting their key. - **Lock conservatively.** A locked checkpoint with a flaky provider will block all your users when that provider has issues. Lock only when you are confident in the provider's reliability. Recommended default For a new service: leave Custom Revenue off . Use Revenue Settings instead. Custom Revenue is a tool for services that already have payout data and want to optimize from there. ## PayPal Settings The PayPal Settings tab lets users buy premium keys directly from your get-key page using PayPal. This is the path for monetization that does not go through ad networks at all — users pay you cash, you give them a premium key, no checkpoints involved. It runs alongside your normal flow rather than replacing it. Monetization Settings · PayPal Settings tab Prerequisites Before configuring this tab, two things must already exist on PayPal's side: - A **PayPal Business account**. A standard personal PayPal account will not work — PayPal only allows payment integrations through Business accounts. - An **app created in the PayPal Developer Dashboard**. This is where the Client ID and Secret Key come from. You cannot make them up — they are issued to you by PayPal when you create the app. ### PayPal Client ID Required **What it is:** The public identifier for your PayPal application. PayPal generates this when you create an app in their Developer Dashboard. It is safe to expose in frontend code — PayPal designed it that way. Think of it as your app's username. **Where to find it:** Go to [developer.paypal.com](https://developer.paypal.com) → log in → Dashboard → My Apps & Credentials → click on your app → "Client ID" appears under App credentials. Copy the entire string and paste it here. If the field shows the word 'Encrypted' That means a Client ID has already been saved. Panda Auth encrypts stored credentials so they do not appear in plain text after save. You can replace it with a new value at any time by typing over it. ### PayPal Secret Key Required **What it is:** The private companion to the Client ID. Where the Client ID identifies your app, the Secret Key proves your app is genuinely yours when calling PayPal's API. Anyone with both your Client ID and Secret Key can act as your app — that is why it is called secret. **Where to find it:** Same place as the Client ID — developer.paypal.com → Dashboard → My Apps & Credentials → your app → "Secret" or "Secret Key" under App credentials. There is usually a "Show" button to reveal it. Copy and paste it here. Security rules - **Never share this key publicly.** Not on Discord, not on GitHub, not in screenshots, not in support tickets. If it leaks, regenerate it in the PayPal Developer Dashboard immediately. - **Never put it in your client-side code.** Your get-key page, your browser frontend, your script source — none of that should ever contain the Secret Key. Panda Auth stores it on our backend where it stays out of the public surface. - **Rotate it if you suspect a leak.** PayPal lets you regenerate the Secret Key at any time. The old key stops working the moment you generate a new one. ### Step-by-step PayPal setup First-time path: - 1. Go to paypal.com and either log in or sign up for a PayPal **Business** account. Personal accounts will not work. - 2. Once your Business account is active, go to developer.paypal.com and log in with the same account. - 3. In the Developer Dashboard, click "Apps & Credentials." - 4. Switch the toggle at the top from "Sandbox" to "Live" when you are ready to accept real payments. (Sandbox is for testing only — sandbox credentials will not process real money.) - 5. Click "Create App." Name the app something memorable like "Panda Auth Production." - 6. Once created, the app's detail page shows your Client ID and a Secret Key. - 7. Copy the Client ID and paste into Panda Auth's PayPal Client ID field. - 8. Click "Show" next to Secret, copy the Secret Key, and paste into Panda Auth's PayPal Secret Key field. - 9. Click Save Changes in Panda Auth. - 10. Test by going to your own get-key page and confirming the PayPal purchase option appears. ### Testing before going live PayPal provides Sandbox credentials (separate from Live) that let you test the full payment flow with fake money. Get your Sandbox Client ID and Secret Key from developer.paypal.com (Sandbox toggle on), paste those into Panda Auth for testing, run a test purchase using PayPal's sandbox buyer accounts, then swap to your Live credentials when ready. Sandbox vs Live Sandbox transactions do not move real money. Live transactions do. Always confirm which mode you are in before going public. Once configured correctly A PayPal purchase button appears on your get-key page. Users see it as an option alongside the normal Get Key checkpoint flow. They click, complete the PayPal payment in a popup, and receive a premium key the moment PayPal confirms the transaction. The money goes directly from the buyer's PayPal account to your PayPal Business account — Panda Auth does not handle the funds at any point. --- For Developers · Monetization & Growth # Instant Access Mode Instant Access is a special mode where users skip every checkpoint and receive a key the moment they hit your get-key page. No ads, no captcha, no monetization — just a key. Designed for time-windowed promotions like weekend giveaways, community milestones, holiday events, and launch days. Monetization Settings · Instant Access tab ## Monthly Budget Banner At the top of this tab you will see a status banner showing your monthly Instant Access budget. It looks like "This month: Unlimited" or "This month: 7 of 14 days remaining." **What it means:** Instant Access is metered by **days of activation per month**. The number of days you can run Instant Access depends on your account tier — higher tiers get more days, with the top tier being unlimited. The banner also shows when your monthly budget resets (typically the first of the next month). **How days are counted:** Each day the activation window covers counts as one day toward your budget. A weekend (2 days) costs 2 days. A 24-hour window costs 1 day. A 4-hour window also costs 1 day — partial days round up. The days are deducted the moment you save the window, not when users start claiming. **Refunds:** If you shorten or disable a window before its end, the unused days from "right now" forward are refunded back to your budget. Days already in the past are gone. ## Enable Instant Access Mode **What it does:** The master switch. When this is on, users hitting your get-key page during the activation window get a key instantly without going through any checkpoints. When this is off, the normal checkpoint flow runs. Critical detail This toggle does nothing on its own. You must also set a valid activation window below. If start/end (or hours) are not set, Instant Access stays off even when this toggle is on. This is a safety guard so you cannot accidentally hand out unlimited free keys with no end date. - **Turn it on if:** You have set up a valid window and want users to get keys instantly during that period. - **Turn it off if:** You want the normal checkpoint flow back, or you want to pause an active window without deleting it. ## Activation Window This is where you define **when** Instant Access is live. Two modes are available, and you pick one: ### By Date **What it does:** Set a specific start date/time and end date/time. Use this for fixed promotions — "Black Friday from Friday 9am to Monday 9am", "Weekend giveaway from Saturday to Sunday". - **Start:** The exact moment Instant Access becomes active. Uses your local browser time. - **End:** The exact moment Instant Access deactivates. Uses your local browser time. ### By Hours **What it does:** Set a rolling window in hours from the moment you save. Use this for spur-of-the-moment promotions — "Active for the next 6 hours starting now." This mode is simpler when you do not need to schedule in advance. The hours count down from when you save the settings. Important behavior Keys issued during the window expire when the window ends , not after the normal key duration. A user who claims a key on day 1 of a 3-day window has that key for 2 days, not 24 or 48 hours. When the window closes, all keys issued during it expire simultaneously. ## Issue as Premium Key **What it does:** When this is on, keys issued during Instant Access count as Premium keys. Premium keys unlock the higher-tier behaviors you have configured elsewhere — multi-HWID per key, multi-account per key, longer HWID reset cooldowns, and whatever other premium perks your service has set. **Default:** On. Most operators want Instant Access keys to feel like a real reward, not just "free but limited." - **Turn it on if:** You want users who get an Instant Access key to receive the full premium treatment. - **Turn it off if:** You want Instant Access keys to behave as standard Free-tier keys, with the same limits as a normal earned key. ## Custom Message (Optional) **What it does:** A short message shown to users on the get-key page above the Instant Access button. Up to 200 characters. **Why use it:** Context. A user who lands on a page and gets a key for free with no checkpoints might think something is broken. A message like "Free access weekend — enjoy!" or "Community milestone reward, limited time" tells them what is happening and why. Best practice Keep it short, on-brand, and time-bound. "Weekend giveaway, ends Sunday 11pm" reads better than just "Free keys." Leave blank if you do not want any extra messaging. ## How Instant Access Mode works Five things to remember - **The window is required.** The toggle does nothing without start/end (or hours) configured. This is intentional — no accidental unlimited-free-keys-forever. - **Keys expire at the window end.** Regardless of when the user claims them. Day-1 claimers and day-3 claimers all lose their keys at the same moment when the window closes. - **One active key per HWID.** Users cannot stockpile or duplicate keys by refreshing the page. Each device gets one Instant Access key per window. - **Days are charged at save time.** The moment you click Save Changes with a valid window, the days are deducted from your monthly budget. Shortening the window later refunds unused future days from "right now" onward. - **Security still runs.** HWID blacklists, captchas, fraud scoring, and abuse protections are all still active during Instant Access. Admins can also force-disable any service's Instant Access at any time if abuse is detected. ## When to use Instant Access Common use cases that work well: - Weekend giveaways or community milestones - Major launch days (your software hits version 2.0, a holiday tied to your community) - Recovery after extended downtime (a "we are back" gesture) - Tier upgrade rewards (your premium tier just expanded — give the whole community a taste) - Holiday promotions (Black Friday, Christmas, New Year) Avoid using it for: - **Permanent free-key flows.** That defeats the point of checkpoints and burns your monthly budget for nothing. Use Keyless Mode instead if you want truly free, ongoing access. - **Tiny windows aimed at specific users.** If you want to whitelist one user, use Security → Trust List → Whitelist instead. Instant Access is broadcast, not targeted. Recommended defaults For most services: leave Instant Access off until you have a specific event or promotion in mind. The feature is event-driven, not always-on. **For a planned promotion:** - Enable Instant Access Mode: **On** - Activation Window: **By Date**, with the exact start and end of your promotion - Issue as Premium Key: **On** (rewards the community properly) - Custom Message: a short on-brand line telling users what is happening After the window ends, the system reverts to normal automatically. You do not need to manually turn anything off — the toggle stays on, but the window has passed, so no instant keys get issued until you set a new window. --- For Developers · Monetization & Growth # Key Streaks Key Streaks reward users for coming back. Every day a user completes your get-key flow, their streak goes up by one, and you decide what reaching a given day is worth: extra time on the key, Panda Token Credits, or a webhook you can hang anything off. Designed for retention: turning a one-off visitor into a daily habit. ## What a streak is A streak is a count of **consecutive days** on which a user successfully finished your checkpoint flow and received a key. Finish today and tomorrow, and your streak is 2. Miss enough days and it goes back to 1 and starts over. **Who a streak belongs to:** the device, identified by its HWID. That is deliberate. The get-key page has no login: the visitor is an anonymous device, and the HWID is what the key binds to anyway. If the same browser also happens to be signed in to a PandaAuth account, that account is recorded alongside the streak, but it is never the identity. A user who signs in halfway through a streak keeps the streak they already built. **Per service.** Streaks do not pool across your services. A user with a 12 day streak on one service starts at zero on another. ## What counts as a qualifying day One qualification per day, per user A day counts once . The first completion of the day advances the streak; everything after it that day is recorded as a normal key issue and changes nothing. A user cannot get to day 30 in an afternoon by refreshing. Counted: - Finishing the last checkpoint of your get-key flow - Returning successfully from an ad provider on the final step - The ad-callback variant of the same flow Not counted: - Opening or refreshing the page, or reaching an ad - An intermediate checkpoint, before the flow is finished - A retried request that hands back a key the user already has, rather than issuing a new one - Instant Access, which has no checkpoints and would be farmable for the length of the window - Keys you create yourself: the bulk key API, a service import, or an HWID reset, which re-issues a key the user already earned ## Grace Period **What it does:** decides how forgiving a missed day is. A user who misses their bus on Tuesday should probably not lose a 40 day streak, but you choose how much slack that is worth. The rule, exactly as the system applies it: **a user whose last qualifying day was day D is due on day D+1. They keep the streak if they qualify at any point from the start of D+1 until the grace period elapses after the END of D+1.** The deadline is measured against the real completion time, not rounded to a day. "12 hours" means twelve hours. - **Strict:** no slack at all. The next day or the streak resets. - **12 hours:** last qualified on the 5th, due on the 6th, and the streak survives until noon on the 7th. - **24 hours (default):** exactly one skipped day is forgiven. Last qualified on the 5th, so anywhere on the 6th or the 7th keeps it, and the 8th resets it. - **48 hours:** two skipped days are forgiven. Last qualified on the 5th, so anywhere up to the end of the 8th keeps it. A grace day is not a free day Grace only stops the streak from breaking. It does not award the skipped day. A user who qualifies on the 5th, skips the 6th and qualifies on the 7th under 24 hour grace goes from 4 to 5, not to 6. ## Day Boundary **What it does:** shifts the moment a streak day rolls over. By default the day rolls at 00:00 UTC. The offset is in minutes, so if your community is mostly in one region and you would rather the day break at their local midnight, set the offset to their UTC offset. **Why it is UTC and not server time:** PandaAuth runs on more than one node. If the boundary followed each machine's local clock, a user served from Europe and a user served from Singapore would disagree about which day it is, and the same completion could count twice or not at all. One fixed boundary per service, applied everywhere, is what makes the streak consistent. Changing the offset mid-streak Moving the boundary shifts which day a completion lands in, so a user who qualified just either side of the old boundary can find that the new one puts two of their completions in the same day. Nothing is lost, but the change is best made when you set the feature up rather than while streaks are running. ## Reward Mode - **Milestone:** pays only on the days you configured. Day 3, day 7, day 30, whatever you set. Nothing on the days in between. - **Daily:** pays the same small reward on every qualifying day, and ignores milestones. - **Hybrid:** pays the daily reward AND any milestone that lands on the same day. A user reaching day 7 gets both. A reward set to day `0` is the daily reward. Any positive number is a milestone on that day of the streak. ## Reward types ### Key Duration **What it does:** adds minutes to the key that completion issues. Reach day 7 with a +60 reward and that key lasts an hour longer than your normal key duration. It applies to one key, not to your service The bonus is added to the single key the user just earned. It does not change your service's key duration setting, and it does not carry over to the next key. Tomorrow's key is a normal key again, plus whatever tomorrow's reward is worth. ### Panda Token Credits **What it does:** credits Panda Tokens to the user's PandaAuth account. **They are permanent.** Credits land in the persistent balance, the same bucket purchases and redeem codes use. The monthly allowance reset on the first of the month never touches them. A user who earns 5 credits in March still has them in December. Requires a signed-in user An anonymous device has no account and therefore nowhere to put tokens. When an anonymous user reaches a token milestone the reward is recorded in history and the milestone is marked as used for that cycle, but nothing is credited, and the get-key page says so rather than claiming a credit that never arrived. If token rewards matter to you, tell your community to sign in to PandaAuth in the same browser before they claim. ### Webhook **What it does:** fires a webhook when the milestone is reached, carrying the streak day, the user's longest streak, a summary of the other rewards paid, and your custom message. Use it for a Discord announcement, a role grant through your own bot, or anything else you want to drive off a milestone. **Where it goes:** the dedicated streak webhook URL if you set one, otherwise your service's existing Discord webhook, so you do not have to configure a second one. **A failed delivery costs the user nothing.** The streak is committed to the database before delivery is even attempted, and the result is stamped onto the reward history as sent or failed. A webhook that is down cannot roll back a day the user legitimately earned. ## Cycles, and rewards that repeat Every unbroken run is a **cycle**. When a streak breaks, the next qualifying day starts a new one. Reward history is tracked per cycle, which is what lets a milestone pay more than once: a user who reaches day 7, drops off, comes back and reaches day 7 again is in a new cycle and is paid again. **Within one cycle each milestone pays exactly once.** That holds even if you edit the reward. Changing "day 7 = +1 hour" into "day 7 = +2 hours" applies from each user's next cycle. A user who already collected day 7 in their current cycle does not collect the difference. ## Show to users **What it does:** controls whether the get-key page shows the user their streak and the reward they are working towards. Turn it off and the feature keeps running silently: days still count, rewards still pay, the user just does not see a counter. Most operators want this on. The counter is most of the reason the feature works. ## Turning it off Disabling preserves everything Switching Key Streaks off stops processing . It does not delete anything: every streak, every qualifying day and every reward already paid stays exactly where it is. Switch it back on and the feature resumes from the state it was frozen in. Users who were away longer than your grace period naturally land in a new cycle, which is the same thing that would have happened had the feature never been off. ## How Key Streaks work Five things to remember - **One day, one qualification.** The first completed flow of the day counts. Everything after it that day is just a key. - **Grace saves the streak, it does not fill the gap.** A forgiven day still does not increment the counter. - **Duration bonuses are one-shot.** They extend the key that was just issued and never touch your service's configured duration. - **Token credits are permanent, and need an account.** The monthly reset never claws them back, and an anonymous device cannot receive them. - **A streak never costs a user their key.** If the streak bookkeeping fails for any reason, the key is still issued. The streak is a bonus on top, never a gate. Recommended defaults For a service that just wants users coming back: - Grace Period: **24 hours**. Forgiving enough that one busy day does not undo a month, strict enough that the streak still means something. - Reward Mode: **Milestone**, with rewards on day 3, day 7 and day 30. Early wins keep new users going, the long one gives regulars something to protect. - Day Boundary: **0** unless your community really is concentrated in one region. - Show to users: **On**. Start with Key Duration rewards. They cost you nothing, they are instantly understood, and they work for anonymous users. Add Panda Token Credits once enough of your community is signed in for them to land. --- For Developers · Monetization & Growth # Service Ads Service Ads lets you place your own ads on your service pages — banners, popups, custom HTML or JS — so you earn revenue every time a user visits your get-key page. Different from checkpoint monetization (which happens during the key-earning flow), Service Ads is passive: ads load with the page, you get impressions, you collect the payout from whichever ad network you wired in. Service Ads — manage banners, popups, and script injections ## How it works Most ad networks (Google AdSense, AdMaven banners, propeller-style providers, custom HTML/JS snippets) give you an embed code — an HTML or JavaScript snippet you copy from their dashboard. Service Ads takes that snippet and injects it into your get-key page automatically. The injection is flexible — banner ads, popup overlays, script-based ad units, any format the ad provider supports. As long as you can paste the embed code, Panda Auth will render it on your page. Service Ads form — paste your ad HTML ## Ad slots available per tier The number of ads you can run at once depends on your account tier: - **Free plan** — 1 ad slot. - **Premium / Special plan** — 2 ad slots. - **Enterprise plan** — 3 ad slots. Why the limits exist Too many ads on a single page slow it down, hurt your conversion rate, and make users bounce before completing the key flow. The tier limits keep you from accidentally over-monetizing in a way that costs more than it earns. ## Ad placements - **Banner** — static HTML at a fixed position: Top of page, Bottom of page, or Sidebar. Best for traditional display ad networks that serve banner units. - **Popup** — modal that appears with configurable triggers (on page load, on scroll, on exit-intent) and frequency (once per session, once per day, every visit). Higher impression value but more disruptive — use sparingly. - **Script** — raw HTML or JavaScript injection. For custom ad units, interstitials, or anything that does not fit the banner or popup formats. Most flexible, but you are responsible for making sure the script behaves and does not break your page. ## Setting up an ad The flow is the same regardless of which ad network you use: - **1. Get the ad code from your network.** Most networks give you a snippet under "Embed", "Integration", or "Get code" in their dashboard. - **2. Pick the placement** (banner, popup, or script) and position in Panda Auth. - **3. Paste the snippet** into the HTML field. - **4. Save**. The ad goes live on your get-key page immediately. Visit your own page to verify it renders correctly. ## Service Ads vs Monetization checkpoints These are two different revenue streams, and they stack: - **Monetization checkpoints** earn you payouts when users complete ad-wall steps to get a key. Active engagement, higher payout per completion. - **Service Ads** earn you payouts based on page impressions and clicks. Passive, smaller per-impression value but adds up across all visitors regardless of whether they complete the key flow. Use both They do not compete with each other. Service Ads earn from every page load; Monetization checkpoints earn from completions. Together they capture revenue from both passive traffic and actively converting users. Test the page after every ad change Custom HTML and JavaScript can introduce errors that break your get-key page silently — broken renders, infinite redirect loops, ad scripts that conflict with our captcha layer. Always load your own get-key page in a fresh incognito window after publishing an ad change to verify everything still works end to end. --- For Developers · Monetization & Growth # Contributors Contributors lets you give other people personal access to your service with a customized permission set. A contributor can manage keys, manage settings, manage VPS, or view statistics — whatever combination you grant. This is how you bring in trusted team members without sharing your full account credentials. Contributors management ## What contributors can do Each contributor gets any combination of independent permissions when you add them: - **Manage Keys** — create, edit, delete keys; change their status; reset HWIDs; run bulk operations. Use for support staff who handle user issues. - **Manage Settings** — edit service configuration, security, monetization, appearance. Use for technical partners who help you tune the service. - **Manage VPS** — control VPS-related infrastructure tied to your service. Use for DevOps-style collaborators. - **View Statistics** — read-only access to analytics and performance data. Use for marketing or community-management people who need numbers without write access. Principle of least access Only grant the permissions a contributor actually needs. A support staff member doesn't need Manage Settings; a marketing collaborator doesn't need Manage Keys. Tighter scopes mean smaller blast radius if their account ever gets compromised. ## Adding a contributor Click the add button on the Contributors page, enter the collaborator's Panda Auth username (they need their own Panda Auth account already), and tick the permissions you want to grant. Save, and they show up under your service immediately — they will see your service in their own dashboard with the permissions you assigned. ## Removing or changing access You can edit a contributor's permissions at any time without removing and re-adding them. Toggle individual permissions on or off, save, and the change takes effect on their next request. Removing a contributor fully revokes their access — they lose the service from their dashboard, their saved sessions for it are invalidated, and they can no longer take any action on your service. Use this when a collaboration ends or you suspect their account has been compromised. Contributors are not owners Contributors cannot transfer ownership of your service, delete the service, or add other contributors themselves. Those operations stay locked to the owning account. This is intentional — even a contributor with all permissions cannot lock you out of your own service. --- For Developers · Monetization & Growth # Discord Integration Connect Discord for account linking, server-based script distribution, and verification. ## Three ways it connects - **Account linking (OAuth)** — users connect their Discord account from **Settings → Connect Discord**. Their username, avatar, and ID link to their Panda Auth account. - **Guild binding** — bind a Discord server to your account via a bot command. The bot gives a temporary confirmation token; you confirm it on the dashboard and pick the service. - **Manual verification** — for users without OAuth. You generate a verification token (valid 3 days), and a moderator approves or rejects it in a private channel. ## Guild requirement 1,300 members minimum Guilds with 1,300 or more members can access VSS scripts via Discord bot commands. ## Verification states A manual verification moves through these states: Pending Request, Pending Review, Approved, Rejected, and Expired. --- For Developers · Monetization & Growth # Webhooks & Analytics Two integrations live on this page: Discord webhooks for piping key events into your community server, and Google Analytics for tracking your get-key page's traffic. Both are optional but worth setting up — webhooks give you real-time visibility into key activity, and Analytics shows you where your traffic comes from and how it converts. ## Discord webhooks Pipe key events into a Discord channel using a webhook URL. When one of the events below fires, Panda Auth sends a message to your webhook with a customizable template. ### Events - **Key Validated** — a successful validation. Payload includes masked key, HWID, expiration. - **Key Generated** — a new key created. Payload includes key value, HWID (if any), expiration. - **Blacklist Added** — an HWID added to your Vanguard blacklist. - **Blacklist Removed** — an HWID removed from the blacklist. - **HWID Reset** — a key's HWID binding reset. ### Template variables Build a custom message format with these placeholders. Panda Auth substitutes them when sending each event. Copy ```lua {{key}} Full key value (e.g. PANDA-ABCD-EF12-3456) {{key_masked}} Partially hidden (e.g. PANDA-****-****-3456) {{hwid}} User's Hardware ID {{expires}} Key expiration date/time {{timestamp}} When the event occurred {{event_icon}} Emoji for the event type {{event_title}} Human-readable event name {{type_emoji}} Key type (normal vs premium) {{separator}} Visual divider line {{service_name}} Your service's display name ``` Example template: Copy ```lua {{event_icon}} {{event_title}} | Key: {{key_masked}} | HWID: {{hwid}} | Expires: {{expires}} ``` Use masked keys in public channels If your webhook posts to a channel where end users can see, use {{key_masked}} instead of {{key}} . The masked variant hides most of the key string, so a user reading the channel cannot copy someone else's freshly-generated key from your support log. ## Google Analytics integration If you already use Google Analytics, Panda Auth integrates with it in one click. Paste your Google Analytics URL and Measurement ID from your GA account into the analytics fields, save, and Panda Auth instantly injects the GA4 tracking script into your get-key page. Google Analytics integration Two fields: - **Google Analytics URL** — the URL of your GA property from your Google Analytics account. - **Google Analytics ID** — your GA4 Measurement ID in the `G-xxxx` format. Find it under **Admin → Data Streams** in your GA account. Once both fields are saved, you can track your get-key page's performance live in Google Analytics — visits, geos, traffic sources, time on page, the standard GA metric set. This is much richer than the built-in analytics dashboard and works well as a complement. Two integrations, one page — pick what matters to you Most services benefit from at least the Discord webhook (real-time visibility into who is redeeming keys). Google Analytics is more useful if you are actively running marketing campaigns and want to measure attribution. Both are free; both are optional. --- For Developers · Monetization & Growth # Referral Program Invite other developers and earn Panda Tokens when they get started. ## How you earn 4 Panda Tokens per active referral You earn 4 Panda Tokens for each active referral, and the person you invited gets 1 Panda Token the moment they sign up with your code. Share your link in the form `/register?ref=YOUR_CODE`. The code works for both email signup and "Continue with Google". ## When it pays out Your invitee's **1 Panda Token** lands immediately on registration. Your own **4 Panda Tokens** are held until their account is **48 hours old** — an anti-throwaway measure — and are then paid automatically by a job that runs every 30 minutes. So expect your reward roughly two days after they join, not the same day. Referring yourself does not pay. Accounts sharing an email or a linked Discord account with you are rejected at payout time. ## What's tracked - **Total Signups** — everyone who registered via your link. - **Active Conversions** — signups that cleared the 48-hour gate (this is what earns tokens). - **Tokens Earned** — total tokens (Active Conversions × 4). --- For Developers · Monetization & Growth # Panda AI An AI chat assistant built into the dashboard. It helps you write and debug Lua, review your config, and answer platform questions. ## Models & cost - **PandaAI-Regular** — DeepSeek V3, supports tool calling. **0.1 Panda Tokens** per message. - **PandaAI-Pro** — advanced reasoning. **0.25 Panda Tokens** per message. ## File uploads Limits Up to 5 files per message , 10MB per file . Supported types include `.lua`, `.luau`, `.js`, `.ts`, `.py`, `.json`, `.html`, `.css`, `.md`, `.txt`, and more. ## Tool calling Panda AI can run up to **5 rounds of tool calls per request** (for example reading your service config or stats) before it answers. --- For Developers · Monetization Ads Provider # Linkvertise Linkvertise is the most commonly used ad provider for Panda Auth services. The setup is quick — copy your Publisher ID from the Linkvertise dashboard, paste it into Panda Auth, save. If you want the harder-to-bypass version, check the Secured Linkvertise page instead. ## Before you start You need a Linkvertise publisher account. If you do not have one, sign up at [publisher.linkvertise.com](https://publisher.linkvertise.com/) before continuing. ## Step 1 — Open your Linkvertise dashboard Go to [publisher.linkvertise.com/dashboard](https://publisher.linkvertise.com/dashboard#dashboard) and log into your account. The Linkvertise publisher dashboard ## Step 2 — Open Full Script API and copy your Publisher ID In the sidebar, navigate to **Full Script API**. The page will show a numeric Publisher ID — that is the value Panda Auth needs. Copy the highlighted number. Full Script API — copy the highlighted Publisher ID ## Step 3 — Paste it into Panda Auth Back in your Panda Auth dashboard, go to **Monetization Settings → Revenue Settings**. Select **Linkvertise (Publisher ID)** from the Revenue Mode dropdown if it is not already, then paste your Publisher ID into the field labeled Publisher ID. Paste your Publisher ID into Panda Auth ## Step 4 — Save and test Click **Save Changes** at the bottom right of the Revenue Settings tab. Then visit your own get-key page in a browser and walk through the checkpoint flow. Each ad-wall step should now route through Linkvertise. Done Linkvertise is now your active monetization provider. You will start seeing payouts in your Linkvertise dashboard within a few hours of the first real users completing checkpoints. Check your Linkvertise analytics for completion rates per geo and per device. Want stronger anti-bypass? Linkvertise also offers a Secured variant that validates completions on the backend instead of in the browser. It is more setup work but much harder for bypass tools to fake. See the Secured Linkvertise page in this section for the full walkthrough. Heads up Make sure the Publisher ID you paste actually belongs to your Linkvertise account. If you paste someone else's ID, the payouts go to them, not you. Double-check by logging into Linkvertise yourself and confirming the ID matches what you copied. --- For Developers · Monetization Ads Provider # Secured Linkvertise Secured Linkvertise is the anti-bypass version of Linkvertise. Setup is more involved than the normal variant — you create one Linkvertise link per checkpoint, paste the destination Panda Auth generates, then configure the Anti-Bypass token. The payoff is much harder-to-fake completions. Per-checkpoint setup Secured Linkvertise requires you to set up one link per checkpoint . If your service has 4 checkpoints, you will be doing the steps below four times. Save after every checkpoint before moving to the next. ## Before you start You need a Linkvertise publisher account. Sign up or log in at [publisher.linkvertise.com](https://publisher.linkvertise.com/) before continuing. Each checkpoint gets its own configuration ## Step 1 — Open Linkvertise and start a new link Log into your Linkvertise dashboard and click **Post and earn** (top menu) to start creating a new link. You will be redirected to the link-creation page. Linkvertise publisher dashboard Post and earn button ## Step 2 — Create a new link On the link-creation page, fill in the basics and create the link. The destination URL is what Panda Auth tells you next — leave it as a placeholder for now if needed, you will paste the real one in Step 4. Linkvertise link creation page Link configuration ## Step 3 — Copy the checkpoint destination from Panda Auth Switch to your Panda Auth dashboard, open **Monetization Settings → Custom Revenue**, find the checkpoint you are configuring, and copy the destination link Panda Auth shows for it. The checkpoint destination link from Panda Auth ## Step 4 — Paste the destination into Linkvertise and save Back on the Linkvertise link page, paste the Panda Auth destination into the Target URL field, then save. Once saved, copy the resulting Linkvertise URL — that is what goes back into Panda Auth for this checkpoint. Paste destination into Linkvertise Linkvertise link saved ## Step 5 — Configure the Anti-Bypass token In the Linkvertise dashboard sidebar, navigate to **Anti-Bypass**. Check the **Use anti bypassing** checkbox, then copy the anti-bypassing token Linkvertise shows you. Linkvertise Anti-Bypass page Back in Panda Auth, paste that token into the Anti-Bypass Token field for the checkpoint. Click Save Changes. Paste anti-bypass token into Panda Auth Repeat for every checkpoint Save after every checkpoint before moving on to the next. Each checkpoint needs its own Linkvertise link with its own paired anti-bypass token. Skipping the save step is the most common mistake — without it, the checkpoint will fail verification at runtime. Done Once every checkpoint is configured and saved, Secured Linkvertise is live for your service. Completions are now validated server-to-server, making bypass tools significantly harder to use against your flow. Heads up Make sure each Linkvertise link belongs to your own account. Cross-check the Publisher ID under your profile if you are unsure. Pasting someone else's link sends the payout to them, not you. --- For Developers · Monetization Ads Provider # Lootlabs Lootlabs is one of the highest-paying ad providers for Panda Auth services. Setup takes two pieces — any Lootlabs link (even an existing one), and your Lootlabs API Token. The Secured Lootlabs variant uses the same steps and is documented separately. ## Before you start You need a Lootlabs publisher account. Sign up or log in at [lootlabs.gg](https://lootlabs.gg/) before continuing. ## Step 1 — Create or copy a Lootlabs link Log into your Lootlabs dashboard. You need any Lootlabs link — if you already have one, you can reuse it. The destination of the link does not have to be Panda Auth; even an unrelated existing link works because Panda Auth overrides the destination at checkpoint time. Lootlabs publisher dashboard ## Step 2 — Paste the Lootlabs link into Panda Auth Switch to Panda Auth, go to **Monetization Settings → Revenue Settings**, select Lootlabs from the Revenue Mode dropdown, and paste the Lootlabs link into the Link field. Paste Lootlabs link into Panda Auth ## Step 3 — Get your Lootlabs API Token Back in Lootlabs, click your profile menu in the top right to open account settings. Lootlabs profile menu Navigate to **API Key**. API Key page Copy your API token. Copy your API token ## Step 4 — Paste the API Token into Panda Auth and save Paste the Lootlabs API token into the API Token field in Panda Auth, then click **Save Changes**. Save changes Done Lootlabs is now your active provider. Test the flow by visiting your own get-key page and walking through a checkpoint — it should route through Lootlabs. Want stronger anti-bypass? Lootlabs also has a Secured variant that validates completions on the backend. Same setup steps, different mode in the dropdown. See the Secured Lootlabs page for the anti-bypass version. --- For Developers · Monetization Ads Provider # Secured Lootlabs Secured Lootlabs is the anti-bypass version of Lootlabs. The setup steps are identical to the normal Lootlabs flow — what changes is the Revenue Mode you select. The Secured mode validates completions server-to-server, making bypass tools much harder to use. Same steps, different mode The screenshots and setup steps on this page are intentionally the same as the regular Lootlabs page. The only practical difference is that you pick Secured Lootlabs in the Revenue Mode dropdown instead of Lootlabs . Everything else — getting the link, copying the API Token — works the same way. ## Before you start You need a Lootlabs publisher account. Sign up or log in at [lootlabs.gg](https://lootlabs.gg/) before continuing. ## Step 1 — Create or copy a Lootlabs link Log into your Lootlabs dashboard. Any Lootlabs link works — Panda Auth overrides the destination at checkpoint time, so even an unrelated existing link is fine. Lootlabs publisher dashboard ## Step 2 — Paste the Lootlabs link into Panda Auth In Panda Auth, go to **Monetization Settings → Revenue Settings**. Pick **Secured Lootlabs** from the Revenue Mode dropdown (not regular Lootlabs), then paste your Lootlabs link into the Link field. Paste Lootlabs link into Panda Auth ## Step 3 — Get your Lootlabs API Token Back in Lootlabs, click your profile menu in the top right. Lootlabs profile menu Navigate to API Key. API Key page Copy your API token. Copy your API token ## Step 4 — Paste the API Token into Panda Auth and save Paste the token into the API Token field, then click **Save Changes**. Test the flow by visiting your own get-key page. Save changes Done Secured Lootlabs is now your active provider. Completions are validated server-to-server, so bypass tools that fake browser-side completion no longer work against your service. --- For Developers · Monetization Ads Provider # Work.ink Work.ink is one of the simpler providers to set up — you only need an API Key. The path through the Work.ink dashboard takes a few clicks (Integration → Link API → API Keys → Show → Generate), but each step is straightforward. ## Before you start You need a Work.ink publisher account. Sign up or log in at [dashboard.work.ink](https://dashboard.work.ink/) before continuing. Work.ink — one API Key is all you need ## Step 1 — Open the Work.ink dashboard Log into [dashboard.work.ink](https://dashboard.work.ink/) to reach the publisher dashboard. Work.ink publisher dashboard ## Step 2 — Navigate to Integration In the sidebar, click **Integration**. Integration menu ## Step 3 — Open Link API Click **Link API**. Link API ## Step 4 — Open API Keys, show, and generate On the Link API page, navigate to **API Keys**. API Keys page Click **Show API Keys**. Show API Keys Then click **Generate API Key** and copy the key it produces. ## Step 5 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Work.ink** from the Revenue Mode dropdown, paste your API Key, and click **Save Changes**. Paste Work.ink API Key into Panda Auth Done Work.ink is now your active provider. Test by walking through your own get-key flow — checkpoints should route through Work.ink. --- For Developers · Monetization Ads Provider # Lockr.so Lockr.so is a straightforward API-key provider. The dashboard takes you through Settings → API → copy key, then paste into Panda Auth and save. ## Before you start If you do not have a Lockr.so account, create one at [lockr.net/r/panda](https://lockr.net/r/panda). Once registered (or if you already have an account), log into the dashboard. ## Step 1 — Open the Lockr.so dashboard Lockr.so publisher dashboard ## Step 2 — Navigate to Settings Settings menu Settings navigation ## Step 3 — Click API In Settings, click **API**. API section ## Step 4 — Copy your API key Your API key appears on this page. Copy it. Lockr.so API key ## Step 5 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Lockr.so** from the Revenue Mode dropdown, paste your API Key, and click **Save Changes**. Paste Lockr.so API key into Panda Auth Done Lockr.so is now your active provider. --- For Developers · Monetization Ads Provider # Short-Jambo Short-Jambo is a quick API-key setup. The dashboard is mostly in Arabic — use your browser's built-in translate to read the menus if needed. The path is Tools → Developer API → copy your API key. Language note Most of the Short-Jambo dashboard is in Arabic. Right-click anywhere in the page and choose Translate to English (Chrome, Edge) or use Google Translate. The screenshots below show the English-translated version. ## Before you start If you do not have a Short-Jambo account yet, sign up at [short-jambo.com](https://short-jambo.com/). If you already have an account, log in and head to the dashboard. ## Step 1 — Open the Short-Jambo dashboard Short-Jambo dashboard ## Step 2 — Open Tools → Developer API In the sidebar, navigate to **Tools → Developer API**. Copy your API key from this page. Developer API page ## Step 3 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Short-Jambo** from the Revenue Mode dropdown, paste your API key, and click **Save Changes**. Paste Short-Jambo API key into Panda Auth Done Short-Jambo is now your active provider. --- For Developers · Monetization Ads Provider # Cuty.io Cuty.io uses a simple API-token setup. The path is Tools → Developer API → copy your API Token, then paste into Panda Auth and save. ## Before you start Register or log in at [cuty.io](https://cuty.io/) before continuing. ## Step 1 — Log into Cuty.io Cuty.io login ## Step 2 — Open Tools → Developer API Once you are in the dashboard, navigate to **Tools → Developer API**. Developer API page ## Step 3 — Copy your API Token Copy your API Token ## Step 4 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Cuty.io** from the Revenue Mode dropdown, paste your API Token, and click **Save Changes**. Paste Cuty.io API Token into Panda Auth Done Cuty.io is now your active provider. --- For Developers · Monetization Ads Provider # Ad-Maven Ad-Maven is a globally available provider with strong fill rates in regions where other networks underperform. Setup takes one credential — your API Key from the Account Settings page. Shared steps with Secured Ad-Maven Ad-Maven and Secured Ad-Maven use the same dashboard and the same API Key. The only difference is the Revenue Mode you select in Panda Auth. If you came here looking for the Secured variant, the steps below apply — just choose Secured Ad-Maven in the dropdown at the end. ## Before you start Log in or sign up at [publishers.ad-maven.com](https://publishers.ad-maven.com/user-login) before continuing. ## Step 1 — Open the Ad-Maven publisher dashboard Ad-Maven publisher dashboard ## Step 2 — Open Account Settings Click your profile icon in the top right and select **Account Settings**. Account Settings ## Step 3 — Navigate to API Key and copy In Account Settings, go to **API Key** and copy your API key. Ad-Maven API Key page ## Step 4 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, pick **Ad-Maven** (or **Secured Ad-Maven** if you want the anti-bypass version) from the Revenue Mode dropdown, paste your API Key, and click **Save Changes**. Paste Ad-Maven API Key into Panda Auth Done Ad-Maven is now your active provider. --- For Developers · Monetization Ads Provider # Secured Ad-Maven Secured Ad-Maven is the anti-bypass variant of Ad-Maven. The setup is identical to the normal Ad-Maven flow — same dashboard, same API key — with the difference being the Revenue Mode you pick in Panda Auth. Secured validates completions on the backend, making bypass tools much harder to use. Same steps, different mode Ad-Maven and Secured Ad-Maven share the same dashboard and API key. The only difference is the dropdown selection in Panda Auth — pick Secured Ad-Maven instead of Ad-Maven . Steps are otherwise identical. ## Before you start Log in or sign up at [publishers.ad-maven.com](https://publishers.ad-maven.com/user-login) before continuing. ## Step 1 — Open the Ad-Maven publisher dashboard Ad-Maven publisher dashboard ## Step 2 — Open Account Settings Account Settings ## Step 3 — Copy the API Key Ad-Maven API Key page ## Step 4 — Paste into Panda Auth and save (pick Secured Ad-Maven) In Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Secured Ad-Maven** from the Revenue Mode dropdown, paste your API Key, and click **Save Changes**. Paste Ad-Maven API Key into Panda Auth Done Secured Ad-Maven is now active. Completions are validated server-to-server, so bypass tools that fake browser-side completion no longer work against your service. --- For Developers · Monetization Ads Provider # Shrinkearn Shrinkearn is a quick API-token setup. Tools → Developers API → copy token → paste in Panda Auth → save. That is the whole flow. ## Before you start Log in or sign up at [shrinkearn.com](https://shrinkearn.com/). ## Step 1 — Open Shrinkearn Shrinkearn ## Step 2 — Open Tools → Developers API Log in and navigate to **Tools → Developers API**. Developers API page ## Step 3 — Copy your API Token Copy your API Token ## Step 4 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **Shrinkearn** from the Revenue Mode dropdown, paste your token, and click **Save Changes**. Paste Shrinkearn API Token into Panda Auth Done Shrinkearn is now your active provider. --- For Developers · Monetization Ads Provider # ShrtFly ShrtFly uses the same Tools → Developers API → copy → paste workflow as the other shortener-style providers. One credential, one save, done. ## Before you start Sign up or log in at [shrtfly.com](https://shrtfly.com/). ## Step 1 — Log into ShrtFly ShrtFly login ## Step 2 — Open Tools → Developers API Once you are in the dashboard, navigate via the sidebar to **Tools → Developers API**. Developers API page ## Step 3 — Copy your API Key Copy your API Key ## Step 4 — Paste into Panda Auth and save Back in Panda Auth, go to **Monetization Settings → Revenue Settings**, select **ShrtFly** from the Revenue Mode dropdown, paste your API Key, and click **Save Changes**. Paste ShrtFly API Key into Panda Auth Done ShrtFly is now your active provider. --- For Developers · Monetization Ads Provider # Universal Link Universal Link lets you plug in any URL shortener as a checkpoint provider, not just the ones we have built-in support for. The setup is similar to Secured Linkvertise — one link per checkpoint, with the destination being whatever Panda Auth generates for that checkpoint. What is Universal Link for? Universal Link exists for two situations: (1) you use a shortener provider that we have not built dedicated support for yet, and (2) you want full control over the link presentation. The trade-off is more manual setup — you configure each checkpoint individually with the destination link Panda Auth gives you. ## How it works Universal Link works just like the per-checkpoint flow used by Secured Linkvertise. For each checkpoint in your service: 1. Panda Auth generates a destination URL for that checkpoint. 2. You create a link on your shortener of choice (any service — even ones outside our supported list) with that destination URL as the target. 3. You paste the resulting shortener URL back into Panda Auth as the Universal Link for that checkpoint. 4. Repeat for every checkpoint your service has. Universal Link configuration ## When to use it Pick a built-in provider (Linkvertise, Lootlabs, Work.ink, etc.) if one supports your shortener — the integration is simpler and completion verification is more reliable. Reach for Universal Link when you specifically need a provider we have not added native support for. Per-checkpoint setup required Save after every checkpoint before moving to the next. Forgetting this step is the most common reason a Universal Link setup partially works — checkpoints without a saved configuration fall back to your Revenue Settings primary provider. Done Once every checkpoint has a saved Universal Link, your service is live with the third-party provider. --- For Developers · Libraries # Choose Your Library Panda Auth talks plain HTTP, so any language works. For common platforms we ship ready-made client libraries, so pick the one that fits. ## The libraries Panda-RBLX SDK Recommended The Roblox SDK. HTTP-only validator with session heartbeats, so it works where WebSocket is broken or missing. Use it for: Every new Roblox integration; executors with no/broken WebSocket. Panda-SDK V5 The non-Roblox SDK. Available in C# and C++ only: one managed DLL with no native dependencies, plus the older native C++ package. Use it for: Desktop software in C# or C++. ## Not on this list? Any language works The underlying API is just HTTP. If your platform isn't covered by a library, call the endpoints directly. See the API Reference for the validate routes and authentication. --- For Developers · Non-Roblox SDK # Panda-SDK V5 Licensing for desktop software, in C# and C++ only. One managed DLL that speaks the PUSL-V4 protocol over plain HTTP: no native library, no libsodium, no WebSocket, no NuGet packages. v1.0.0, 2026-09-08. ## Download Panda-SDK V5 is a single .NET 8 assembly, `Panda.Pusl.Client.dll`. It has zero package references, so dropping it next to your executable is the whole install. Version: v 1.0.0 Target: net8.0 Updated: 2026-09-08 SHA-256: a2a46fb120dcda97 … Download Panda-SDK-V5.zip Reference it from your project: YourApp.csproj Copy ```lua libPanda.Pusl.Client.dll ``` ## Sample usage Create the client, hand the user the GetKey URL, validate what they type. On success the heartbeat starts on its own in the background. Program.cs Copy ```lua using Panda.Pusl.Client; var options = new PuslOptions { ServiceId = "your_service_identifier", }; using var client = new PuslClient(options); Console.WriteLine("Get a key: " + client.GetKeyUrl()); Console.Write("Enter key: "); var key = Console.ReadLine() ?? ""; var result = await client.ValidateAsync(key); if (!result.Success) { Console.WriteLine($"Auth failed [{result.ReasonCode}]: {result.Error}"); return result.Reason == PuslReason.InvalidKey ? 2 : 1; } Console.WriteLine($"Authenticated. Premium: {result.IsPremium}"); Console.WriteLine($"Expires: {client.GetExpiryFormatted()}"); Console.ReadLine(); await client.DisconnectAsync(); return 0; ``` Do not kick on a bare false ValidateAsync fails for a bad key, and it also fails for a rate limit or a dropped request. Read result.Reason before you act on it. Only INVALID_KEY means the key is bad. Wrap the call in the retry policy you should ship with: Copy ```lua // Only INVALID_KEY means the key is bad. Everything else is transient, so // back off and retry instead of telling a paying user their key is wrong. static async Task Authenticate(PuslClient client, string key) { var result = await client.ValidateAsync(key); for (var attempt = 1; attempt <= 3; attempt++) { if (result.Success || result.Reason == PuslReason.InvalidKey) break; // A 404 is the slug being rejected, and it stays rejected. if (result.HttpStatus == 404) break; var wait = TimeSpan.FromSeconds(result.RetryAfterSeconds ?? attempt * 5); await Task.Delay(wait); result = await client.ValidateAsync(key); } return result; } ``` ## Watch the session A session can end after a successful validate: the key expires, the heartbeat stops coming back, or the server closes it. Subscribe to `SessionEnded` and read `IsConnected` where the work happens. Copy ```lua // Fires when a live session drops on its own: "network", "protocol", // "slug_rejected", "session_closed", or a reason the server sent. client.SessionEnded += (_, reason) => _revoked = reason; // IsConnected is false the moment the heartbeat stops coming back. if (!client.IsConnected || _revoked is not null) { // Stop doing the paid work. Do not call Environment.Exit here. } ``` `DisconnectAsync` sends the goodbye and stops the heartbeat. Disposing the client without it leaves the session to time out server side. ## Key expiry Copy ```lua client.ExpiresAt // "2026-08-09T22:15:00.000Z", null = lifetime client.ExpiresAtUnix // 1786429200, null = lifetime client.GetTimeLeft() // 604800 seconds, null = lifetime, floored at 0 client.IsExpired() // false for a lifetime key client.GetExpiryFormatted()// "7d 0h 0m" | "Lifetime" | "Expired" // null means LIFETIME, never "expired". if (client.GetTimeLeft() is { } left && left < 86_400) Warn($"Key expires in {client.GetExpiryFormatted()}"); ``` null means lifetime, not expired GetTimeLeft and ExpiresAtUnix return null for a key with no expiry at all, which is why IsExpired() is false in that case. Time is measured against the server clock, adopted during the handshake, so a wrong system clock still counts down correctly. They also return `null` on a client that has not validated yet, so `IsExpired()` is false on a brand new client too. It is a countdown, not a gate. Pair it with `IsConnected` anywhere you use it to decide something. ## Reason codes | Code | Meaning | What to do | | --- | --- | --- | | OK | Authenticated. | Continue. | | INVALID_KEY | The key is wrong, used up, or expired. | Reject the user. This is the only fatal one. | | RATE_LIMITED | Too many attempts from this address. | Wait RetryAfterSeconds, then retry. | | NETWORK | The request failed or timed out. | Back off and retry. | | PROTOCOL | The server replied with something unexpected. | Back off and retry. | | IDENTITY | The server did not prove it was ours. | Do not authenticate. Check ServerPublicKeyHex. | | CLOCK_SKEW | The device clock was too far off. | Retried once automatically, then retry yourself. | | NO_SERVICE | ServiceId was not set. | Fix your configuration. | | NO_KEY | An empty key was passed in. | Ask the user again. | On a 429 the server says how long to wait and the client passes it through as `result.RetryAfterSeconds`. Add your own jitter on top. ## Options Copy ```lua var options = new PuslOptions { ServiceId = "your_service_identifier", // Must match the server. Rotate them together. VerifyKey = "pusl_v4_vk_...", SlugSecret = "pusl_v4_ss_...", // Public half of the server signing key. A wrong value fails every // handshake with IDENTITY. ServerPublicKeyHex = "4dd84e1d...", // Set this only if heartbeats come back 404. SessionSlugServiceId = null, // Leave null unless your product already has a device identity. Hwid = null, Executor = "MyApp/1.4.0", Debug = false, }; ``` ServiceId string required Your service identifier from the dashboard. VerifyKey / SlugSecret string optional The pair baked into your build. They must match the server, and they rotate together. Mixing one from each keyset gets past the handshake and then fails on the signature, which reads like a bad key and is not one. ServerPublicKeyHex string optional The pinned server identity key. If it is not the public half of the key your region signs with, every handshake fails with `IDENTITY`. SessionSlugServiceId string? optional Only needed if heartbeats come back 404. Put the service row id here. The `SessionEnded` reason for that case is `slug_rejected`. Hwid string? optional Overrides the derived machine fingerprint. Whatever you pass has to be the same value the GetKey page saw, or the key resolves to a different device. Debug / Logger bool / Action optional Prints the protocol trace. Turn it off in shipping builds: it names every step of the handshake. ## Additional trick protections The library protects the wire: rotating endpoints, an Ed25519 pinned server identity, a signed request body, and AES plus HMAC replies keyed per sequence number. None of that protects your executable. A .NET assembly decompiles cleanly, so the attack is never on the protocol, it is on the line where you branch. These are the tricks that matter. ### 1. Never gate on a single bool This is the shape every cracker looks for: Copy ```lua // One branch, one place. In a decompiler this is a single brtrue to flip. if (await client.ValidatePremiumAsync(key)) { RunApp(); } ``` One instruction flipped and the app runs. Carry the values the session produced into the code that needs them instead: Copy ```lua var result = await Authenticate(client, key); if (!result.Success) return Exit(result); // Carry values the app actually needs, not a flag. Patch the check out and // the app is left with no session id and nothing to send to your backend. var session = new Session( Id: result.SessionId!, Premium: result.IsPremium, ExpiresUnix: result.ExpiresAtUnix, Hwid: client.Hwid); // Use them for real. Premium features read session.Premium, the status bar // reads client.GetExpiryFormatted(), your API calls carry session.Id. using var http = new HttpClient(); http.DefaultRequestHeaders.Add("X-Panda-Session", session.Id); var payload = await http.GetStringAsync("https://your-api.example/premium/data"); ``` Now removing the check does not unlock anything. It leaves the app with no session id, no expiry and nothing to send to your backend. ### 2. Put the value on your server The only protection that cannot be patched out Anything shipped in the binary can be unlocked in the binary. Keep the work that is worth paying for behind your own API, and send result.SessionId with each request so your backend can refuse it. A crack of the client then buys an app with no data in it. ### 3. Check often, where the work happens One check at startup is one place to patch. Read live state at the point the feature runs, so there is no cached flag to flip: Copy ```lua // Bad: one gate at startup. static bool _licensed; // Better: the value is read where the work happens, every time. sealed class Licence { private readonly PuslClient _client; private readonly bool _premium; public Licence(PuslClient client, PuslResult result) => (_client, _premium) = (client, result.IsPremium); // No cached bool to flip, and it reads live session state. public bool CanExport => _premium && _client.IsConnected && !_client.IsExpired(); } ``` Do not call `Environment.Exit` the instant a check fails. An immediate exit points straight at the check that triggered it. Degrade quietly instead. ### 4. Treat the baked secrets as obscurity `VerifyKey` and `SlugSecret` ship inside the assembly, exactly as they do in the compiled native SDK. They raise the effort of talking to the protocol, they are not authentication. Real authenticity comes from the signed body, the Ed25519 identity on the server hello, and the signed session cookie. Rotation locks out shipped builds Rotating the pair server side without a PUSL_*_PREV grace window breaks every build already in the hands of users until they update. ### 5. Keep the identity pin on `VerifyServerIdentity` defaults to true and should stay that way. With it off, anything that can redirect your host, a hosts file entry or a local proxy, answers the handshake and your app believes it. The pin also checks `CanonicalHost` and rejects a signature more than 60 seconds old, so a captured hello cannot be replayed later. The pin only grades a signed hello A server hello that carries no signature , hostname or ts at all is accepted, flag on or off, because a dev server with no signing seed has to be able to answer. The pin is a check on what a real node sends, not a guarantee that something answered as one. Treat the handshake as the start of trust and let your own backend be the thing that decides. ### 6. Understand the HWID before you override it The default fingerprint is a SHA-256 over the machine name, platform, processor count, the Linux machine-id when present, and the sorted physical MAC addresses. It moves when the machine changes: - Renaming the machine changes it. - Adding or removing a network adapter changes it, and a VPN adapter counts. Set `PuslOptions.Hwid` only if your product already has a device identity of its own. Never hardcode one: every copy then shares a device, and one key covers all of them. ### 7. Harden the build last Copy ```lua # Ship a single file, trimmed, with no debug symbols next to it. dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true -p:SelfContained=true -p:DebugType=none # Then obfuscate the output. Do this on top of server-side gating, never # instead of it. ``` Publish single file, strip the symbols, then obfuscate. Shipping a `.pdb` next to the assembly hands a reader your original names and line numbers for free. All of this raises effort, none of it replaces the server holding the value. ### What not to do - Do not kick on a bare false. A rate limit is not a bad key. - Do not treat a null time left as expired. Null means lifetime. - Do not turn off `VerifyServerIdentity` in a shipping build. - Do not leave `Debug` on. It traces the whole handshake. - Do not hardcode a HWID, and do not send one the GetKey page never saw. ## Coming from the native DLL Older builds call the native `PandaLib_PUSL.dll` through P/Invoke. `PandaSdk` in this library is a static facade with the same shape, so existing call sites compile against the managed assembly with no rewrite: - `PandaSdk.Validate(service, key)` and `Validate_Premium` - `PandaSdk.Get_Key(service)`, `IsValid()`, `Shutdown()` - `PandaSdk.PandaGetLastError()`, which returns `REASON: message` It is a migration path, not the target. It blocks, it holds process-wide state, and its boolean return is the exact shape trick protection 1 tells you to avoid. New code should use `PuslClient` directly. The C++ header for the native DLL is unchanged, and the old package is still at `/downloads/PandaSDK_V5.zip`: panda_v5.h Copy ```lua // panda_v5.h #pragma once #ifdef PANDA_V5_EXPORTS #define PANDA_API extern "C" __declspec(dllexport) #else #define PANDA_API extern "C" __declspec(dllimport) #endif // Connect to server, validate key, start heartbeat. PANDA_API bool Validate(const char* service, const char* key); // Returns the GetKey URL with auto-HWID appended. PANDA_API const char* Get_Key(const char* service); // Check if the session is still alive (heartbeat ok, not expired). // Fails if the internal thread detects debugging or heartbeat drops. PANDA_API bool IsValid(); // Graceful disconnect. PANDA_API void Shutdown(); // Get the last error message string. PANDA_API const char* PandaGetLastError(); ``` --- For Developers · Roblox SDK # Panda-RBLX SDK The Roblox SDK, built on the PUSL-V4 protocol: HTTP-only key validation with no WebSocket, so it runs on mobile executors including Delta Android. ## Using the Kryptic Vault? You do not load the Panda-RBLX SDK yourself. It is built into the Vault loader as `PandaAuthV4`. Your uploaded script just calls it: Copy ```lua if PandaAuthV4.Validate(key) then -- authenticated end if PandaAuthV4.Validate_Premium(key) then -- authenticated + premium end -- Recommended when you kick on failure — tells you WHY it failed. local ok, reason, isPremium = PandaAuthV4.ValidateEx(key) -- reason: "OK" | "INVALID_KEY" | "RATE_LIMITED" | "NETWORK" -- | "NO_SERVICE" | "NO_KEY" | "NO_HTTP" | "IDENTITY" | "PROTOCOL" ``` The expiry accessors exist on `PandaAuthV4` too, in PascalCase: Copy ```lua PandaAuthV4.Validate(key) -- must run first PandaAuthV4.GetExpiry() --> "2026-08-09T22:15:00.000Z" PandaAuthV4.GetExpiryUnix() --> 1786429200 PandaAuthV4.GetTimeLeft() --> 604800 (nil = lifetime) PandaAuthV4.IsExpired() --> false PandaAuthV4.GetExpiryFormatted() --> "7d 0h 0m" | "Lifetime" | "Expired" ``` ## When to use it The Panda-RBLX SDK authenticates a key entirely over HTTP: a signed handshake, an AES-256-CBC encrypted and HMAC-signed response, and a rolling-key heartbeat that keeps the session live. There is no WebSocket, so it runs on executors with broken or missing WS support. HTTP only — no WebSocket Every exchange is a plain HTTP request. Endpoints rotate every 5 minutes, the server identity is Ed25519-pinned, and each message carries a rolling AES key + HMAC + sequence number for relay and replay protection. ## 1. Fetch the library Copy ```lua local ok, src = pcall(function() return game:HttpGet("https://secure.pandauth.com/pv4/lib") end) if not ok or not src then return warn("[PUSL-V4] Failed to fetch library.") end local PUSL = loadstring(src)() if not PUSL or type(PUSL.configure) ~= "function" then return warn("[PUSL-V4] Library failed to initialize.") end ``` ## 2. Configure Copy ```lua PUSL.configure({ serviceId = "YOUR_SERVICE_ID", debug = false, kickOnDetect = false, }) ``` ## 3. Validate Copy ```lua local key = "USER_KEY_HERE" -- supply from your own key UI / saved config if not key or key == "" then return warn("[PUSL-V4] Get a key: " .. PUSL.getKeyUrl()) end local result = PUSL.validate(key) if not result.success then return warn("[PUSL-V4] Auth failed: " .. (result.error or "unknown")) end print("[PUSL-V4] Authenticated. Premium:", result.isPremium) ``` API: `configure`, `validate`, `validateEx`, `validatePremium`, `getKeyUrl`, `copyGetKeyUrl`, `isConnected`, `disconnect`, `hwid`, `getVersion`, `getExpiry`, `getExpiryUnix`, `getTimeLeft`, `isExpired`, `getExpiryFormatted`. On success `validate` returns `{ success, isPremium, expiresAt, expiresAtUnix, timeLeft, getKeyUrl, dashboardUrl, sessionId }` and starts the HTTP heartbeat in the background. On failure it also returns a machine-readable `reason`: `INVALID_KEY`, `RATE_LIMITED`, `NETWORK`, `NO_SERVICE`, `NO_KEY`, `NO_HTTP`, `IDENTITY` or `PROTOCOL`. ## 4. Key expiration Copy ```lua -- After a successful validate(), the expiry of the key is available. -- All of these read the last validate() — call validate() first. PUSL.getExpiry() --> "2026-08-09T22:15:00.000Z" (raw ISO, UTC) PUSL.getExpiryUnix() --> 1786429200 (epoch seconds) PUSL.getTimeLeft() --> 604800 (seconds, floored at 0) PUSL.isExpired() --> false PUSL.getExpiryFormatted() --> "7d 0h 0m" -- nil means LIFETIME (the server sent no expiry), not "expired": local left = PUSL.getTimeLeft() if left == nil then print("Key: lifetime") elseif left < 86400 then warn("Key expires in " .. PUSL.getExpiryFormatted()) end ``` nil means lifetime, not expired getTimeLeft and getExpiryUnix return nil both before the first validate and for keys with no expiry at all. Treat nil as "unlimited" — isExpired returns false in that case for exactly that reason. Time remaining is measured against the **server** clock: the offset between server time and device time is captured during `validate`, so an executor with a wrong system clock still reports the correct countdown. ## 5. Retry instead of kicking Only INVALID_KEY means the key is bad Every other reason is transient. Treat a bare false as fatal and you will kick real users over a momentary rate limit or a dropped mobile request. Copy ```lua -- Never kick on a bare false. A rate limit or a dropped request is not a -- bad key, and kicking on it punishes legitimate users (multi-instance, -- shared IP, flaky mobile connection). local function authenticate(key) for attempt = 1, 4 do local ok, reason, isPremium = PUSL.validateEx(key) if ok then return true, isPremium end if reason == "INVALID_KEY" then return false, false, reason end task.wait(attempt * 5) -- transient: back off, then retry end return false, false, "RETRIES_EXHAUSTED" end local ok, isPremium, reason = authenticate(key) if not ok and reason == "INVALID_KEY" then game.Players.LocalPlayer:Kick("Your key is invalid or expired.") elseif not ok then warn("[PUSL-V4] Auth unavailable (" .. tostring(reason) .. ")") end ``` ## Executor support HTTP is resolved from `request` / `http_request` / `http.request`. WebSocket is not required. Synapse X (`syn.*`) and Fluxus are not referenced — both executors are defunct. --- For Developers · Libraries # V3 External Library The V3 library without VSS. Loaded directly via loadstring from a Panda-hosted URL — no tokens consumed, no tier limits, no obfuscation work on your end. Same Pelinda API surface as VSS-served V3, but the caller must pass Service explicitly since there's no auto-injection. When to use this vs VSS-served V3 - **Use External** when you're out of Panda Tokens, your tier doesn't include enough VSS quota, or you want to host the same loader on every script without re-uploading. - **Use VSS-served V3** when you want per-script customization, a unique loader per upload, or your tier covers the token cost comfortably. ## The loadstring URL The external V3 library lives at a stable public URL. Hit it with `game:HttpGet` + `loadstring`: Copy ```lua loadstring(game:HttpGet("https://api.pandauth.com/lib/external/v3.lua"))() ``` The URL is cached for an hour at our edge so loads are fast. When we update the library (admin re-saves it in the dashboard), the same URL transparently serves the new build — your end users never need to update anything. ## Minimal example The shortest possible working script. Replace `"your-service-id"` with your service's identifier from the Hub Details tab. Copy ```lua -- Load the external V3 library local Pelinda = loadstring(game:HttpGet("https://api.pandauth.com/lib/external/v3.lua"))() -- Validate local result = Pelinda.Init({ Service = "your-service-id", -- REQUIRED — no auto-inject like VSS Key = "PANDA-XXXX-XXXX", SilentMode = false, }) if result == "validated!!" then print("Authenticated. Premium:", __PELINDA_IS_PREMIUM__) -- your script logic here elseif result == "error!!" then warn("Connection error") else -- "invalid!!" local link = Pelinda.GetKeyLink({ Service = "your-service-id" }) setclipboard(link) end ``` Service is REQUIRED Unlike VSS-served V3 (which auto-injects Client_ServiceID ), the External build has no service context. You MUST pass Service in every Pelinda.Init and Pelinda.GetKeyLink call. Omitting it returns "error!!" with a console message telling you to add it. ## Pelinda API reference The Pelinda API is identical to the VSS-served V3 build — same parameter names, same return values, same globals set on success. The only difference is that `Service` is required. ### Pelinda.Init({ ... }) - `Service` **(string, required)** — your service identifier. - `Key` **(string, required unless keyless)** — the user's license key. - `SilentMode` **(boolean, default false)** — suppress validation prints. - `SecurityLevel` **(number, default 1)** — leave at 1 unless you have a specific reason. **Returns one of:** - `"validated!!"` — success. Globals listed below are populated. - `"invalid!!"` — the key is wrong / expired / HWID-mismatched. - `"error!!"` — network or config error (missing service, no internet, etc.). ### Pelinda.GetKeyLink({ Service = ... }) Returns the URL the user visits to get a key. Same auto-HWID handling as VSS — the user's HWID is appended to the URL for you. Returns `nil` if `Service` is missing. ### Globals populated on validation - `__PELINDA_IS_PREMIUM__` — boolean. - `__PELINDA_IS_KEYLESS__` — boolean (true for keyless mode validations). - `__PELINDA_KEY_EXPIRES_AT__` — ISO string or nil for non-expiring keys. - `__PELINDA_KEY_HWID__` — the HWID the key got bound to. ## Save-and-resume pattern Most scripts want the user to enter their key once, then validate silently on every subsequent run. The standard pattern uses `isfile` / `readfile` / `writefile` guarded by `pcall`: Copy ```lua -- Pattern: try saved key first, fall back to UI local function trySaved() if not isfile or not isfile("panda_key.txt") then return false end local key = readfile("panda_key.txt") local result = Pelinda.Init({ Service = "your-service-id", Key = key, SilentMode = true, }) return result == "validated!!" end if not trySaved() then -- show your key entry UI here end ``` Low-UNC compatibility Always guard executor-specific functions — isfile , readfile , writefile , setclipboard — with pcall or a typeof(fn) == "function" check. Low-UNC mobile executors may not implement them, and the script should degrade gracefully instead of crashing. ## Template Gallery We ship **45 visually distinct GUI templates** you can use as a starting point — a mix of dark and light themes, all compatible with every executor including low-UNC mobile ones. Each template has an **Advanced Settings** form so you can customize `SilentMode`, `SaveKey`, `HubName`, kick behavior, and other knobs before downloading. Lucide icons are wired in via sprite-sheet, so the buttons and discs show real icons in-game — not emojis. Layout vocabulary covers centered modals, top/bottom toasts, side drawers, bottom sheets, full-screen splashes, floating bubbles, a 4-segment OTP-style pin, an auto-validate spinner, and a Material Design 3 extended FAB. Pick by feel — the auth flow is identical across all 45. Open the Template Gallery ## Common pitfalls - **Forgetting the Service param.** Single most common error. The library will print a helpful message but the silent-mode path will just silently fail. - **Using setclipboard / writefile unguarded.** Crashes on low-UNC executors. Wrap with `pcall` or a function-typeof check. - **Hard-coding test keys in shipped scripts.** Anyone reading your script gets a free trial. Always require the user to enter their own. - **Skipping retries.** Network blips happen. The ship templates retry 3× by default — keep it. --- For Developers · Kryptic Vault # Kryptic Vault Overview Kryptic Vault is the next-generation Virtual Storage system for Roblox Lua scripts. Upload your Lua source, configure obfuscation, and Kryptic serves it through a single loadstring URL that runs inside a hardened, encrypted loader. It replaces the legacy VSS system and is the recommended way to ship Lua scripts to your users. Kryptic Vault dashboard ## What Kryptic Vault does Instead of sharing a raw `.lua` file that anyone with the link can read, copy, or reuse — you upload your script to Kryptic Vault. The vault stores it server-side, obfuscates it through the obfuscator you pick, and exposes it as a single loadstring URL. Your users execute the loadstring; the obfuscated, hardened script runs inside a loader that resists tampering, dumping, and most off-the-shelf bypass tools. Compared to the legacy VSS, Kryptic adds: - **Stronger obfuscation** — Luraph integration plus community-built obfuscators (Lua-Crack, Dead-Secure, WeAreDevs / Prometheus). - **Loader-side protections** — Heartbeat checks, AI optimization, Silent Mode for fail-safe behaviour, and other anti-tamper features. - **Auto-backup to Google Drive** — every time you change your script. - **Init Script (2nd Script)** — split your loader from your actual UI, so the second script runs only after the first triggers it. - **Telemetry** — track every execution with user, game, executor, and HWID data. ## How to open the vault The Kryptic Vault page lives at [pandauth.com/dashboard/vault](https://pandauth.com/dashboard/vault). Open it from your sidebar (Vault icon) or navigate directly. The vault dashboard shows every script you have uploaded with quick actions to edit, replace, delete, and view telemetry. ## When to use Kryptic vs legacy VSS - **Use Kryptic for new uploads.** It is the recommended path for everything going forward — better obfuscation, better loader, better telemetry. - **Use Legacy VSS only when you need backwards compatibility** with executors or library versions that don't yet support the Kryptic loader. The **Compatible Mode** page in this section covers the migration path. Roblox-Lua only Kryptic Vault is a Roblox Lua feature. The obfuscators, loaders, and telemetry are all tuned to the Roblox execution environment. If you ship software in a non-Roblox context (Discord bot, Windows app, web app), you don't need the vault — your code lives in your own runtime. ## Sub-pages in this section - **Upload & Obfuscation** — walk through uploading a script and configuring the obfuscator. - **Panda Tokens** — how tokens work for vault-served scripts. - **Loader & Execution** — what the runtime loader does, how it protects your script. - **Compatible Mode (Legacy VSS)** — migrating from old VSS uploads to Kryptic. - **Telemetry** — monitor execution of your uploaded scripts. --- For Developers · Kryptic Vault # Upload & Obfuscation Upload your Lua script to Kryptic Vault, configure the validation library and obfuscation settings, and the vault produces a single loadstring you can ship to users. The upload form covers everything — script name, service binding, library version, obfuscation preset, and the extra Kryptic options that harden the loader. ## Open the Upload form From the Kryptic Vault dashboard, click **Upload** in the top-right. The upload form opens and looks like this: Kryptic Vault upload form ## Script Name The display name for your script. Pick anything you want — this shows up in the vault dashboard and in your service's script list. Pure organizational naming; users never see it. ## Service The service this script is tied to. Pick from the dropdown of your services (for example, "Panda Developer Kit"). The script is linked to that service for key validation, telemetry, and permissions — make sure you pick the right one. ## Trust List **What it does:** Gates who is allowed to run this specific script, by device (HWID). It does not keep its own list — it reads the HWID Whitelist and Blacklist of the service you picked above, the same table you manage under **Service → Security → Trust List**. One blacklist entry therefore covers your get-key page and every Vault script at once. Two modes: - **Blacklist Only** (default) — everyone runs the script except devices you have blacklisted. - **Whitelist Only** — only devices on the whitelist run the script. Everyone else is turned away. The blacklist still wins, so a device on both lists is blocked. **When it runs:** the loader checks the list at the last moment before it hands over your script, once the executor has reported its HWID. A blocked device never receives a single byte of the script — it is kicked with *"You're Blacklisted from the Service (Your Service)"* (or *"You're not Whitelisted for the Service (Your Service)"* in Whitelist Only mode). Because the check is live, blacklisting someone in the dashboard takes effect on their very next execution. Needs a linked service The Trust List reads the lists that belong to a service, so it can only be enabled on a script that has one selected above. Clear the Service and the toggle switches off. Blocked executions show up in Telemetry Every block is recorded so you can see who is being turned away — look for trust_list_blocked in the script's execution logs. ## Validate Libraries Picks the validation library version the script will use to call back to Panda Auth at runtime. The main options: - **PandaAuthV4 (Built-in)** — recommended for new scripts. Ships inside the loader with your Service ID already baked in, so you never call configure(). - **V3-iVAL (Pelinda)** — HTTP AES/SHA inline validation, injected ahead of your source. Use it when you want the V3 call shape. - **I add the library myself** — nothing is injected or pre-configured. You integrate a Panda Auth validation library in your own script. Pick PandaAuthV4 for new uploads Unless you have a specific reason, default to the built-in PandaAuthV4 SDK. It gets security updates first and has the smoothest integration with the current Kryptic loader. ## Lua Source Upload your actual script file. This is usually your key system GUI script or the main entrypoint — the SDK from the validation library you picked above loads here. ## Obfuscation (Luraph) The obfuscation preset that runs against your script before it's served. Three presets: - **Recommended** — balanced Luraph configuration for most scripts. Strong protection, broad compatibility. - **Max Compatible** — obfuscation tuned for low-UNC executors. Less aggressive, but works on more devices. - **Customization** — manually configure every Luraph option. Don't touch Customization unless you know Luraph The Customization mode exposes every Luraph knob. Wrong settings can produce scripts that fail at runtime on real executors, break specific opcodes, or slow execution dramatically. If you're not comfortable reading Luraph documentation, stick with Recommended or Max Compatible. ## Kryptic Vault options Extra hardening features that run alongside obfuscation. Each is independent — turn on the ones you want. Kryptic Vault options - **Heartbeat** — periodic check-ins from the running script to verify it's still legitimate. Fails closed if the heartbeat stops, catching dump-and-replay attacks. - **Performance** — runtime optimizations for the loader. - **AI Optimization** — applies a machine-learning tuned obfuscation profile based on similar scripts. - **Silent Mode** — failure modes don't produce visible errors. Bypass tools have a harder time iterating without clear error messages to debug against. - **Auto-Backup to Google Drive** — every time you change your script, an automatic backup is pushed to your connected Google Drive. ## Ini Script (2nd Script) An advanced feature: upload a second script that runs only when the first script triggers it via **PandaV4.InitScript()**. The pattern lets you split a loader from the actual UI or game code, so the second script stays hidden until the first script explicitly invokes it. Useful for keeping your main script logic out of the initial loadstring path — bypass tools that capture the first loadstring don't get the actual logic, just the bootstrap. ## Obfuscator backends Beyond Luraph, Kryptic supports community-built obfuscators for users who want alternatives: Kryptic Vault obfuscation backends - **Luraph** — the recommended commercial obfuscator. Strong, well-supported, broadly compatible. - **Lua-Crack** — community-built obfuscator with a different attack surface than Luraph. - **WeAreDevs / Prometheus** — open-source obfuscator stack. - **Dead-Secure** — community-built obfuscator focused on aggressive protection. Pick one, stick with it Different obfuscators have different runtime characteristics — some are faster, some are more aggressive, some have better compatibility with specific executors. Pick one for a given script and avoid switching mid-development; if you need to change, retest the script end-to-end on your target executors. ## Upload Click **Upload**. Kryptic obfuscates the script, builds the loader, generates a loadstring URL, and adds the script to your vault dashboard. You can now ship the loadstring to your users. Done — you have a loadstring Your script is now served from the vault. Users execute the loadstring; Panda Auth validates them against your service; the obfuscated script runs inside the hardened loader. From here, check the Telemetry page to monitor execution. --- For Developers · Tokens # Panda Tokens The Panda Token is the only currency on the platform. Kryptic Vault, VSS obfuscation and Panda AI all spend the same balance. ## One currency, two balances There is no such thing as a VSS token or a credit token any more. Those were separate columns that could only be spent in some places, which is why the dashboard used to show you two or three different numbers and why the Vault would refuse a balance the VSS page said you had. Both were merged into your Panda Token balance and removed. Nothing was lost and there is nothing to migrate. One currency, but it is held on two sides. The only difference between them is what survives the 1st of the month: - **Monthly allowance** is what your tier pays you. It is set back to your tier allocation on the 1st of every month, so it does not roll over. - **Credits** are tokens you bought, redeemed with a code, earned from a referral or were granted. They carry over indefinitely and are never reset. Your spendable balance is the sum of the two, and you never pick which side pays. A charge drains the monthly allowance first and only reaches for credits once the allowance is gone. That ordering is deliberate: it spends the balance that expires before it spends the balance that does not. ## What things cost - **Upload a script** — 1 token. - **AI Optimize** — 0.5 tokens on top. - **Init script with Luraph** — 1 extra token. (Lua-Crack and WeareDevs init scripts have no surcharge.) You only pay for what succeeds Tokens are charged for operations that complete. If obfuscation fails, you are not charged for it. ## Recurring grants Tokens are **added** to your monthly allowance on a schedule. They are not topped up to a floor: a grant stacks on whatever allowance you already have, up to a cap of twice the grant amount so unused tokens do not accrue forever. Tokens you buy are not affected by that cap, because they are credits rather than allowance, and credits are not affected by the reset below either. - Free — +10 tokens per month, once your account is verified - Basic — +10 tokens per month, once your account is verified - Premium — +10 tokens per week - Special — +10 tokens per week - Enterprise — +80 tokens per month New accounts get 5 tokens, once A new account is created with 5 Panda Tokens to try the Vault with. That grant is one-time and never renews. Free and Basic earn nothing further until the account is verified. Once a moderator accepts your verification your balance is filled to 10 straight away — not on some later schedule — and the monthly grant starts from there. Premium, Special and Enterprise are paid regardless. ## Upgrading a tier Buying a tier credits Panda Tokens to your balance straight away, on top of what you already hold: Free and Basic 10, Premium and Special 30, Enterprise 60. Those land in your credits, so they keep. This is separate from the recurring grant above and does not delay it. ## Buying more Need more than your grant? Buy Panda Tokens with PayPal or card from the token widget in the dashboard. Tokens are `$0.50` each, minimum 2, maximum 100 per purchase, so the smallest order is`$1.00` and the largest is `$50.00`. Paying in USDT has a higher minimum of 10 tokens, because network fees make smaller transfers uneconomic. Anything you buy goes to your credits and stays there until you spend it. ## The monthly reset On the 1st of every month at 00:00 Singapore time, every monthly allowance is set to its tier allocation: Free and Basic 10, Premium and Special 30, Enterprise 60. Your purchases are safe The reset only ever touches the monthly allowance. It does not read your credits, let alone write them, so tokens you bought, redeemed or earned are still there on the 2nd. Purchased tokens used to share one column with the allowance, which is why the reset could take them and why the old advice was to spend rather than stockpile. That is fixed, and stockpiling credits is now a reasonable thing to do. On the allowance side it is a hard set, not a top-up. An allowance you built up above your tier allocation does not carry across the 1st, so there is nothing to gain by sitting on unspent grant. Unverified Free and Basic accounts are skipped by the reset entirely. It would otherwise hand them the tier allocation every month without verifying, and it would wipe whatever is left of their signup grant. --- For Developers · Kryptic Vault # Loader & Execution When a user runs your loadstring, they do not get the raw script. They get a small loader that proves the session is genuine, then receives the real code over an encrypted channel. Here is what happens and why it is hard to bypass. ## The execution flow 1 Handshake The loader opens a secure connection and exchanges keys with the server. Each session is bound to the user and uses fresh, single-use credentials. 2 Environment check A small check script runs first. If it spots a logger or hook trying to capture the code, it stops responding instead of returning, so the attacker gets nothing and the server records the attempt. 3 Function check The loader confirms the executor behaves like a real one before any of your code is sent. 4 Delivery Only after the checks pass does the server stream your main script down in chunks. If you attached an init script, it is delivered at this stage too. ## Two transports - **WebSocket** (default) — a live connection with the lowest latency and the richest session tracking. - **HTTP long-poll (Compatible Mode)** — a fallback for executors that cannot hold a WebSocket open. Same security, delivered over HTTP requests instead. ## Why it resists tampering The channel is encrypted and signed. The server identity is verified, every message is checked for freshness and order to block replays, and the challenge token is single-use and tied to the requesting device. If anything looks off, the loader simply does not deliver the script. Tamper attempts are logged When the environment check detects a hook, the run is recorded as a crack attempt. You can review these in the vault's execution logs. ## Execution telemetry Every run reports back: which executor was used, whether it succeeded, and whether a tamper attempt was seen. The **Logs** page in the vault turns this into a live view of who is running your script and how it is behaving in the wild. Execution telemetry in the vault logs ## Built-in PandaAuth If you linked the script to a service, the loader wires in PandaAuth V4 for you. Your script can call `Validate()` and `GetKey()` directly, and when an init script is enabled it is fetched through the same trusted channel. ## Loader options Set these on `getgenv()` **before** your loadstring runs. Both are optional and both are read from `getgenv()` or `_G`, whichever your executor exposes. Copy ```lua getgenv().HIDE_GUI = true getgenv().Authentication_Method = "Auto" loadstring(game:HttpGet("https://vss.pandauth.com/kv/YOUR_SLUG"))() ``` - `HIDE_GUI` — defaults to `false`. When true the on-screen loading card is never created; the same progress is printed to the console instead. Useful for scripts that draw their own UI. Silent Mode still wins over this — it suppresses output entirely. - `Authentication_Method` — which identity your key is checked against. Defaults to `"ClientID"`. - `"ClientID"` (default) — the executor's hardware id (`gethwid()`). Unchanged behaviour. - `"UserID_Only"` — the player's Roblox user id, sent as `rbx-`. The key follows the account instead of the device, so the same key works on any executor the player uses. It also means anyone on that account shares the key. - `"Auto"` — tries the hardware id first and falls back to the user id only if the key is rejected outright. Rate limits and network errors are not retried on the fallback, so a temporary blip never burns it. Switching modes re-binds the key Keys are bound to whichever identity generated them. A player whose key is bound to their hardware id will need a new key after you switch that script to "UserID_Only" — or use "Auto" , which accepts either. The link returned by GetKey() always carries the identity your chosen mode uses, so new keys bind correctly without any extra work. `PandaAuthV4.GetAuthMethod()` and `PandaAuthV4.GetIdentity()` return the active mode and the identity that authenticated, if you want to surface either in your own UI. --- For Developers · Kryptic Vault # Telemetry Telemetry is the per-execution log for every script you upload to Kryptic Vault. Every time your script runs on a user's device, an entry is added to the telemetry table — date, Roblox user, game ID, executor, script, and HWID. It's how you know what's actually being run, where, by whom, and on which executor environment. Execution Telemetry ## What gets logged Every execution of a Kryptic-served script produces a telemetry row with this information: - **Date / Time** — when the script executed. - **User** — the Roblox user that triggered the execution. - **Game ID** — the Roblox place ID the script ran inside. Useful for understanding which game your script is being used in. - **Executor** — which Roblox executor environment was used (Synapse, Krnl, Fluxus, and so on). - **Script** — which of your uploaded scripts ran. - **HWID** — the device fingerprint of the user's machine. ## Why telemetry matters Telemetry answers questions you can't easily answer any other way: - **Is my script actually being used?** A flat telemetry chart means users hit your key flow but never executed the script. Worth investigating. - **Which game is driving my traffic?** If the same game ID dominates your telemetry, that's where your audience actually is — useful for targeting marketing. - **Which executors do my users run?** A surge in executions from a particular executor might mean you need to test compatibility there more carefully. A drop might mean that executor's user base moved elsewhere. - **Is one user running my script abnormally often?** High-frequency executions from a single HWID can flag automation or testing-tool usage. - **Did a code change break execution?** A sudden drop after a script update is the fastest way to know your latest version is failing on real devices. ## How to use the telemetry view The telemetry page shows every execution as a row in a searchable, sortable table. Filter by script, by date range, by executor, or by Roblox user to narrow down. Sort by date to see the most recent executions first, or by executor to spot environment-specific issues. Best practice Check telemetry after every script update. The minutes after you push a new version are when you most need to know whether executions still happen at the expected rate — if they don't, rolling back the change is straightforward; finding the bug three days later when users start complaining is not. Telemetry is automatic for Kryptic-served scripts You don't need to add anything to your script — Kryptic's runtime loader reports execution automatically. Telemetry only tracks scripts served through Kryptic Vault. Scripts shipped through the legacy VSS or distributed outside the vault are not tracked. --- For Developers · Discord Bot # PandaAuth Core Bot Invite one bot, link your service, and your Discord server becomes a whitelist dashboard — key delivery, redemption, HWID resets, buyer roles and an audit trail, without your buyers ever leaving Discord. ## What it does PandaAuth Core is the official Discord bot for Panda Key System. It is multi-tenant: the same bot serves every developer. You invite it, run `/login`, pick which of your services this server sells, and everything the bot does from then on happens against that service through the public API. - **Members** press buttons on a panel — Get Key, Redeem, Get Script, Reset HWID, My Stats, Get Role — or use the equivalent slash commands. - **You** whitelist, blacklist, compensate, bulk-generate keys and inspect members without opening the dashboard. - **Nothing is duplicated.** Keys, HWIDs and expiries stay in Panda Key System. The bot only stores which server is linked to which service, its panels and its settings. ## Multiple products in one server A server is not limited to a single service. Run `/login` again to link a second one, then post a separate panel for each with `/setpanel`. Every command takes an optional `service` option (with autocomplete) and falls back to the default service you set with `/select-service`. ## Requirements - A Panda Key System service that is **active**. Its API key is what the bot stores. - **Manage Server** permission, or the manager role set with `/settings roles`, to run any management command. - For the buyer role to work, the bot needs **Manage Roles** and its own role must sit **above** the buyer role in Server Settings → Roles. - For `/script` to return anything, at least one script must be marked **Discord-visible** in your dashboard. ## Permissions the bot asks for - **View Channel, Send Messages, Embed Links, Read Message History** — posting and updating panels. - **Attach Files** — delivering `/mass-generate` key files. - **Manage Roles** — granting and removing the buyer role. - **Manage Messages** — cleaning up panels deleted with `/panels delete`. Per-command permissions are Discord's, not ours The bot does not build its own permission system beyond the manager role. Open Server Settings → Integrations → PandaAuth Core to restrict any individual command to specific roles or channels. ## Privacy - Every reply the bot sends is **ephemeral** — only the person who ran the command sees it. Keys are never posted publicly. - Passwords and license keys are collected in **modals**, never as slash-command options, because Discord displays command arguments in the channel. - Your service API key is encrypted at rest by the bot and is never shown in any reply. ## Where to go next - **Set Up the Bot** — invite, link a service, configure roles, post a panel. - **Command Reference** — every command, option and permission. - **Member Panel** — what each button does and what members see. - **Troubleshooting** — what each error message means. --- For Developers · Discord Bot # Set Up the Bot From an empty server to a working whitelist panel in five steps. ## Setup 1 Invite the bot Use the invite link from your dashboard, or run /invite in a server that already has it. The link requests exactly the permissions listed in the overview — do not strip Manage Roles if you plan to use a buyer role. 2 Link your service Run /login account . A private form asks for your PandaAuth email and password. If your account has 2FA, a second prompt asks for the code from your authenticator app or your email — a recovery code works too. A dropdown then lists every service on your account; pick the one this server sells. Prefer not to type your password? /login apikey links the server with a service API key instead. Copy it from Dashboard → your service → API key . It creates no login session at all. 3 Set your roles Copy ```lua /settings roles manager:@Staff buyer:@Customer ``` Manager — may run every management command, on top of anyone with Manage Server. Buyer — handed out automatically when someone is whitelisted or redeems a key, and taken back on /unwhitelist . Both are optional; skip the buyer role if you do not gate channels by purchase. 4 Post the member panel Copy ```lua /setpanel channel:#get-script ``` One embed with the buttons your members need. Everything is customisable — title, description, image, and which buttons appear. Buttons keep working after a bot restart, so you post it once. 5 Turn on the audit trail (optional) Copy ```lua /setlogs webhook:https://discord.com/api/webhooks/... ``` Every command and button press is mirrored to that channel: who did it, to whom, and whether it succeeded. The bot sends a test message first and refuses a webhook Discord rejects. /logs shows the same history in-place without a webhook. ## Verify it worked Run `/status`. You should see the linked service, its key counts, the number of panels, and your role configuration. If the key counts are replaced by a warning, the stored API key is no longer accepted — re-run `/login`. ## Recommended settings - `/settings hwid cooldown_hours:24` — how long a member must wait between self-service HWID resets. Set `self_reset:False` to force every reset through staff. - `/settings general default_key_days:30` — the duration `/whitelist` uses when you do not pass `days`. - `/settings script key_variable:_G.YourKey` — the variable name in the snippet members receive. - `/settings general color:1D4ED8` — the embed accent, as hex without `#`. Re-render after changing settings Existing panels keep their old buttons and colour until you run /panels refresh . ## Adding a second product Run `/login` again and choose a different service, then post a second panel with `/setpanel service: channel:#other-product`. Set which one commands default to with `/select-service`; every command still accepts an explicit `service` option. ## Unlinking `/logout confirm:True` removes the link and the panels that belong to it. Members keep their keys — nothing is revoked. Removing the bot from the server has the same effect on the link, and re-inviting it requires `/login` again. --- For Developers · Discord Bot # Command Reference Every slash command PandaAuth Core provides, with its options and who may run it. ## How to read this page - Manager — needs **Manage Server**, or the manager role set with `/settings roles`. Server owners always qualify. - Everyone — any member of the server. - Almost every command accepts an optional `service` option with autocomplete. Omit it and the command uses the default service set by `/select-service`. It is listed once here rather than repeated on every command. - All replies are ephemeral — only the person who ran the command sees them. ## Linking /login account Manager Sign in with your PandaAuth email and password, then pick which service this server manages. A private form collects the credentials; if 2FA is on, a second prompt asks for the authenticator code, the emailed code, or a recovery code. /login apikey Manager Link with a service API key instead of your account password. Copy it from Dashboard → your service → API key. No login session is created. /logout Manager Unlink a service from this server. Panels belonging to it stop working and are removed. Members keep their keys — nothing is revoked. confirm boolean required Must be True ; the command refuses to run otherwise. service string Which linked service to unlink. /select-service Manager Choose which linked service commands target when they do not name one. Only moves the default — other services stay linked. service string required The service to make default. /status Everyone Show what this server is linked to. Members see the service list and panel counts; managers additionally see key counts, execution totals and the role/HWID configuration. ## Panels /setpanel Manager Post a member panel with persistent buttons. Post as many as you like — one per service, or several per service in different channels. channel channel Where to post it. Defaults to the current channel. title string Panel title. Defaults to “ · Whitelist”. description string Panel body. Use \n for line breaks. get_key boolean Show the Get Key button. Default on. redeem boolean Show the Redeem button. Default on. get_script boolean Show the Get Script button. Default on. reset_hwid boolean Show the Reset HWID button. Default on. stats boolean Show the My Stats button. Default on. get_role boolean Show the Get Role button. Default off; requires a buyer role. image string Large image URL. thumbnail string Thumbnail URL. /panels list Manager Show every panel, its service, its channel, a jump link and its id. /panels refresh Manager Re-render every panel message. Run this after changing settings so panels pick up new buttons and colours. /panels delete Manager Delete a panel and its message. panel_id string required The id shown by /panels list . ## Members /whitelist Manager Generate a key, bind it to a member, grant the buyer role and DM them the key. If their DMs are closed, the key is shown to you instead. user user required Member to whitelist. Bots are rejected. days integer Duration, 1–36500. Defaults to the server's default_key_days . lifetime boolean Never expires. Overrides days . premium boolean Mark the key as premium. note string Note stored on the key. /unwhitelist Manager Revoke every key the member holds on this service and remove the buyer role. Revoked keys stay on record by default, so the history survives. user user required Member to revoke. delete boolean Delete the keys outright instead of marking them revoked. /mass-whitelist Manager Whitelist every human member holding a role — the migration tool for moving a user base across. Reports an ETA, updates progress as it goes, and stops early if the API key is rejected. role role required Role to whitelist. days integer Duration. Defaults to the server default. lifetime boolean Never expires. premium boolean Mark the keys as premium. skip_existing boolean Skip members this server already issued a key to. Default on. dm boolean DM each member their key. Default on. /blacklist Manager Block a member or a raw HWID. For a member: every key they hold is suspended and every device bound to those keys is blacklisted. A member with no device bound yet still has their keys suspended. user user Member to block. hwid string Block a raw HWID instead. reason string Reason stored on the entry. days integer Expire the block after N days. Omit for permanent. /unblacklist Manager Lift a block: un-blacklists the HWIDs and reactivates the keys the block suspended. user user Member to unblock. hwid string Unblock a raw HWID instead. /force-resethwid Manager Reset a member's device binding, ignoring the self-service cooldown. Their own cooldown is not consumed. user user Member whose key to reset. key string Reset by key value instead. Mass operations are paced deliberately The API allows 30 requests per minute per service, and each member costs two. /mass-whitelist therefore processes roughly twelve members a minute, caps at 500 members per run, and DMs you the summary if the run outlives Discord's 15-minute interaction window. ## Keys and analytics /mass-generate Manager Generate unassigned keys and receive them as a .txt file — for resellers, giveaways or manual distribution. count integer required How many keys, 1–200. days integer Duration. Defaults to the server default. lifetime boolean Never expires. premium boolean Mark the keys as premium. note string Note stored on every key. dm boolean Send the file by DM. Default on; falls back to an ephemeral reply if your DMs are closed. /compensate Manager Add days to every active key on the service at once — what you run when a script gets patched. Lifetime keys are skipped. days integer required Days to add, 1–365. confirm boolean required Must be True . This cannot be undone from Discord. reason string Recorded in the audit log. /lookup Manager Inspect a member, a single key or an HWID: status, expiry, bound device, premium flag, note and last use. HWID lookups also report whether it is blacklisted. user user Every key a member holds. key string One key value; searches both activated and unredeemed keys. hwid string The key bound to a device, plus its blacklist state. /stats Manager Service analytics: active keys, unredeemed keys, keyless entries, blacklisted devices, total executions, how many members this server whitelisted, and which scripts are Discord-visible. ## Configuration /settings view Manager Show the current configuration for this server. /settings roles Manager Set the manager and buyer roles. Warns if the bot cannot assign the buyer role. manager role Role allowed to run management commands. buyer role Role granted to whitelisted members. clear boolean Clear both roles. /settings hwid Manager Self-service HWID reset rules. self_reset boolean Let members reset their own device binding. cooldown_hours integer Hours between self-service resets, 0–720. 0 disables the cooldown. /settings script Manager How the Get Script snippet is built. key_variable string Variable the key is assigned to, e.g. _G.PandaKey . custom_loadstring string Full custom snippet. {key} and {script} are substituted. clear_custom boolean Remove the custom snippet and go back to the default form. /settings general Manager Defaults and appearance. default_key_days integer Duration /whitelist uses when none is given. color string Embed accent as hex without # , e.g. 1D4ED8 . allow_get_role boolean Allow the panel's Get Role button. /setlogs Manager Mirror every command and button press to a Discord webhook. The bot posts a test message and refuses a webhook Discord rejects. webhook string Discord webhook URL. clear boolean Stop logging. /logs Manager Recent bot activity in this server, without needing a webhook. limit integer How many entries, 1–25. Default 15. ## Member commands These do the same work as the panel buttons, for members who prefer commands or servers that do not post a panel. /getkey Everyone Opens the checkpoint page for this service, where a key can be earned. /redeem Everyone Bind a key you own to your Discord account. The key is typed into a private form, never as a visible command argument. /script Everyone Your personal loader snippet, with your key already filled in. Requires a valid key. /resethwid Everyone Clear your own device binding so the script runs on a new device. Subject to the server's cooldown. /mykey Everyone Your key status: expiry, bound device, tier and whether it is still valid. /getrole Everyone Claim the buyer role if you hold a valid key. ## General /help Everyone What the bot can do. Managers additionally see the management commands. /ping Everyone Latency to Discord and to the Panda backend, plus uptime. /invite Everyone Invite link with the correct permissions pre-selected. --- For Developers · Discord Bot # Member Panel One embed in one channel that behaves like a small application: your buyers redeem, pull the script and reset their own device without ever opening a ticket. ## Posting a panel Copy ```lua /setpanel channel:#get-script title:My Script description:Press a button below. ``` The panel is a normal message the bot owns. Its buttons are rebuilt from the database every time somebody clicks, so restarts, redeploys and updates never break them — you post it once and leave it. There is no limit of one panel per server. Post one panel per product, or several panels for the same service in different channels. ## What each button does - **🔑 Get Key** — replies with a link to your service's checkpoint page, where the member earns a key. - **🎟️ Redeem** — opens a private form for a key. The key is checked against this service, refused if it is expired, revoked or already claimed by somebody else, then bound to the member's Discord account. The buyer role is granted at the same moment. - **📜 Get Script** — returns the loader with the member's own key already filled in, one block per Discord-visible script. A single copy-paste. - **🔄 Reset HWID** — clears the device binding, subject to the cooldown you set. The member is told exactly when they may reset again. - **📊 My Stats** — status, expiry, bound device (masked) and tier for every key the member holds here. - **👤 Get Role** — claims the buyer role for a member who already holds a valid key. Off by default; needs a buyer role to be configured. Everything is private Every button replies ephemerally. Keys, snippets and device IDs are only ever visible to the member who pressed the button. ## The script snippet By default a member receives: Copy ```lua _G.PandaKey = "PANDA-XXXX-XXXX-XXXX" loadstring(game:HttpGet("https://vss.pandauth.com/kv/"))() ``` Change the variable name with `/settings script key_variable:_G.YourKey`, or replace the whole snippet with `custom_loadstring`, where `{key}` and `{script}` are substituted: Copy ```lua /settings script custom_loadstring:getgenv().Key = "{key}"\n{script} ``` Nothing to hand out yet? Get Script only returns scripts marked Discord-visible in your dashboard. With none marked, members are told the owner has not published one. ## Typical member journey - Member presses **Get Key** → completes the checkpoints → receives a key. - Back in Discord, presses **Redeem** → pastes the key → gets the buyer role. - Presses **Get Script** → pastes the snippet into their executor. - New PC later → presses **Reset HWID** → runs the script again. None of those steps needs you. If a member is stuck, the fastest checks are `/lookup user:@them` to see what they hold, and `/force-resethwid user:@them` to clear a device binding without waiting for the cooldown. ## Editing a panel Panel text and buttons are fixed at creation. To change them, delete the old panel and post a new one: Copy ```lua /panels list /panels delete panel_id: /setpanel channel:#get-script ... ``` Colour and settings-driven changes — the accent, whether Reset HWID or Get Role appear — apply to existing panels after `/panels refresh`. --- For Developers · Discord Bot # Bot Troubleshooting What each error the bot shows actually means, and the fastest fix. ## Linking This server is not linked to a Panda service yet setup optional Nobody has run `/login` here, or the link was removed. An admin runs `/login account` or `/login apikey`. Captcha verification failed login optional The dashboard login is captcha-protected, and a bot cannot solve it. Use `/login apikey` instead — it links the server with your service API key and is not affected. Invalid credentials login optional Wrong email/username or password, or the account signs in with Google only and has no password set. Google-only accounts must use `/login apikey`. MFA session expired or invalid login optional The 2FA prompt was left open too long. Run `/login account` again. No services found login optional The account owns no service yet. Create one in the dashboard first. The stored API key was rejected runtime optional The service's API key was regenerated, or the service was disabled. Re-run `/login` to store the current key. IP not whitelisted for this API key runtime optional The service has an IP allowlist and the bot's host is not on it. Add the bot host's IP under the service's allowed IPs, or clear the allowlist. This Discord server is already bound to service … linking optional The dashboard binds one Discord server to one service. The bot still links locally and works normally — only the dashboard's own binding field is left pointing at the first service. ## Keys and members Key not found redeem optional The key belongs to a different service, or it was mistyped. Check with `/lookup key:` — that searches both activated and unredeemed keys on the selected service. Already claimed redeem optional The key is bound to another Discord account here. Issue a new one with `/whitelist`, or free it with `/unwhitelist` on the account that holds it. No valid key is linked to your Discord account member optional The member never pressed Redeem, or their key expired or was revoked. `/lookup user:@them` shows what they actually hold. Reset failed / not eligible hwid optional The key has no device bound yet — there is nothing to reset — or the service's own reset cooldown is still running. That cooldown is configured per service in the dashboard and is separate from the server-side cooldown in `/settings hwid`. Cooldown active hwid optional The member's server-side cooldown. Use `/force-resethwid user:@them` to bypass it without consuming their next reset. Cannot extend lifetime key keys optional Lifetime keys have no expiry to extend, so `/compensate` skips them by design. ## Roles bot role is below the buyer role roles optional Discord only lets a bot manage roles ranked beneath its own. In **Server Settings → Roles**, drag the bot's role above the buyer role. Could not grant the buyer role roles optional Usually the ranking above, or the bot is missing **Manage Roles**. Re-invite with the default permissions if it was stripped. buyer role no longer exists roles optional The role was deleted. Set a new one with `/settings roles buyer:@Role`. Managed roles cannot be granted Roles created by another bot or by a Discord integration (including booster roles) can never be assigned by a third-party bot. Use a plain role for buyers. ## Panels and commands Panel unavailable panel optional The panel row was deleted — usually because its service was unlinked. Post a fresh one with `/setpanel`. Cannot post there panel optional The bot lacks **View Channel** or **Send Messages** in the target channel. Commands do not appear discord optional Newly published global commands can take up to an hour to propagate. Fully closing and reopening the Discord client usually surfaces them sooner. You need Manage Server… permissions optional You are neither an admin nor holding the manager role. Ask an admin for `/settings roles manager:@YourRole`. ## Rate limits The API allows **30 requests per minute per service**. The bot stays under that with its own queue and retries when the limit is hit, so bursts of panel presses are safe. What you will notice: - `/mass-whitelist` processes roughly twelve members a minute and shows an ETA before starting. - Runs longer than fifteen minutes DM you the final summary, because Discord's interaction window closes before the run does. - Each linked service has its own queue, so a busy server never slows another one down. ## Still stuck `/status` shows whether the link and API key are healthy, `/ping` shows whether the backend is reachable, and `/logs` shows what the bot last did in this server, including failures. --- For Developers · Panda MCP # Panda MCP-Development Panda MCP lets an AI assistant (Claude Code, Codex, Antigravity, Cursor, Gemini) talk to a Roblox game you're running through your executor. You enable it once, connect the AI client by signing in with your Panda account or with a Client API Key, and paste a one-line loader into your executor to connect the game. ## How it works There are two sides to a Panda MCP session: - **Your AI client** (Claude Code / Codex / Antigravity / Cursor / Gemini) connects over HTTP to `mcp.pandauth.com/mcp`, authenticated either by **signing in with your Panda account** or by a **Client API Key**. - **Your Roblox executor** connects over a secure WebSocket to the same server and reports back its Roblox username, executor, place and device. This side always uses the Client API Key. Connected executors show up live on your dashboard under **Client Connected (MCP)**, where you can Kick or Blacklist them. ## 1 · Enable MCP & get your API key 1 Open Dashboard → MCP Control Go to Dashboard → MCP Control and turn on Enable Panda MCP-Development . 2 Generate your Client API Key Click Generate API Key . The full key is shown once — copy it now. You can Reset it anytime (which invalidates the old one). 3 Pick your permissions Toggle what PandaMCP is allowed to do (developer console, Kryptic Vault, services, anti-AFK). See Permissions below. Treat the key like a password Anyone with your Client API Key can connect as you. Don't commit it to a repo or paste it in a public place. If it leaks, hit Reset API Key . ## 2 · Sign in from your AI client (no key in your config) Panda MCP is an OAuth 2.1 resource server, so a client can authenticate as you without a key ever touching its config file. Point it at `https://mcp.pandauth.com/mcp` with no credential and it discovers the sign-in flow on its own. Claude Code Codex Antigravity Cursor Copy ```lua claude mcp add --transport http panda-mcp https://mcp.pandauth.com/mcp # then, inside Claude Code: /mcp # pick panda-mcp -> Authenticate ``` Whichever client you use, the browser lands on the Panda consent screen: it names the client, lists exactly which permissions it is about to get, and shows **Signed in as your-email** so you can see which account you are binding before you press Allow. Ask the AI to run `whoami` afterwards and it reports the same account back. 1 No browser on that machine? Use a code Over SSH, inside a container, or in any client that cannot open a browser, the same sign-in works with a code instead of a redirect. Clients that support the device flow print a short XXXX-XXXX code: open pandauth.com/mcp/device on any device you are signed in on, type it, approve, and the client picks up the connection within a few seconds. The code lasts 15 minutes. 2 …or paste the code back Clients that ask for a pasted code (they register the redirect urn:ietf:wg:oauth:2.0:oob ) get the approval page showing a long one-time code instead of redirecting. Copy it, paste it into the waiting prompt, and the client confirms which account it signed in as. That code is valid for 10 minutes and works once. A code is a live credential until it is used Anyone who gets the code in that window can connect as you. Never read one out on stream or paste it into a chat — if one leaks, deny the next prompt and start over. Access follows your MCP switches Signing in grants only what MCP Control has enabled at that moment. Turning Panda MCP off, or turning a permission off, applies to the next tool call — there is no separate list of client grants to go clean up. ## 3 · …or connect with your Client API Key Add Panda MCP as a remote (Streamable HTTP) server. Replace `YOUR_API_KEY` with the key from step 1. The header method is preferred — it keeps the key out of shell history and logs. Claude Code Codex Antigravity Cursor Gemini CLI Copy ```lua # Add the server (key in an auth header — recommended) claude mcp add --transport http panda-mcp https://mcp.pandauth.com/mcp \ --header "Authorization: Bearer YOUR_API_KEY" # …or embed the key in the URL instead of a header claude mcp add --transport http panda-mcp "https://mcp.pandauth.com/mcp?api_key=YOUR_API_KEY" ``` After adding it, restart the client (or run `/mcp` in Claude Code) to confirm `panda-mcp` is connected. ## 4 · Connect Roblox (executor) Paste this into your executor while in the game you want to control. Set `_G.Api_Key` to your Client API Key, then run the loader: Copy ```lua _G.Api_Key = "YOUR_API_KEY" loadstring(game:HttpGet("https://mcp.pandauth.com/connect"))() ``` A small **Panda MCP** status pill appears bottom-right. Once it reads **Connected**, the client shows up on your dashboard's **Client Connected (MCP)** panel. It auto-reconnects if the connection drops. The same loader also installs the **Roblox decompiler**: `getgenv().decompile` is wrapped so Dex and other viewers get the Panda result, and `getgenv().PandaDecompiler` is the direct API. It decompiles with your executor's own function first and only falls back to PandaMCP when there is none. Want the decompiler without the bridge? Load `https://mcp.pandauth.com/decompiler/connector` instead. Optional globals (set before the loadstring): - `_G.Anti_AFK = false` — disable anti-AFK (on by default). - `_G.Keep_Reconnecting = false` — stop after one disconnect. - `_G.Panda_MCP_Url = "wss://…"` — override the server URL (self-host / dev). - `_G.Fling_Protection = false` — refuse the server's fling guard (on by default). - `_G.Auto_Execute = false` — refuse auto-execute pushes (on by default). - `_G.Console_Log = false` — keep `print`/`warn` local instead of mirroring them to the dashboard (on by default). - `_G.Panda_Decompiler = false` — skip the bundled decompiler connector entirely (on by default). - `_G.Panda_Install_Decompile = false` — load the decompiler but leave `getgenv().decompile` alone and call `PandaDecompiler:Decompile()` yourself. These globals can only ever *refuse* a feature — they never switch one on that the MCP Control page has turned off. Executor needs WebSocket + HttpGet The loader uses the executor's WebSocket API ( WebSocket.connect / syn.websocket ). Most modern executors support it; a few mobile ones may not. ## Permissions Each toggle on the **MCP Control** page controls what the AI may do: - **Roblox Developer Console** — read console output / logs from the game. - **Kryptic Vault** — access and manage your Kryptic Vault scripts. - **Manage your Services** — act on your PandaAuth services. - **Anti-AFK** — enable/disable the anti-AFK keep-alive on connected clients. Least privilege Leave everything off and switch on only what a given task needs. You can change permissions any time — they apply to new tool calls immediately. ## Runtime features These are set on the **MCP Control** page and pushed to every connected client immediately — no rejoin, no re-running the loader. - **Fling Protection** — clamps absurd character velocities every Heartbeat, so exploiters can't fling you off the map. Legit fast movement is preserved (the direction is kept, only the magnitude is capped). - **Auto-Execute Script** — paste or upload a `.lua` file (512 KB max). Every client that connects with your key runs it automatically, right after it authenticates. Saving re-fires it on clients that are already connected. - **Console Log** — `print` and `warn` from connected clients are mirrored to the MCP Control console as `[ (Player - Executor) ] - message`. Output still reaches the executor's own console as well. Console logs are kept for 7 days Lines live in Redis, not the database, and expire automatically after 7 days. They're capped per account, so a chatty script can't grow without bound. ## Managing connected clients On the dashboard home, the **Client Connected (MCP)** panel lists every executor connected with your key: - **Kick** — drop the session. The client can reconnect. - **Blacklist** — permanently ban that Roblox UserId *and* device (HWID). It can't reconnect with your key. --- API Reference # Overview Call Panda Auth directly over HTTP. Every key, blacklist, shortener, and VSS operation has an endpoint. ## Base URL Copy ```lua https://api.pandauth.com/api/v1 ``` All endpoints below are relative to this base. The API speaks JSON. ## What's here - **Authentication** — how API keys authenticate requests. - **API Key Permissions** — what each key is allowed to do. - **Dashboard API** — keys, blacklist, HWID resets, generation. - **URL Shortener API** — create checkpoint-routed short links. - **VSS Management API** — upload, list, and delete scripts. - **Account Limits API** — validate keys with multi-account caps. Where to get your API key Each service has its own API key under Service Settings → General → API Key . --- API Reference # Authentication & API Keys Authenticate every request with your service API key, sent as a header. ## The header Send your key in the `X-API-Key` header. Keys look like `pk_live_xxxxxxxxxxxx`: Copy ```lua GET /api/v1/keys/api/blacklist Host: api.pandauth.com X-API-Key: pk_live_xxxxxxxxxxxx ``` No bearer token Authentication is a direct header. There's no OAuth or bearer flow. Just set X-API-Key on each request. ## Where to find your key Open **Service Settings → General → API Key**. There's a copy icon, and a regenerate button that invalidates the old key immediately if it's ever leaked. ## Keep it secret Server-side only Treat the API key like a password. Use it from your backend or bot, not from client code where users could read it. --- API Reference # API Key Permissions API Permission lets you scope your service's API key — limiting what actions it can perform and which IP addresses are allowed to use it. Both settings exist for the same reason: if your API key ever leaks, the damage is bounded by whatever permissions and IPs you allow. Limit aggressively and a leaked key becomes almost useless to whoever found it. API Permission configuration ## Why scope your API key A typical Panda Auth service's API key can do a lot — generate keys, edit existing keys, upload Kryptic Vault scripts, create shorteners. If that key leaks (accidentally committed to a public GitHub repo, posted in a Discord support channel, embedded in client-side code that ships to users), whoever finds it can do all those things against your service. API Permissions and IP Allowlist are your defense. With both configured tightly, even a leaked key gives the attacker almost nothing useful. ## The three permissions Each API key has three independent permission flags: - `allowUrlShortener` — gates `POST /public/shortener/create`. Default: allowed. - `allowManageKeys` — gates mutating `/keys/api/*` routes (generate, edit, delete, keyless, webhook, Discord). Default: allowed. - `allowVss` — gates `/vss/api/*` (upload, list, loadstring, update, delete). Default: allowed. Read-only routes aren't gated GET routes (key lookup, service info/status, validation, check-hwid, validate-account, and similar) are always allowed regardless of these toggles. Public read endpoints don't pose a leak risk because they only return public data. ## Read permissions GET /api/v1/services/:id/permissions Copy ```lua { "success": true, "data": { "allowUrlShortener": true, "allowManageKeys": true, "allowVss": true } } ``` ## Update permissions PATCH /api/v1/services/:id/permissions Copy ```lua { "allowUrlShortener": false, "allowVss": true } ``` ## Denied response When a key lacks a permission, the action returns: Copy ```lua { "success": false, "error": "This API key is not permitted for this action (allowVss)" } ``` ## IP Allowlist The IP Allowlist restricts which addresses can use your API key. When you add IPs to the allowlist, requests from any other address are rejected — even if they have the correct key. The allowlist accepts: - **Exact IPv4 addresses** — `1.2.3.4` - **CIDR ranges** — `10.0.0.0/24` for a whole subnet Why IP Allowlist matters If you only call the Panda Auth API from a single server (e.g., a Discord bot on a VPS, a license-management backend on Heroku), adding just that one IP to the allowlist means a leaked key is useless to anyone who isn't running from that exact IP. This is one of the highest-value security configs you can set. Recommended security setup For most services: leave the three permission flags on (they are the default), but add your backend's IP to the allowlist. That gives you full API functionality while making the key worthless to a leaker. For services where you only need a subset of operations, disable the unused permissions too — a key that cannot delete keys cannot be used to delete keys, regardless of whether the leaker has it. --- API Reference # Dashboard API Manage keys, the HWID blacklist, and resets programmatically. All routes use your X-API-Key header; creating, editing, or deleting keys and blacklist entries also requires the allowManageKeys permission. Full request & response examples in your dashboard You're viewing the public API reference. Sign in and open Documentation → API Reference in your dashboard for copy-paste curl requests and live response examples for every endpoint. ## Generate keys POST /keys/api/generate Create one or more generated keys. `expirationType` is `byDays`, `byDate`, or `lifetime`. ## Fetch an active key GET /keys/api/key Search an active key by `key`, `hwid`, or `note`. ## Edit an active key PUT /keys/api/key Update `note`, `hwid`, `isPremium`, `noHwidValidation`, `status`, `expiresAt`, or `discordId`. Only the fields you send are changed. ## Delete an active key DELETE /keys/api/key ## Extend key expiration POST /keys/api/key/extend-expiration Add `days` to a key's expiration. Lifetime keys (no expiry) cannot be extended. ## Fetch a generated key GET /keys/api/generated-key Search a generated key by `key` or `note`. ## Edit a generated key PUT /keys/api/generated-key Same fields as an active key, plus `discordId` (the Discord bind carries over when the key is validated). `expiresAt` cannot be null for generated keys. ## Delete a generated key DELETE /keys/api/generated-key ## Check key binding GET /keys/api/key/binding Whether a key is HWID-bound. `type` is `active` (bound key) or `generated` (not yet redeemed, never bound). ## Discord Bot — fetch by Discord ID GET /keys/api/key/by-discord Fetch every key bound to a Discord user — searches both generated and active keys. Pass `discordId` (required). Add `includeLoadstring=1` to also receive your Discord-visible script loadstring(s) when the user has a valid key (built for VSS or Kryptic Vault). Bind a user with the `discordId` field on the edit endpoints above. ## Reset HWID POST /keys/reset-hwid Unbinds a key's HWID. Behaves exactly like the self-serve reset page — it honours your dashboard cooldown config, picking the free or premium cooldown automatically. ## Keyless — fetch GET /keys/api/keyless Look up a keyless (whitelist) entry by `hwid`. ## Keyless — add POST /keys/api/keyless Whitelist an HWID. `isPremium` and `expiresAt` are optional (defaults to non-premium, 1 year). ## Keyless — remove DELETE /keys/api/keyless ## Service info GET /keys/api/service/info Service metadata and a snapshot of its settings. ## Service status GET /keys/api/service/status Live counts: active keys, generated keys, keyless entries, blacklisted HWIDs, and total executions. ## Execution — increment POST /keys/api/execution Increment the service execution counter (and bump last-active). ## Execution — get GET /keys/api/execution ## Send webhook POST /keys/api/webhook Post a message to the service's configured Discord webhook. `content` is required; `username` is optional. The webhook must be enabled in settings. ## Compensate (bulk extend) POST /keys/api/compensate Add `days` (1–365) to every active key — both active and generated. ## Update settings PUT /keys/api/settings Update the service's webhook URL and toggle. `webhookUrl` must be a Discord webhook. ## Discord server — connect POST /keys/api/discord/connect Bind a Discord server to this service. `guildId` and `guildName` are required. ## Discord server — disconnect POST /keys/api/discord/disconnect ## Public scripts GET /keys/api/scripts List the service's Discord-visible scripts with ready-to-run loadstrings (built for VSS or Kryptic Vault automatically). ## Blacklist — list GET /keys/api/blacklist Paginated list of blacklisted HWIDs. Optional `page`, `limit`, `search`. ## Blacklist — add POST /keys/api/blacklist Add an HWID. `reason` and `expiresAt` are optional (omit `expiresAt` for a permanent ban). ## Blacklist — remove DELETE /keys/api/blacklist ## Blacklist — check GET /keys/api/blacklist/check Check whether a single `hwid` is currently blacklisted. --- API Reference # URL Shortener API Create short links that route through your checkpoint flow before reaching the destination. Full request & response examples in your dashboard You're viewing the public API reference. Sign in and open Documentation → API Reference in your dashboard for copy-paste curl requests and live response examples for every endpoint. ## Create a short link POST /api/v1/public/shortener/create Authenticate with the `x-api-key` header (or an `api_key` field in the body). Requires the `allowUrlShortener` permission. ## Notes - The `checkpoint` field routes the link through 1–10 checkpoints. - Links can be temporary, self-destructing after 30 minutes or after the checkpoint is completed. --- API Reference # VSS Management API Upload, list, update, and delete Virtual Storage scripts programmatically. Every endpoint uses your x-api-key header and requires the allowVss permission. Full request & response examples in your dashboard You're viewing the public API reference. Sign in and open Documentation → API Reference in your dashboard for copy-paste curl requests and live response examples for every endpoint. ## Upload a script POST /api/v1/vss/api/scripts `obfuscationType` is one of `NONE`, `IB1`, `LURAPH`, or `WYNFUSCATOR`. Max script size is 40 MB. ## List scripts GET /api/v1/vss/api/scripts Paginated. Optional `page`, `limit`, `search`. ## Get loadstring GET /api/v1/vss/api/scripts/:idOrSlug/loadstring `:idOrSlug` is the script's UUID or its name. ## Update a script PUT /api/v1/vss/api/scripts/:idOrSlug Re-upload code or change settings. Only the fields you send are changed. ## Delete a script DELETE /api/v1/vss/api/scripts/:idOrSlug --- API Reference # Account Limits API Validate a key while enforcing a per-key account cap. Requires Multi-Account enabled on the service. Full request & response examples in your dashboard You're viewing the public API reference. Sign in and open Documentation → API Reference in your dashboard for copy-paste curl requests and live response examples for every endpoint. ## Validate with account POST /keys/validate-account Authenticated by `ServiceID` + `Key` in the body (no X-API-Key header). Pass a stable `AccountID` (for Roblox, the player's `UserId`). Omit `HWID` only if HWID verification is disabled. ## Success response - `Max_Accounts` — the account cap (honoring per-key overrides). - `Current_Accounts` — accounts already bound. - `Account_Slots` — slots remaining (`0` = full). ## Failure response When the cap is reached, validation fails: Check `Authenticated_Status`. Grant access only on `"Success"`, and on `"Failed"` show the `Note` to the user.