Webhooks

Webhooks let you receive real-time HTTP notifications when events happen in GeckoGuard — license authorizations, revocations, team changes, and more.

Supported Events

EventTrigger
license.createdA new license is created
license.revokedA license is revoked
license.unrevokedA revoked license is restored
license.expiredA license expires
license.authorizedA license is successfully validated
license.authorization_deniedA license validation is denied
license.hwid_resetHWID bindings are reset
license.ip_resetIP bindings are reset
license.frozenA license is frozen
license.unfrozenA license is unfrozen
api_key.createdAn API key is created
api_key.revokedAn API key is revoked
api_key.rotatedAn API key is rotated
team.member_addedA team member is added
team.member_removedA team member is removed

Managing Webhook Endpoints

Create an Endpoint

const response = await fetch('/v1/dashboard/webhooks/products/PRODUCT_ID', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://your-server.com/webhooks/geckoguard',
    events: ['license.authorized', 'license.revoked', 'license.expired'],
    enabled: true
  })
});

const { data } = await response.json();
// data.endpoint.secret = 'whsec_...' — save this for signature verification!

The response includes a secret — store it securely. You'll use it to verify webhook signatures.

Update an Endpoint

PATCH /v1/dashboard/webhooks/products/:productId/:endpointId

Update the URL, events list, or enabled state.

Delete an Endpoint

DELETE /v1/dashboard/webhooks/products/:productId/:endpointId

View Delivery History

GET /v1/dashboard/webhooks/products/:productId/:endpointId/deliveries?limit=50

Returns recent delivery attempts with status, success flag, and error messages.

Send a Test Event

POST /v1/dashboard/webhooks/products/:productId/:endpointId/test

Sends a test.ping event to verify your endpoint is working.

Webhook Payload Format

{
  "event": "license.authorized",
  "data": {
    "licenseId": "license-uuid",
    "productId": "product-uuid",
    "wasActivated": false,
    "effectiveExpiresAt": "2025-12-31T23:59:59.000Z"
  },
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Signature Verification

Every webhook request includes an HMAC-SHA256 signature in the X-GeckoGuard-Signature header. Verify it to ensure the request is authentic:

const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express example
app.post('/webhooks/geckoguard', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-geckoguard-signature'];
  const body = req.body.toString();

  if (!verifyWebhook(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(body);
  console.log('Received:', event.event, event.data);

  res.status(200).send('OK');
});

Request Headers

HeaderDescription
Content-Typeapplication/json
X-GeckoGuard-SignatureHMAC-SHA256 signature of the body
X-GeckoGuard-EventEvent type (e.g., license.authorized)
User-AgentGeckoGuard-Webhooks/1.0

Delivery Behavior

  • Webhook requests have a 10-second timeout
  • A 2xx response is considered successful
  • Failed deliveries are recorded with the error message
  • Delivery history is available via the dashboard API

Best Practices

  1. Always verify signatures — reject unsigned or invalid requests
  2. Respond quickly — return 200 immediately, process asynchronously if needed
  3. Handle duplicates — use idempotent processing in case of retries
  4. Subscribe only to events you need — reduces noise and load
  5. Monitor delivery history — check for failing endpoints regularly
  6. Use the test endpoint — verify your handler works before going live