Skip to content

Admin Endpoints

All admin endpoints require either adminSecret (super admin) or an apiKey scoped to your products. See API Overview for delivery methods.


Create License

Creates a new license and returns the generated license key.

POST /createLicense

Request

{
  "adminSecret": "your_secret",
  "email": "user@example.com",
  "productId": "prod_abc123",
  "variant": "pro",
  "maxMachines": 3,
  "maxConcurrent": 1,
  "licenseType": "per-machine",
  "expiresAt": "2026-01-01T00:00:00Z",
  "discountCode": "SALE50",
  "purchaseId": "gum_txn_xyz",
  "bundleId": "bundle_suite",
  "unlockedProducts": ["prod_abc123", "prod_def456"]
}
Parameter Type Required Description
email string Yes Customer email address
productId string Yes Product to license
variant string No Variant name (e.g. pro, studio). Defaults to "indie".
maxMachines number No Maximum simultaneous activations. Defaults to 2.
maxConcurrent number No Max concurrent floating sessions. Floating licenses only.
licenseType string No per-machine, floating, or site. Defaults to "per-machine".
expiresAt string No ISO 8601 expiry timestamp. Omit for perpetual licenses.
discountCode string No Discount code applied at purchase time.
purchaseId string No External transaction ID (e.g. Gumroad sale ID).
bundleId string No Bundle identifier for group purchases.
unlockedProducts array No List of product IDs unlocked by a bundle license.

Success Response 200

{
  "success": true,
  "licenseKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Errors

Status Cause
400 Missing email or productId
404 productId does not belong to your API key scope

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/createLicense",
    json={
        "adminSecret": "your_secret",
        "email": "user@example.com",
        "productId": "prod_abc123",
        "variant": "pro",
        "maxMachines": 3,
    },
)
license_key = resp.json()["licenseKey"]
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/createLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "email": "user@example.com",
    "productId": "prod_abc123",
    "variant": "pro",
    "maxMachines": 3
  }'

Get License

Returns full license details including all machine activations and any recorded violations.

GET /getLicense or POST /getLicense

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX"
}
Parameter Type Required Description
licenseKey string Yes License key to look up

Success Response 200

{
  "success": true,
  "license": {
    "key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "email": "user@example.com",
    "productId": "prod_abc123",
    "variant": "indie",
    "licenseType": "per-machine",
    "status": "active",
    "maxMachines": 2,
    "createdAt": "2024-01-01T00:00:00Z",
    "purchasedAt": "2024-01-01T00:00:00Z",
    "expiresAt": null
  },
  "activations": [
    {
      "fingerprint": "sha256-of-machine-id",
      "hostname": "my-workstation",
      "firstSeen": "2024-06-01T00:00:00Z",
      "lastSeen": "2024-06-15T00:00:00Z",
      "tokenExpiry": "2024-07-15T00:00:00Z",
      "sessionStarted": null,
      "countries": ["US"],
      "lastCountry": "US",
      "sessionActive": false
    }
  ],
  "violations": []
}

Errors

Status Cause
400 Missing licenseKey
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/getLicense",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    },
)
data = resp.json()
print(data["activations"])
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/getLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX"
  }'

List Licenses

Returns a filtered list of licenses. All filter parameters are optional.

GET /listLicenses or POST /listLicenses

Request

{
  "adminSecret": "your_secret",
  "productId": "prod_abc123",
  "email": "user@example.com",
  "status": "active",
  "limit": 50
}
Parameter Type Required Description
productId string No Filter by product
email string No Filter by customer email
status string No Filter by status: active, revoked, expired
limit number No Maximum results to return. Defaults to 100.

Success Response 200

{
  "success": true,
  "licenses": [
    {
      "key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "email": "user@example.com",
      "productId": "prod_abc123",
      "variant": "indie",
      "status": "active",
      "maxMachines": 2,
      "createdAt": "2024-01-01T00:00:00Z"
    }
  ],
  "count": 1
}

Errors

