API Reference
The GeckoGuard API is a RESTful API that uses JSON for request and response bodies.
Base URL
All API requests should be made to:
https://api.geckoguard.net
Authentication
Different endpoints accept different credentials. The short version:
| Endpoint prefix | Credential | Header |
|---|---|---|
POST /v1/licenses/authorize | API key + HMAC signature | X-Api-Key + X-GG-* |
GET /v1/whoami, /v1/products/:id/api-keys | API key | X-Api-Key |
/v1/products/:productId/* (recommended for backend integrations) | API key with management scopes | X-Api-Key |
/v1/dashboard/* (used by the web UI) | JWT access token from /v1/auth/login | Authorization: Bearer <accessToken> |
/v1/auth/*, /v1/status, /health | none (public) | — |
/v1/enduser/* | end-user JWT | Authorization: Bearer … |
About the
/v1/dashboard/*prefix: despite the name, this is the public management API. Use it from your backend with a Bearer JWT — API keys are not accepted on dashboard routes and will return401 UNAUTHORIZED. The path is kept stable for backwards compatibility.
See the Authentication guide for the full auth matrix, the request-signing recipe for /v1/licenses/authorize, and /v1/whoami token introspection.
Request Format
Content-Type: application/jsonheader for POST/PATCH requests- JSON body for POST/PATCH requests
- Query parameters for filtering and pagination
Response Format
All responses follow this structure:
{
"ok": true,
"data": { /* response data */ }
}
Error responses:
{
"ok": false,
"error": {
"message": "Error description",
"code": "ERROR_CODE"
}
}
Pagination
List endpoints use page-based pagination. There is no cursor option today.
GET /v1/dashboard/orgs/:orgId/licenses?page=1&pageSize=50
| Param | Default | Notes |
|---|---|---|
page | 1 | 1-indexed |
pageSize | endpoint-specific (typically 50) | Max varies by endpoint |
Per-endpoint pageSize ceilings:
| Endpoint | Max pageSize |
|---|---|
GET /v1/dashboard/orgs/:orgId/licenses | 1000 |
GET /v1/dashboard/licenses | 1000 |
GET /v1/dashboard/orgs/:orgId/end-users | 100 |
| Other list endpoints | typically 100–200, see endpoint-specific docs |
Responses always include a pagination envelope with total and totalPages:
{
"ok": true,
"data": {
"licenses": [ /* … */ ],
"pagination": { "page": 1, "pageSize": 50, "total": 342, "totalPages": 7 }
}
}
Consistency is best-effort — if rows are inserted while you paginate, you may see overlap or gaps. For exact snapshots of large datasets use the export endpoints (e.g. GET /v1/dashboard/orgs/:orgId/licenses/export?format=csv), which stream the full set in a single request without paging.
Rate Limiting
Buckets are credential-dependent: API-key calls hit per-IP + per-key + per-product; JWT-only calls (/v1/dashboard/* with a Bearer token) only hit the per-IP bucket (default 120/min). A bot batching dashboard operations from one IP needs to pace below that.
/v1/licenses/authorize adds an extra 20/min per license key to make credential stuffing expensive.
429 responses return RATE_LIMITED or PRODUCT_RATE_LIMITED — always honor Retry-After. Full breakdown of buckets, defaults, and headers: Authentication → Rate limits.
Idempotency
Mutating endpoints accept an Idempotency-Key header. Replaying the same key within 24 hours returns the original response with Idempotent-Replayed: true. Mismatched bodies return 409 IDEMPOTENCY_KEY_REUSE. See Authentication → Idempotency.
Endpoints Overview
Building a backend integration? Start with the Backend Quickstart — five steps with curl that exercise the core path (login → smoke test → list IDs → create license → refresh loop). The reference below is the lookup table you'll come back to.
Token Introspection
Use these to verify a credential is valid before writing code against it:
| Method | Endpoint | Auth | Returns |
|---|---|---|---|
GET | /v1/whoami | API key | { apiKeyId, productId } |
GET | /v1/dashboard/me | JWT | { user, orgs, activeOrgId } |
Auth — for backend integrators
The three endpoints a bot or backend script actually calls:
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/auth/login | Exchange email + password for an access + refresh token pair. Returns a 2FA challenge if the account has TOTP enabled. |
POST | /v1/auth/refresh | Single-use rotation: exchange a refresh token for a new access + refresh pair. |
POST | /v1/auth/logout | Revoke the current refresh token. |
Dashboard-UI plumbing.
/v1/auth/register,/v1/auth/forgot-password,/v1/auth/reset-password,/v1/auth/verify-email,/v1/auth/totp/verify-loginexist for the GeckoGuard web UI — backend integrators don't call these directly. Sign up your service-account user via the dashboard once; after that, only the three above matter.
License Validation (API Key Auth + Signed Request)
Detailed documentation with code examples · Request signing recipe
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/licenses/authorize | Validate a license key. Requires API key with license:authorize permission AND HMAC-signed request headers (X-GG-Timestamp, X-GG-Nonce, X-GG-Signature). |
Management Endpoints (API Key + Scopes)
The recommended path for backend integrations (Discord bots, admin tools, CRMs). All routes accept
X-Api-Keyand authorize against the scopes on the key. No login flow, no refresh tokens. See Backend Quickstart for a 5-minute curl walkthrough.
| Method | Endpoint | Required scope |
|---|---|---|
GET | /v1/products/:productId/licenses | license:read |
GET | /v1/products/:productId/licenses/:licenseId | license:read |
POST | /v1/products/:productId/licenses | license:create |
PATCH | /v1/products/:productId/licenses/:licenseId | license:update |
DELETE | /v1/products/:productId/licenses/:licenseId | license:delete |
POST | /v1/products/:productId/licenses/:licenseId/revoke | license:revoke |
POST | /v1/products/:productId/licenses/:licenseId/unrevoke | license:unrevoke |
POST | /v1/products/:productId/licenses/:licenseId/reset-hwid | license:reset_hwid |
POST | /v1/products/:productId/licenses/:licenseId/reset-ip | license:reset_ip |
GET | /v1/products/:productId/blacklists | blacklist:read |
POST | /v1/products/:productId/blacklists | blacklist:write |
DELETE | /v1/products/:productId/blacklists/:entryId | blacklist:write |
GET | /v1/products/:productId/end-users | end_user:read |
GET | /v1/products/:productId/end-users/:endUserId | end_user:read |
GET | /v1/end-users | end_user:read |
GET | /v1/end-users/:endUserId | end_user:read |
GET | /v1/products/:productId/analytics | analytics:read |
End-user lookups come in two flavors.
/v1/end-userssearches across every product in the API key's org — useful for a unified Discord bot that handles all your products./v1/products/:productId/end-usersis the same shape but filtered to one product, so a key bound to product A literally cannot see product B's customers. Pick whichever matches your blast-radius preference. All three filters are case-insensitive:?username=(exact),?email=(exact),?search=(partial match across both).Owner fields on license responses.
GET /v1/products/:productId/licensesand…/licenses/:licenseIdreturnendUserId,endUserUsername,endUserEmail(eachnullwhen unassigned) — but only when the API key has theend_user:readscope. Without that scope, the fields are omitted entirely. Filter the licenses list by owner with?endUserId=<uuid>.
Every write accepts Idempotency-Key. Wrong-product calls return 403 FORBIDDEN. Missing scope returns 403 PERMISSION_DENIED with the missing scope name in the message.
Organizations
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/dashboard/orgs | List your organizations |
POST | /v1/dashboard/orgs | Create an organization |
GET | /v1/dashboard/orgs/:orgId | Get organization details |
PATCH | /v1/dashboard/orgs/:orgId | Update organization |
DELETE | /v1/dashboard/orgs/:orgId | Delete organization |
Products
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/dashboard/products | Create a product |
GET | /v1/dashboard/products/:id | Get product details |
PATCH | /v1/dashboard/products/:id | Update product (name, policy) |
DELETE | /v1/dashboard/products/:id | Delete product |
GET | /v1/dashboard/orgs/:orgId/products | List products in an org |
POST | /v1/dashboard/orgs/:orgId/products | Add product to org |
DELETE | /v1/dashboard/orgs/:orgId/products/:productId | Remove product from org |
Licenses
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/dashboard/orgs/:orgId/licenses | List licenses (filterable by product, status, search) |
POST | /v1/dashboard/orgs/:orgId/licenses | Create license(s) — supports bulk creation up to 500 |
GET | /v1/dashboard/orgs/:orgId/licenses/analytics | License analytics (counts by status, product) |
GET | /v1/dashboard/orgs/:orgId/licenses/expiring | List licenses expiring soon |
GET | /v1/dashboard/orgs/:orgId/licenses/export | Export licenses as CSV or JSON |
POST | /v1/dashboard/orgs/:orgId/licenses/import | Bulk import licenses |
POST | /v1/dashboard/orgs/:orgId/licenses/freeze | Bulk freeze licenses |
POST | /v1/dashboard/orgs/:orgId/licenses/unfreeze | Bulk unfreeze licenses |
POST | /v1/dashboard/orgs/:orgId/licenses/revoke | Bulk revoke licenses |
POST | /v1/dashboard/orgs/:orgId/licenses/unrevoke | Bulk restore revoked licenses |
POST | /v1/dashboard/orgs/:orgId/licenses/extend | Bulk extend license expiry |
DELETE | /v1/dashboard/orgs/:orgId/licenses | Bulk delete licenses |
Per-License Endpoints (via dashboard)
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/dashboard/licenses/:id | Get single license details |
PATCH | /v1/dashboard/licenses/:id | Update license (status, expiry, policy, freeze) |
POST | /v1/dashboard/licenses/:id/revoke | Revoke a license |
POST | /v1/dashboard/licenses/:id/unrevoke | Restore a revoked license |
POST | /v1/dashboard/licenses/:id/reset-hwid | Reset HWID bindings |
POST | /v1/dashboard/licenses/:id/reset-ip | Reset IP bindings |
POST | /v1/dashboard/licenses/redeem | Redeem a license key |
Sessions
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/dashboard/licenses/:id/sessions | List active sessions for a license |
POST | /v1/dashboard/licenses/:id/sessions/:sessionId/revoke | Kill a specific session |
POST | /v1/dashboard/licenses/:id/sessions/revoke-all | Kill all sessions for a license |
API Keys
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/dashboard/api-keys | Create an API key (with optional permissions) |
GET | /v1/dashboard/api-keys?productId= | List API keys for a product |
PATCH | /v1/dashboard/api-keys/:id | Update API key (name, permissions) |
DELETE | /v1/dashboard/api-keys/:id | Delete an API key |
POST | /v1/dashboard/api-keys/:id/rotate | Rotate an API key secret |
POST | /v1/dashboard/api-keys/:id/revoke | Revoke an API key |
Blacklists
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/dashboard/blacklists/products/:productId | List blacklist entries (filter by type: HWID or IP) |
POST | /v1/dashboard/blacklists/products/:productId | Add a blacklist entry |
POST | /v1/dashboard/blacklists/products/:productId/bulk | Bulk add blacklist entries |
DELETE | /v1/dashboard/blacklists/products/:productId/:entryId | Remove a blacklist entry |
Webhooks
Verifying webhook deliveries: every outbound delivery is signed with HMAC-SHA256. Header is
X-GeckoGuard-Signature-V2: t=<unixSec>,v1=<hex>, where<hex>isHMAC-SHA256(endpoint_secret, "${t}.${rawBody}"). Receivers must reject when|now − t| > 300s. Full verification recipe with per-event payloads, Node.js / Python / Go examples →
Endpoints are managed under /v1/dashboard/webhooks/products/:productId. Retry policy: up to 6 attempts with exponential backoff capped at 16 minutes. See Webhooks for the full event catalog with example payloads.
Specialized endpoints
The endpoints below aren't part of the core integrator path. Each section has its own page so the main reference stays focused — skip whichever ones don't apply to your integration.
| Page | Skip if you… |
|---|---|
| Backend Quickstart | …only validate licenses at runtime via an SDK |
| Team & Org Admin | …aren't building org-admin tooling (members, invites, role changes, ownership transfer, analytics) |
| Subscriptions & Plans | …don't sell recurring subscriptions through GeckoGuard |
| End User Portal API | …don't expose a self-service portal to your customers |
| App Variables | …don't ship configuration values per-license |
| App Versions | …don't gate app updates per-license |
| Product Files | …don't deliver downloadable files (DLLs, installers) gated by license |
See API Errors for the full error-code reference.