Quick Start

This guide will walk you through creating your first organization, product, and license, then validating it from your application.

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

  • A GeckoGuard account (Sign up here)
  • An API key (created in your dashboard)

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 using the authorization endpoint. This endpoint requires an API key with license:authorize permission and a signed request (HMAC-SHA256 over a canonical string — see the signing recipe, or use one of the official SDKs which handle signing for you):

const response = await fetch('https://api.geckoguard.net/v1/licenses/authorize', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    productId: 'your-product-id',
    licenseKey: 'LICENSE-KEY-123',
    hwid: 'device-hardware-id',   // Optional: for hardware binding
    ip: '192.168.1.1',            // Optional: for IP restrictions
    deviceId: 'device-uuid',      // Optional: device identifier
    sessionId: 'unique-session',  // Optional: for concurrency limits
    dryRun: false                 // Optional: test without persisting changes
  })
});

const result = await response.json();
if (result.allow) {
  console.log('License is valid!');
  console.log('Expires at:', result.effectiveExpiresAt);
  console.log('Remaining limits:', result.limits.remaining);
} else {
  console.error('Denied:', result.reasonCode, result.message);
}

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_MISMATCH",
  "message": "Hardware ID does not match bound device"
}

Next Steps