Developers
Webhooks
Receive real-time HTTP notifications when records change. No polling required.
Overview
When you register a webhook endpoint, we'll send an HTTP POST to your URL every time a matching event occurs. Payloads are JSON with HMAC-SHA256 signatures for verification.
Events
| Event | Fires When |
|---|---|
receipt.created | A new firearm is acquired (via web UI or API) |
receipt.updated | A receipt record is edited |
receipt.disposed | A disposition is recorded (sale/transfer) |
receipt.deleted | A record is soft-deleted |
ping | Test event sent when you click "Test" in the dashboard |
* | Subscribe to all events |
Registering Endpoints
Via Dashboard: Go to Dashboard > Webhooks > Add Endpoint. Select which events to receive.
Via API:
POST /rest/v1/webhooks
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"url": "https://your-pos.com/webhooks/lbfg",
"events": ["receipt.created", "receipt.disposed"]
}
// Response includes the signing secret:
{
"data": { "id": 1, "url": "...", "events": [...] },
"secret": "whsec_abc123..."
}
Payload Format
{
"event": "receipt.created",
"timestamp": "2026-04-01T14:30:00-07:00",
"data": {
"id": 12345,
"user_id": 42,
"record": 157,
"book": "Handguns",
"receipt_date": "2026-04-01",
"manufacturer": "Glock",
"model": "G19 Gen5",
"serial_number": "ABCD1234",
"type": "Pistol",
"caliber": "9mm",
"received_from": "Acme Firearms",
...
}
}
Headers
| Header | Description |
|---|---|
X-LBFG-Event | Event name (e.g., receipt.created) |
X-LBFG-Signature | HMAC-SHA256 signature: sha256=HMAC(secret, body) |
X-LBFG-Delivery | Unique delivery ID for deduplication |
Content-Type | application/json |
User-Agent | LogbooksForGuns-Webhook/1.0 |
Signature Verification
Always verify the signature to ensure the webhook came from us. Your signing secret is shown once when you create the endpoint.
PHP Example:
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_LBFG_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $your_secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
Node.js Example:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = 'sha256=' +
crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature), Buffer.from(expected)
);
}
Retry Policy
If your endpoint returns a non-2xx response or times out (5 second limit), we retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
After 10 consecutive failures, the endpoint is automatically disabled. You can re-enable it from the dashboard.
Managing Webhooks via API
| Method | Endpoint | Description |
|---|---|---|
GET | /rest/v1/webhooks | List your webhook endpoints |
POST | /rest/v1/webhooks | Create a new endpoint |
DELETE | /rest/v1/webhooks/{id} | Delete an endpoint |
Best Practices
- Always verify the
X-LBFG-Signatureheader - Respond with
200quickly — process the payload asynchronously - Use the
X-LBFG-Deliveryheader to deduplicate events - Store the signing secret securely (treat it like a password)
- Handle
pingevents to verify connectivity