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

# key/activate

> Validate a key from the injected Vampauth launcher. Simplified contract for SDK scripts.

export const CopyPrompt = () => {
  const [copied, setCopied] = useState(false);
  const prompt = "Write a client call to Vampauth POST /api/v1/key/activate for SDK-injected scripts. Headers must include X-Vampauth-Injected: 1, X-Vampauth-Nonce (random <=64 chars), X-Vampauth-Signature = HMAC_SHA1(auth_secret, nonce|key|hwid). Body: { project_id, auth: auth_secret, key, hwid, executor? }. On 200 expect { status: 'valid', hwid_bound, expires_at, signature, project_id }. Non-2xx returns { status: 'invalid', reason }. Reasons: invalid_request, invalid/bad_auth, bad_signature, forbidden, rate_limited, key_not_found, key_banned, key_expired, hwid_banned, fingerprint_mismatch, internal_error. Fail closed. Under 25 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>;
};

# key/activate

Activation endpoint called by the Vampauth launcher injected into [SDK-mode scripts](/platform/scripts). It runs the same validation ladder as [key/check](/rest-api/key-check) — not found, banned, expired, project HWID ban, fingerprint mismatch — persists usage stats and lazy HWID binding, and returns a launcher-friendly body.

You normally never call this yourself: scripts saved in **Vampauth SDK** mode ship it built in. Use [key/check](/rest-api/key-check) for your own clients or [Custom SDK](/platform/scripts) scripts.

## Request

`POST /api/v1/key/activate`

`Content-Type: application/json`. Only accepted from injected launcher builds.

**Headers**

| Header                 | Required | Notes                                                      |
| ---------------------- | -------- | ---------------------------------------------------------- |
| `X-Vampauth-Injected`  | yes      | Must be `1`. Requests without it get `403`.                |
| `X-Vampauth-Nonce`     | yes      | Random value, at most 64 chars. Fresh per call.            |
| `X-Vampauth-Signature` | yes      | `HMAC_SHA1(auth_secret, nonce\|key\|hwid)`, lowercase hex. |

**Body**

| Field        | Type   | Required | Notes                                                      |
| ------------ | ------ | -------- | ---------------------------------------------------------- |
| `project_id` | string | yes      | Your public project ID.                                    |
| `auth`       | string | yes      | The project's auth secret, echoed. Compared timing-safely. |
| `key`        | string | yes      | The license key to validate.                               |
| `hwid`       | string | yes      | Hardware ID from the client. Passthrough.                  |
| `executor`   | string | no       | Plain executor label. Max 64 chars.                        |

```json theme={null}
{
  "project_id": "2Q9V222NTI2WJ45N",
  "auth": "c3499ac4ae2f5ca6715e9ee04cfe542aa5070593d6fa6341",
  "key": "A13A-6D58-A93C-6AC7",
  "hwid": "delta-live-test-hwid",
  "executor": "Delta"
}
```

## Success response

HTTP 200:

```json theme={null}
{
  "status": "valid",
  "hwid_bound": true,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "signature": "7138f26fdda7f37abf453c67fe5675daca003490",
  "project_id": "61b4a242-e6b3-4765-aefb-23904d92d984"
}
```

The launcher only runs your script when `status` is `valid`.

## Errors

Every non-2xx returns `{ "status": "invalid", "reason": "..." }`. The launcher maps reasons to its configured failure action (`kick`, `console`, or `silent`).

| HTTP | `reason`               | Meaning                                              |
| ---- | ---------------------- | ---------------------------------------------------- |
| 400  | `invalid_request`      | Missing/malformed body field.                        |
| 401  | `bad_auth`             | Body `auth` doesn't match the project's auth secret. |
| 401  | `bad_signature`        | Header signature doesn't match — tampered request.   |
| 401  | `invalid`              | Unknown `project_id`.                                |
| 403  | `forbidden`            | Request didn't come from an injected launcher build. |
| 403  | `key_banned`           | Key is banned or revoked.                            |
| 403  | `fingerprint_mismatch` | Key is bound to different hardware and isn't FFA.    |
| 403  | `hwid_banned`          | This device is banned from the project.              |
| 404  | `key_not_found`        | No such key on this project.                         |
| 410  | `key_expired`          | Key has expired.                                     |
| 429  | `rate_limited`         | Over 120 req / 60s per IP.                           |
| 500  | `internal_error`       | Unexpected server error.                             |

<CopyPrompt id="key-activate" />
