STAGING — non-production environment. Billing is disabled; data may be wiped at any time.

Quick Start

The fastest path creates everything needed for one real, signed authorization and shows the result in your dashboard.

Building a backend integration instead? If you're writing a Discord bot, admin tool, or any backend script that manages licenses (creates, lists, revokes) on behalf of a logged-in user — go to Backend Quickstart. That's a different (curl-first, no-SDK) path.

Prerequisites

Five-minute sandbox

  1. Sign in and create your first workspace. GeckoGuard automatically creates a sandbox product, test license, and least-privilege SDK key. If you already have an empty workspace, open Dashboard and select Create sandbox.
  2. Copy the JavaScript example immediately. The API key and signing secret are shown only once; keep them out of source control.
  3. Install the checksummed preview package using the command shown above the example, then save the copied example as quickstart.mjs and run node quickstart.mjs.
  4. Confirm the terminal prints Authorized: true.
  5. Select View authorization events in the quickstart, or open Dashboard → Analytics, and confirm the new verification appears under Recent Verification Events.

The preview package is for staging evaluation while the coordinated five-SDK 1.0.0 release is on hold. Use the API base URL included in the generated example; staging examples must call the staging API.

Manual setup

Use the steps below when you want to name and configure each resource yourself instead of using the sandbox.

Step 1: Create an Organization

Organizations are the top-level containers for your products and licenses. Each organization can have multiple team members and products.

  1. Log in to your GeckoGuard dashboard
  2. Click "Create Organization" or select an existing one
  3. Give your organization a name (e.g., "My Software Company")

Step 2: Create a Product

Products represent the software applications you want to protect with licenses.

  1. Navigate to your organization
  2. Go to the "Products" section
  3. Click "Create Product"
  4. Fill in the product details:
    • Name: Your product name (e.g., "My Desktop App")
    • Default License Policy: Configure default HWID, IP, concurrency limits, and reset budgets

Step 3: Generate an API Key

API keys authenticate your requests to the GeckoGuard API.

  1. Go to "API Keys" in your dashboard
  2. Click "Create API Key"
  3. Select the product it belongs to
  4. Optionally set permissions (e.g., license:authorize, license:read)
  5. Important: Copy the key immediately — you won't be able to see it again!

Step 4: Find your IDs

Most management endpoints take :orgId and productId in the path or body. All IDs are UUIDs — slugs aren't accepted as URL parameters.

You have two ways to find them:

From the dashboard URL. When you're inside an org, the URL looks like /dashboard/orgs/<orgId>/.... The same is true for products: /dashboard/orgs/<orgId>/products/<productId>. Copy the UUIDs straight out of the address bar.

From the API. Once you have an access token from /v1/auth/login, list everything you can see:

# List your orgs
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  https://api.geckoguard.net/v1/dashboard/orgs

# List products in an org
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.geckoguard.net/v1/dashboard/orgs/$ORG_ID/products"

# Sanity-check who you are and your role in each org
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  https://api.geckoguard.net/v1/dashboard/me

GET /v1/dashboard/me is the easiest "is my JWT working" check. For API keys, the equivalent is GET /v1/whoami with X-Api-Key.

Step 5: Create Your First License

Create a license through the dashboard UI, or programmatically via the API. Note: license-management endpoints under /v1/dashboard/* require a JWT access token, not an API key. See Authentication for the full matrix.

// Get the token first via POST /v1/auth/login (see /docs/authentication)
const response = await fetch('https://api.geckoguard.net/v1/dashboard/orgs/YOUR_ORG_ID/licenses', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    productId: 'your-product-id',
    // key: 'CUSTOM-KEY-123',    // Optional — auto-generated if omitted
    // expiresAt: null,           // Fixed expiry date (ISO 8601)
    // expiresAfterDays: 30,      // Relative expiry (days after first activation)
    // expirationMode: 'never',   // 'never' | 'fixed' | 'afterActivation' | 'both'
    // policyOverride: { ... },   // Override product default policy
    // count: 1                   // Bulk create up to 500 licenses
  })
});

const result = await response.json();
console.log('License created:', result.data);

Step 6: Validate a License

In your application, validate licenses with an official SDK. The SDK signs each request with the API key's one-time signing secret and verifies the API's signed response before returning a decision:

import { GeckoGuardClient, LicenseDeniedError } from '@geckoguard/sdk';

const gecko = new GeckoGuardClient({
  apiKey: process.env.GECKO_API_KEY,
  productId: process.env.GECKO_PRODUCT_ID,
  signingSecret: process.env.GECKO_SIGNING_SECRET,
});

try {
  const result = await gecko.authorize('LICENSE-KEY-123');
  console.log('License is valid. Expires:', result.effectiveExpiresAt);
} catch (error) {
  if (error instanceof LicenseDeniedError) {
    console.error('Denied:', error.errorCode, error.message);
  } else {
    throw error;
  }
}

Use the signing recipe only when implementing the raw HTTP protocol yourself.

Successful Response

{
  "ok": true,
  "allow": true,
  "reasonCode": "ALLOW",
  "message": "Authorization granted",
  "policy": { "summary": "Authorization granted" },
  "limits": {
    "remaining": {
      "hwid": "unlimited",
      "ip": "unlimited",
      "concurrency": "unlimited"
    }
  },
  "activatedAt": "2025-01-15T10:30:00.000Z",
  "effectiveExpiresAt": "2025-12-31T23:59:59.000Z",
  "expiresAt": "2025-12-31T23:59:59.000Z",
  "expiresAfterDays": null
}

Denied Response

{
  "ok": false,
  "allow": false,
  "reasonCode": "HWID_STICKY_VIOLATION",
  "message": "HWID is sticky - cannot bind to different HWID"
}

Next Steps