> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vampauth.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Snippets

> Copy-paste examples for the validation API.

export const CopyPrompt = () => {
  const [copied, setCopied] = useState(false);
  const prompt = "Give me a minimal, correct snippet integrating Vampauth key/check in the environment the user names (Roblox executor, Node, Python, C#, Lua). It must: compute a hardware id by mixing several signals (persisted per-machine storage such as rblxanalytics-backed storage, executor fingerprints/install id, and runtime signals like platform and resolution), hash or encrypt the combined string so the inputs are not readable, send a POST to the API with X-Project-Key, verify the Ed25519 signature over the documented payload using the project's Public Signing Key, and gate the script body behind the verification. No extra features, no dead code, keep it under 40 lines.";
  const copy = async () => {
    try {
      await navigator.clipboard.writeText(prompt);
    } catch {
      const t = document.createElement("textarea");
      t.value = prompt;
      document.body.appendChild(t);
      t.select();
      document.execCommand("copy");
      document.body.removeChild(t);
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
  return <div className="not-prose my-4 flex items-center justify-between gap-3 rounded-lg border border-zinc-200 px-4 py-2.5 dark:border-zinc-800">
      <span className="text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400">AI prompt</span>
      <button onClick={copy} className="cursor-pointer rounded border border-zinc-300 px-2.5 py-1 text-xs font-semibold text-zinc-700 hover:bg-zinc-100 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800">{copied ? "Copied" : "Copy"}</button>
    </div>;
};

# Integration Snippets

There is no SDK. Your script talks to the REST API directly. These snippets are the starting point for any executor or language.

## Minimal check (pseudo-code)

```
POST /api/v1/key/check
  header X-Project-Key: pk-...
  body   { key, hwid, nonce }

if status 200:
  verify signature over nonce_echo | hwid | expires_at_unix | project_id
  if valid -> run script
else:
  read { error, message } and exit
```

## Hardware ID

HWID is passthrough — Vampauth only compares equality. The quality of the fingerprint is on you. A single weak value is easy to spoof, so combine several signals into one fingerprint:

* **Persisted storage** — Roblox offers per-machine storage that survives the session (e.g. `rblxanalytics`-backed storage). Store a random identifier there once and reuse it; this is stable across sessions and hard to reset from the script alone.
* **Executor fingerprint** — your executor (Synapse, Wave, etc.) exposes APIs or memory patterns that are unique to the current install. Hash whatever is available.
* **Runtime signals** — things an attacker would have to reproduce exactly: platform, executor version, Roblox client build, display resolution, locale.

Mix them, then obfuscate so a forger cannot read which parts matter:

```lua theme={null}
local storage = rblxanalytics_storage_get("vampauth_hwid") -- persisted per machine
if not storage then
  storage = random_id()
  rblxanalytics_storage_set("vampauth_hwid", storage)
end

local raw = storage
  .. "|" .. tostring(executor_api and executor_api.get_install_id() or "")
  .. "|" .. gethwid()          -- executor-provided machine id, when available
  .. "|" .. platform          -- e.g. "windows"
  .. "|" .. tostring(game:GetService("GuiService"):GetScreenResolution().X)

local hwid = sha256(raw) -- single opaque string to send as "hwid"
```

Encrypt or key-hash the combined string so the forger cannot strip out individual signals:

* `sha256(raw)` — simple, opaque, but the inputs are still guessable.
* `hmac(raw, secret_key)` — a secret baked into your script (and obfuscated) makes the fingerprint worthless without the key.
* `encrypt(raw)` — a real cipher over the concatenated fields; reversing it requires the key.

Keep the fingerprint stable across calls for the same machine, and regenerated if the user's hardware/executor changes. Vampauth never sees the components — just the final string.

## Nonce

A nonce is a random value you generate once per call. The server never stores it — it only echoes it back (`nonce_echo`) and includes it in the signature payload (`sha256(nonce|hwid|expiresAtUnix|project_id)`).

* Any string works, up to 128 characters.
* It must be **fresh and random on every call**. This is what makes replay protection work: if an attacker captures a valid response, the client's next call uses a different nonce, so the captured signature no longer verifies.
* The client must check that `nonce_echo` matches the nonce it sent (and the signature verifies) before trusting the response.

A nonce that is reused or predictable defeats the whole mechanism — an attacker can replay a captured `valid` response unchanged.

## curl

```bash theme={null}
curl -X POST https://vampauth.com/api/v1/key/check \
  -H "X-Project-Key: pk-..." \
  -H "Content-Type: application/json" \
  -d '{"key":"DP3P-YDMA-NJDI-HJJC","hwid":"my-hwid","nonce":"abc123"}'
```

## Follow the contract

* [Authentication](/rest-api/authentication)
* [key/check](/rest-api/key-check)
* [Signature verification](/rest-api/signature-verification)

<CopyPrompt id="integration-snippets" />
