Webhooks
Webhooks allow you to receive real-time notifications when events occur in your Bookmark Manager account. You can configure webhooks to send data to your application or service whenever a bookmark is created, updated, deleted, or when bulk operations occur.
Creating Webhooks
You can create webhooks in your integration settings. Each webhook requires:
- URL - The endpoint that will receive webhook payloads
- Event type - The specific event you want to listen for
- Description (optional) - A note to help you identify the webhook's purpose
You can also generate a signing secret when creating a webhook. This allows you to verify that webhook requests are coming from Bookmark Manager.
Event Types
The following event types are available for webhooks:
Single Bookmark Events
bookmark.created
- Triggered when a bookmark is createdbookmark.updated
- Triggered when a bookmark is updatedbookmark.deleted
- Triggered when a bookmark is deleted
Bulk Operation Events
bookmarks.imported
- Triggered when bookmarks are imported in bulkbookmarks.deleted
- Triggered when multiple bookmarks are deletedbookmarks.updated
- Triggered when multiple bookmarks are updatedtag.renamed
- Triggered when a tag is renamed across multiple bookmarkstag.deleted
- Triggered when a tag is removed from multiple bookmarks
Webhook Payloads
All webhook payloads share a common structure. The specific data included depends on the event type. Here are examples of the different payload formats:
Common Structure
{
"id": "webhook-delivery-id",
"event": "event.type",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
// Event-specific data
}
}
bookmark.created
{
"id": "webhook-delivery-id",
"event": "bookmark.created",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
"id": "abc123",
"url": "https://example.com",
"title": "Example Website",
"description": "An example website",
"tags": ["example", "demo"],
"createdAt": "2023-06-15T12:30:45Z",
"updatedAt": "2023-06-15T12:30:45Z"
}
}
bookmark.updated
{
"id": "webhook-delivery-id",
"event": "bookmark.updated",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
"old": {
"id": "abc123",
"url": "https://example.com",
"title": "Old Title",
"description": "Old description",
"tags": ["old", "tags"],
"createdAt": "2023-06-15T12:30:45Z",
"updatedAt": "2023-06-15T12:30:45Z"
},
"new": {
"id": "abc123",
"url": "https://example.com",
"title": "Updated Title",
"description": "Updated description",
"tags": ["updated", "tags"],
"createdAt": "2023-06-15T12:30:45Z",
"updatedAt": "2023-06-15T13:45:30Z"
}
}
}
bookmark.deleted
{
"id": "webhook-delivery-id",
"event": "bookmark.deleted",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
"id": "abc123",
"url": "https://example.com",
"title": "Example Website",
"description": "An example website",
"tags": ["example", "demo"],
"createdAt": "2023-06-15T12:30:45Z",
"updatedAt": "2023-06-15T12:30:45Z"
}
}
Bulk Operations
Bulk operation payloads include a count and list of affected bookmark IDs:
{
"id": "webhook-delivery-id",
"event": "bookmarks.imported",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
"count": 25,
"bookmarkIds": ["abc123", "def456", "ghi789", "..."]
}
}
Tag Operations
{
"id": "webhook-delivery-id",
"event": "tag.renamed",
"timestamp": "2023-06-15T12:30:45Z",
"data": {
"count": 10,
"bookmarkIds": ["abc123", "def456", "ghi789", "..."],
"oldTag": "javascript",
"newTag": "js"
}
}
Security
When creating a webhook, you can generate a signing secret. This secret is used to create a signature that is sent with each webhook payload, allowing you to verify that the request came from Bookmark Manager.
The signature is included in the X-Webhook-Signature
header of the webhook request.
It is calculated using HMAC-SHA256 with your webhook secret.
Verifying Signatures
To verify webhook signatures:
- Get the signature from the
X-Webhook-Signature
header - Create an HMAC-SHA256 hash of the request body using your webhook secret
- Compare the two signatures
Here's how you can verify signatures in different languages:
// Node.js
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const computedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(computedSignature)
);
}
// Example usage in Express
app.post('/webhook', express.json(), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(req.body, signature, 'your-webhook-secret');
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook
console.log('Webhook verified:', req.body);
res.status(200).send('Webhook received');
});
Best Practices
- Respond quickly - Your endpoint should return a 2xx status code as quickly as possible. Process the webhook asynchronously if needed.
- Handle failures - Make sure your webhook endpoint can handle temporary failures as currently we don't implement automatic retries for failed webhook deliveries.
- Verify signatures - Always verify webhook signatures to ensure the requests are coming from Bookmark Manager.
- Idempotency - While we take measures to prevent duplicate webhook deliveries, designing your webhook handlers to be idempotent is still recommended as a best practice for resilient integrations.