API reference

Public and dashboard APIs.

Use an API key from the client dashboard for player activation. Dashboard session routes manage products, keys, licenses, and protection jobs after Discord sign-in.

Public: activate a player license

POST /api/v1/licenses/activate
Authorization: Bearer <api-key>

{ "licenseKey": string, "hwid": string }

-> 200 { key, status, hwidBound, activatedAt, productId }
-> 409 { error: "license_not_found" | "license_inactive" | "license_expired" | "hwid_mismatch" | "product_mismatch" }
-> 401 { error: "unauthorized" }
-> 400 { error: "licenseKey_and_hwid_required" }

Rate-limit this on your side as well. API keys are scoped to one of your products.

Dashboard session: customer workspace

These require a signed-in Discord browser session (same-origin cookies), not an API key.

GET  /api/customer/products
POST /api/customer/products              { name, summary? }

GET  /api/customer/api-keys
POST /api/customer/api-keys              { productId, label? }
POST /api/customer/api-keys/:id/revoke

GET  /api/customer/licenses
POST /api/customer/licenses              { productId, note?, expiresInDays? }
POST /api/customer/licenses/:id/revoke
POST /api/customer/licenses/:id/reset-hwid

Dashboard session: protection jobs

POST /api/jobs               multipart: file=.jar, productId?
GET  /api/jobs/:id
GET  /api/jobs/:id/output    protected jar when status=complete

Jobs always run the client protection profile with native bridge enabled. Uploaded jars are never executed as programs — they are input data only.

Legacy public activate

POST /api/license/activate still exists for older Phantom-owned entitlement flows. New client integrations should use /api/v1/licenses/activate with a product API key.