Documentation

← Panda Auth

For Developers · Libraries

PUSL-V4

Panda-Unified Security Libraries V4 — an HTTP-only authentication SDK combining V4.3-Cookies and V4-HyperGuard. No WebSocket, built for mobile executors including Delta Android.

When to use it

PUSL-V4 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

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

PUSL.configure({
    serviceId    = "YOUR_SERVICE_ID",
    debug        = false,
    kickOnDetect = false,
})

3. Validate

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

-- 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.
-- 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

Using the Kryptic Vault?

You do not load PUSL-V4 yourself — it is built into the Vault loader as PandaAuthV4. Your uploaded script just calls it:

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:

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"

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.