Bkmark Webhooks — Real-Time Event Notifications API
Receive HTTP POST notifications when Bkmark events occur. Covers subscription setup, payload formats, HMAC signature verification, retries, and polling.
Webhooks let your application react to changes in a user’s Bkmark account the moment they happen — no polling required. When an event occurs (a bookmark is created, a tag is renamed, a group is deleted), Bkmark sends an HTTP POST request containing a JSON payload to the URL you registered. You verify the request came from Bkmark using an HMAC-SHA256 signature, then process the event however your application needs.
The secret field is returned only once — at creation time. Store it immediately in a secure secrets manager (such as AWS Secrets Manager, HashiCorp Vault, or an environment variable). You cannot retrieve it again. If you lose it, delete the subscription and create a new one.
Bkmark emits events across three resource types: bookmarks, groups, and tags.
Event
Trigger
bookmark.created
A new bookmark is saved
bookmark.updated
A bookmark’s title, description, or other fields change
bookmark.deleted
A bookmark is permanently deleted
bookmark.favorited
A bookmark is marked as a favorite (transition only)
bookmark.unfavorited
A bookmark’s favorite status is removed (transition only)
bookmark.archived
A bookmark is archived (transition only)
bookmark.unarchived
A bookmark is unarchived (transition only)
bookmark.restored
A soft-deleted bookmark is restored from trash
group.created
A new group is created
group.updated
A group’s name or color changes
group.deleted
A group is deleted
tag.created
A new tag is created
tag.updated
A tag’s name or color changes
tag.deleted
A tag is deleted
Transition events (bookmark.favorited, bookmark.unfavorited, bookmark.archived, bookmark.unarchived) fire only when the boolean state actually changes. For example, PATCHing isArchived: true on a bookmark that is already archived does not fire bookmark.archived. No-op updates to tags and groups also do not fire tag.updated or group.updated.
tag.updated and group.updated both include a previous object inside data with the prior values of every field that changed. Useful for “if name changed from X to Y” workflows.
Every delivery includes an X-Bkmark-Signature header containing the HMAC-SHA256 hex digest of the raw request body, computed using your webhook secret.
Always verify the signature before processing any webhook. Skip this step and an attacker can send forged events to your endpoint. Use a timing-safe comparison function — standard string equality is vulnerable to timing attacks.
The verification algorithm is:
Read the raw request body as bytes (do not parse JSON first).
Compute HMAC-SHA256(secret, rawBody) and encode as a hex string.
Compare the result with the value in X-Bkmark-Signature using a timing-safe equality function.
Bkmark dispatches webhook requests asynchronously from a background job queue. The following guarantees and constraints apply:
Your endpoint must return a 2xx status code within 10 seconds. Any non-2xx response or a timeout is treated as a failure.
Failed deliveries are retried 3 times using exponential backoff.
You can inspect every attempt — including the HTTP response code your server returned — via GET /api/v1/webhooks/:id/deliveries.
Respond with 200 OK immediately and offload any heavy processing to a background worker or task queue. This prevents timeouts caused by slow database writes or third-party API calls inside your handler.
Because deliveries can be retried, your handler should be idempotent. Use the timestamp field and the entity id inside data together as a deduplication key — if you’ve already processed an event with that combination, skip it.
If you need to backfill events or reconcile state without webhooks, you can poll the bookmarks list endpoint with time-based filters.
Parameter
Description
?since=<ISO 8601>
Return bookmarks with createdAtafter the given timestamp
?updatedSince=<ISO 8601>
Return bookmarks with updatedAtafter the given timestamp
Both filters are strictly greater-than — a bookmark whose timestamp exactly matches the boundary is excluded. Combine with sortField=updatedAt&sortDir=desc for efficient incremental sync.
# Fetch all bookmarks created after June 1stcurl "https://api.bkmark.it/api/v1/bookmarks?since=2025-06-01T00:00:00.000Z&sortField=createdAt&sortDir=desc" \ -H "Authorization: Bearer ACCESS_TOKEN"# Fetch all bookmarks updated in the last 15 minutescurl "https://api.bkmark.it/api/v1/bookmarks?updatedSince=2025-06-01T14:15:00.000Z&sortField=updatedAt&sortDir=desc" \ -H "Authorization: Bearer ACCESS_TOKEN"