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 prefixCredentialHeader
POST /v1/licenses/authorizeAPI key + HMAC signatureX-Api-Key + X-GG-*
GET /v1/whoami, /v1/products/:id/api-keysAPI keyX-Api-Key
/v1/products/:productId/* (recommended for backend integrations)API key with management scopesX-Api-Key
/v1/dashboard/* (used by the web UI)JWT access token from /v1/auth/loginAuthorization: Bearer <accessToken>
/v1/auth/*, /v1/status, /healthnone (public)
/v1/enduser/*end-user JWTAuthorization: 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 return 401 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/json header 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
ParamDefaultNotes
page11-indexed
pageSizeendpoint-specific (typically 50)Max varies by endpoint

Per-endpoint pageSize ceilings:

EndpointMax pageSize
GET /v1/dashboard/orgs/:orgId/licenses1000
GET /v1/dashboard/licenses1000
GET /v1/dashboard/orgs/:orgId/end-users100
Other list endpointstypically 100200, 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:

MethodEndpointAuthReturns
GET/v1/whoamiAPI key{ apiKeyId, productId }
GET/v1/dashboard/meJWT{ user, orgs, activeOrgId }

Auth — for backend integrators

The three endpoints a bot or backend script actually calls:

MethodEndpointDescription
POST/v1/auth/loginExchange email + password for an access + refresh token pair. Returns a 2FA challenge if the account has TOTP enabled.
POST/v1/auth/refreshSingle-use rotation: exchange a refresh token for a new access + refresh pair.
POST/v1/auth/logoutRevoke 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-login exist 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

MethodEndpointDescription
POST/v1/licenses/authorizeValidate 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-Key and authorize against the scopes on the key. No login flow, no refresh tokens. See Backend Quickstart for a 5-minute curl walkthrough.

MethodEndpointRequired scope
GET/v1/products/:productId/licenseslicense:read
GET/v1/products/:productId/licenses/:licenseIdlicense:read
POST/v1/products/:productId/licenseslicense:create
PATCH/v1/products/:productId/licenses/:licenseIdlicense:update
DELETE/v1/products/:productId/licenses/:licenseIdlicense:delete
POST/v1/products/:productId/licenses/:licenseId/revokelicense:revoke
POST/v1/products/:productId/licenses/:licenseId/unrevokelicense:unrevoke
POST/v1/products/:productId/licenses/:licenseId/reset-hwidlicense:reset_hwid
POST/v1/products/:productId/licenses/:licenseId/reset-iplicense:reset_ip
GET/v1/products/:productId/blacklistsblacklist:read
POST/v1/products/:productId/blacklistsblacklist:write
DELETE/v1/products/:productId/blacklists/:entryIdblacklist:write
GET/v1/products/:productId/end-usersend_user:read
GET/v1/products/:productId/end-users/:endUserIdend_user:read
GET/v1/end-usersend_user:read
GET/v1/end-users/:endUserIdend_user:read
GET/v1/products/:productId/analyticsanalytics:read

End-user lookups come in two flavors. /v1/end-users searches across every product in the API key's org — useful for a unified Discord bot that handles all your products. /v1/products/:productId/end-users is 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/licenses and …/licenses/:licenseId return endUserId, endUserUsername, endUserEmail (each null when unassigned) — but only when the API key has the end_user:read scope. 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

MethodEndpointDescription
GET/v1/dashboard/orgsList your organizations
POST/v1/dashboard/orgsCreate an organization
GET/v1/dashboard/orgs/:orgIdGet organization details
PATCH/v1/dashboard/orgs/:orgIdUpdate organization
DELETE/v1/dashboard/orgs/:orgIdDelete organization

Products

MethodEndpointDescription
POST/v1/dashboard/productsCreate a product
GET/v1/dashboard/products/:idGet product details
PATCH/v1/dashboard/products/:idUpdate product (name, policy)
DELETE/v1/dashboard/products/:idDelete product
GET/v1/dashboard/orgs/:orgId/productsList products in an org
POST/v1/dashboard/orgs/:orgId/productsAdd product to org
DELETE/v1/dashboard/orgs/:orgId/products/:productIdRemove product from org

Licenses

Detailed documentation with examples

MethodEndpointDescription
GET/v1/dashboard/orgs/:orgId/licensesList licenses (filterable by product, status, search)
POST/v1/dashboard/orgs/:orgId/licensesCreate license(s) — supports bulk creation up to 500
GET/v1/dashboard/orgs/:orgId/licenses/analyticsLicense analytics (counts by status, product)
GET/v1/dashboard/orgs/:orgId/licenses/expiringList licenses expiring soon
GET/v1/dashboard/orgs/:orgId/licenses/exportExport licenses as CSV or JSON
POST/v1/dashboard/orgs/:orgId/licenses/importBulk import licenses
POST/v1/dashboard/orgs/:orgId/licenses/freezeBulk freeze licenses
POST/v1/dashboard/orgs/:orgId/licenses/unfreezeBulk unfreeze licenses
POST/v1/dashboard/orgs/:orgId/licenses/revokeBulk revoke licenses
POST/v1/dashboard/orgs/:orgId/licenses/unrevokeBulk restore revoked licenses
POST/v1/dashboard/orgs/:orgId/licenses/extendBulk extend license expiry
DELETE/v1/dashboard/orgs/:orgId/licensesBulk delete licenses

Per-License Endpoints (via dashboard)

MethodEndpointDescription
GET/v1/dashboard/licenses/:idGet single license details
PATCH/v1/dashboard/licenses/:idUpdate license (status, expiry, policy, freeze)
POST/v1/dashboard/licenses/:id/revokeRevoke a license
POST/v1/dashboard/licenses/:id/unrevokeRestore a revoked license
POST/v1/dashboard/licenses/:id/reset-hwidReset HWID bindings
POST/v1/dashboard/licenses/:id/reset-ipReset IP bindings
POST/v1/dashboard/licenses/redeemRedeem a license key

Sessions

MethodEndpointDescription
GET/v1/dashboard/licenses/:id/sessionsList active sessions for a license
POST/v1/dashboard/licenses/:id/sessions/:sessionId/revokeKill a specific session
POST/v1/dashboard/licenses/:id/sessions/revoke-allKill all sessions for a license

API Keys

MethodEndpointDescription
POST/v1/dashboard/api-keysCreate an API key (with optional permissions)
GET/v1/dashboard/api-keys?productId=List API keys for a product
PATCH/v1/dashboard/api-keys/:idUpdate API key (name, permissions)
DELETE/v1/dashboard/api-keys/:idDelete an API key
POST/v1/dashboard/api-keys/:id/rotateRotate an API key secret
POST/v1/dashboard/api-keys/:id/revokeRevoke an API key

Blacklists

MethodEndpointDescription
GET/v1/dashboard/blacklists/products/:productIdList blacklist entries (filter by type: HWID or IP)
POST/v1/dashboard/blacklists/products/:productIdAdd a blacklist entry
POST/v1/dashboard/blacklists/products/:productId/bulkBulk add blacklist entries
DELETE/v1/dashboard/blacklists/products/:productId/:entryIdRemove 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> is HMAC-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.

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