Status Cause
400 API key user has more than 30 products and no productId filter was provided
401 Invalid or missing auth credential

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/listLicenses",
    json={
        "adminSecret": "your_secret",
        "productId": "prod_abc123",
        "status": "active",
        "limit": 50,
    },
)
data = resp.json()
print(f"{data['count']} licenses found")
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/listLicenses \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "productId": "prod_abc123",
    "status": "active",
    "limit": 50
  }'

Update License

Updates mutable fields on an existing license.

POST /updateLicense

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX",
  "variant": "studio",
  "licenseType": "per-machine",
  "maxMachines": 5,
  "maxConcurrent": 3,
  "expiresAt": "2027-01-01T00:00:00Z",
  "status": "active"
}
Parameter Type Required Description
licenseKey string Yes License key to update
variant string No New variant name
licenseType string No New license type: per-machine, floating, or site
maxMachines number No New machine activation limit
maxConcurrent number No New concurrent session limit (floating licenses)
expiresAt string No New expiry timestamp. Pass null to make perpetual.
status string No Override status directly: active or revoked

Success Response 200

{
  "success": true
}

Errors

Status Cause
400 Missing licenseKey
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/updateLicense",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
        "maxMachines": 5,
        "expiresAt": "2027-01-01T00:00:00Z",
    },
)
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/updateLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    "maxMachines": 5,
    "expiresAt": "2027-01-01T00:00:00Z"
  }'

Revoke License

Marks a license as revoked. Revoked licenses are denied at all client endpoints.

POST /revokeLicense

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX",
  "reason": "refund"
}
Parameter Type Required Description
licenseKey string Yes License key to revoke
reason string No Reason for revocation: refund, chargeback, or fraud

Success Response 200

{
  "success": true
}

Errors

Status Cause
400 Missing licenseKey
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/revokeLicense",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
        "reason": "refund",
    },
)
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/revokeLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    "reason": "refund"
  }'

Reinstate License

Reinstates a previously revoked license, setting its status back to active.

POST /reinstateLicense

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX"
}
Parameter Type Required Description
licenseKey string Yes License key to reinstate

Success Response 200

{
  "success": true
}

Errors

Status Cause
400 Missing licenseKey
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/reinstateLicense",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    },
)
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/reinstateLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX"
  }'

Resolve Violations

Marks specific violations as resolved, recalculating the license threat level and status.

POST /resolveLicense

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX",
  "violationIds": ["viol_001", "viol_002"]
}
Parameter Type Required Description
licenseKey string Yes License key containing the violations
violationIds array Yes IDs of violations to mark as resolved

Success Response 200

{
  "success": true,
  "threatLevel": 0,
  "status": "active"
}

Errors

Status Cause
400 Missing licenseKey or violationIds
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/resolveLicense",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
        "violationIds": ["viol_001", "viol_002"],
    },
)
data = resp.json()
print(f"Threat level now: {data['threatLevel']}")
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/resolveLicense \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    "violationIds": ["viol_001", "viol_002"]
  }'

Reset Activations

Removes all machine activations from a license, freeing all slots. Useful for customer support when a user has lost access to their machines.

POST /resetActivations

Request

{
  "adminSecret": "your_secret",
  "licenseKey": "XXXX-XXXX-XXXX-XXXX"
}
Parameter Type Required Description
licenseKey string Yes License key to reset

Success Response 200

{
  "success": true,
  "deletedCount": 2
}

Errors

Status Cause
400 Missing licenseKey
401 Invalid or missing auth credential
404 License not found

Examples

import requests

resp = requests.post(
    "https://us-central1-cg-license-server.cloudfunctions.net/resetActivations",
    json={
        "adminSecret": "your_secret",
        "licenseKey": "XXXX-XXXX-XXXX-XXXX",
    },
)
data = resp.json()
print(f"Cleared {data['deletedCount']} activation(s)")
curl -s -X POST \
  https://us-central1-cg-license-server.cloudfunctions.net/resetActivations \
  -H "Content-Type: application/json" \
  -d '{
    "adminSecret": "your_secret",
    "licenseKey": "XXXX-XXXX-XXXX-XXXX"
  }'