Webhooks
Receive real-time events from GrenLogger when things happen in your organization. Configure webhooks in the dashboard and verify payloads using the Standard Webhooks signature scheme.
Real-time notifications
When you activate remote logging for a user, create or delete a project, or exceed an error threshold, GrenLogger sends a signed webhook to your configured URL. Respond with 2xx within 15 seconds to acknowledge receipt.
Event types
You can subscribe to these events when creating a webhook:
remote_activation.added– Remote log activation added for a userremote_activation.removed– Remote log activation removedproject.created– New project createdproject.updated– Project updatedproject.deleted– Project deletedmember.invited– Team member invitedmember.removed– Team member removedlog.error.threshold_exceeded– Error count in last 24h exceeded tier threshold
Payload format
Webhooks follow the Standard Webhooks spec. Each request includes:
- Headers:
webhook-id,webhook-timestamp,webhook-signature - Body: JSON with
type,timestamp(ISO 8601), anddata
{
"type": "remote_activation.added",
"timestamp": "2024-01-15T14:30:00.000Z",
"data": {
"projectId": "proj_abc123",
"userId": "user_xyz789",
"expiresAt": "2024-01-16T14:30:00.000Z",
"activatedBy": "uid_owner"
}
}Verifying signatures
Use HMAC-SHA256 to verify the payload. The signed content is:
webhook-id.webhook-timestamp.raw_body
The signature header format is v1,base64_signature. Use your webhook secret (shown once when creating the webhook) to compute the HMAC and compare with constant-time comparison.
Example: Node.js verification
const crypto = require('crypto');
function verifyWebhook(payload, headers, secret) {
const webhookId = headers['webhook-id'];
const timestamp = headers['webhook-timestamp'];
const signature = headers['webhook-signature'];
if (!webhookId || !timestamp || !signature) return false;
const signedContent = webhookId + '.' + timestamp + '.' + payload;
const rawSecret = Buffer.from(secret.replace(/^whsec_/, '').replace(/-/g, '+').replace(/_/g, '/'), 'base64');
const expected = 'v1,' + crypto.createHmac('sha256', rawSecret).update(signedContent).digest('base64');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Best practices
- Respond with 2xx within 10–15 seconds to avoid retries
- Use the
webhook-idas an idempotency key to avoid processing duplicates - Verify
webhook-timestampis within a few minutes to prevent replay attacks - Process webhooks asynchronously (queue and respond quickly)
Setup
- Go to your project in the dashboard
- Open the Webhooks section
- Add a webhook URL (HTTPS required)
- Select the events you want to receive
- Save the secret shown once—you will need it to verify signatures
Configure webhooks
Webhooks are available on Expert and higher plans.