Documentation

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 created
  • bookmark.updated - Triggered when a bookmark is updated
  • bookmark.deleted - Triggered when a bookmark is deleted

Bulk Operation Events

  • bookmarks.imported - Triggered when bookmarks are imported in bulk
  • bookmarks.deleted - Triggered when multiple bookmarks are deleted
  • bookmarks.updated - Triggered when multiple bookmarks are updated
  • tag.renamed - Triggered when a tag is renamed across multiple bookmarks
  • tag.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:

  1. Get the signature from the X-Webhook-Signature header
  2. Create an HMAC-SHA256 hash of the request body using your webhook secret
  3. 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.