Webhooks
Webhooks let you receive real-time HTTP notifications when events happen in GeckoGuard — license authorizations, revocations, team changes, and more.
Supported Events
| Event | Trigger |
|---|---|
license.created | A new license is created |
license.revoked | A license is revoked |
license.unrevoked | A revoked license is restored |
license.expired | A license expires |
license.authorized | A license is successfully validated |
license.authorization_denied | A license validation is denied |
license.hwid_reset | HWID bindings are reset |
license.ip_reset | IP bindings are reset |
license.frozen | A license is frozen |
license.unfrozen | A license is unfrozen |
api_key.created | An API key is created |
api_key.revoked | An API key is revoked |
api_key.rotated | An API key is rotated |
team.member_added | A team member is added |
team.member_removed | A 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
| Header | Description |
|---|---|
Content-Type | application/json |
X-GeckoGuard-Signature | HMAC-SHA256 signature of the body |
X-GeckoGuard-Event | Event type (e.g., license.authorized) |
User-Agent | GeckoGuard-Webhooks/1.0 |
Delivery Behavior
- Webhook requests have a 10-second timeout
- A
2xxresponse is considered successful - Failed deliveries are recorded with the error message
- Delivery history is available via the dashboard API
Best Practices
- Always verify signatures — reject unsigned or invalid requests
- Respond quickly — return
200immediately, process asynchronously if needed - Handle duplicates — use idempotent processing in case of retries
- Subscribe only to events you need — reduces noise and load
- Monitor delivery history — check for failing endpoints regularly
- Use the test endpoint — verify your handler works before going live