Developers · 7 min read · Updated October 26, 2026
Webhooks: React to Link Clicks and Bio Page Views in Real Time
A dashboard tells you what happened the next time you look at it. A webhook tells you the moment it happens: ReSlug sends a signed HTTP POST to a URL you control as soon as a link is created, updated, clicked, or a bio page is viewed, so your own systems react in real time instead of polling the API on a timer.
This guide covers the event types you can subscribe to, how to set up and verify an endpoint, what happens when your receiver is slow or down, and where a webhook fits next to the URL shortener API for the parts it does not cover.
What a webhook actually sends you
Without webhooks, finding out a link was clicked means asking: calling the analytics endpoint and checking whether the count changed since last time. A webhook flips that around. You register an HTTPS URL on your side, and the moment a subscribed event happens, ReSlug sends that URL a signed JSON POST describing it. Your server reacts immediately; there is nothing to poll and nothing to miss between polls.
Each endpoint is created under Webhooks in your workspace settings and can be scoped to exactly the event types you want, so a CRM sync listening for new links is not also woken up by every click.
The event types you can subscribe to
| Event | Fires when | Notes |
|---|---|---|
link.created | A link is created | Includes links created via QR codes or bulk import, not just the create-link dialog. |
link.updated | A link's destination, title, or settings change | Covers edits to any field, including controls like passwords or expiry. |
link.deleted | A link is deleted | Fires once per deletion, including bulk deletes. |
link.clicked | A human visitor is redirected | Bot and crawler traffic, including link-preview fetches, is excluded. |
bio_page.viewed | A human visitor views a bio page | Same bot exclusion as link clicks. |
lead_capture.submitted | A visitor submits a bio page sign-up form | Marked "Coming soon": visible in the endpoint dialog but not yet subscribable. |
There is also a test.ping event, but it is not something you subscribe to: it only exists so you can fire a one-off test delivery at an endpoint you already created, covered below.
Setting up an endpoint
- Open Webhooks and click Add Endpoint.
- Give it a name (so you can tell "CRM sync" apart from "Slack alerts" later), an HTTPS URL, and check the event types it should receive.
- Save. ReSlug shows the signing secret exactly once, in a dialog that will not reopen; copy it into your receiver's configuration before closing it.
Webhooks are a Pro feature: the Free plan does not include them at all, and a workspace that downgrades keeps its configured endpoints but stops sending to them until it upgrades again, the same way retargeting pixels pause rather than disappear. A Pro workspace can hold up to 5 endpoints at once, so splitting integrations across a few focused endpoints instead of one that subscribes to everything is well within budget.
Verifying a delivery is really from ReSlug
Anyone who finds your endpoint URL could POST to it, so every delivery is signed and your receiver should check the signature before trusting the body. ReSlug sends two headers with each delivery: X-Reslug-Timestamp, and X-Reslug-Signature containing v1= followed by the hex-encoded HMAC-SHA256 of {timestamp}.{body}, keyed with your endpoint's secret.
const crypto = require('crypto')
function isValidReslugSignature(rawBody, timestamp, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')
const received = signatureHeader.replace(/^v1=/, '')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))
}Compute the HMAC over the raw request body, not a re-serialized version of the parsed JSON; re-serializing can reorder keys or change whitespace and the signature will no longer match. If you need to inspect a delivery body by hand while wiring this up, a JSON formatter makes it easier to read than the raw request log.
Retries, auto-disable, and recovery
A delivery your endpoint does not acknowledge is not simply dropped. ReSlug retries a failed delivery with backoff for roughly seven hours before giving up on that one event, which comfortably covers a deploy, a restart, or a brief outage on your side. The endpoint detail view lists recent deliveries with their status (Pending, Succeeded, or Failed), HTTP response code, attempt count, and the last error, which is normally enough to tell a timeout apart from your receiver returning a 4xx on a malformed payload.
An endpoint that keeps failing across many consecutive events is auto-disabled rather than retried forever, which is what protects your account from quietly burning through retries against a receiver that is gone for good. An auto-disabled endpoint shows that status clearly and resumes with the same one-click Resume action you would use to bring back an endpoint you paused yourself; nothing about its configuration, URL, or secret is lost in the meantime.
Before relying on an endpoint for anything real, use Send test event from its detail view. That fires the test.ping event once, immediately, so you can confirm your receiver returns a success status and that the signature check above actually passes, without waiting for a real link click.
Zapier-created endpoints work a little differently
An endpoint created from a Zap shows up in the same list, tagged Zapier, but it is not fully editable from the ReSlug side: Zapier owns the URL and event subscription, since those are configured from the Zap itself. From ReSlug you can still pause it, resume it, or delete it, but not edit its name or URL, and there is no secret to rotate because Zapier manages the connection on its own terms. If you need an endpoint you can tune by hand (different events, your own retry logic, your own secret rotation schedule), create it directly in Webhooks rather than through a Zap.
Where a webhook is the right tool
Webhooks and the API answer different questions: the API is for asking ReSlug to do something (create a link, read analytics); a webhook is for finding out the moment something already happened, without asking. Pulling click counts on a schedule gets slower and more wasteful the more often you need fresh data; a webhook gives you the same information at the moment it is true, for free.
- Sync new links into a CRM or ticketing system the moment they are created, instead of a nightly batch job.
- Trigger a Slack or PagerDuty alert when a launch link gets an unusual burst of
link.clickedevents. - Keep an internal audit log of
link.updatedandlink.deletedevents for links your team manages jointly, independent of ReSlug's own audit log. - React to bio page traffic by warming a cache or notifying a team channel on
bio_page.viewed, ahead of the lead-capture event that will extend this to form submissions.
Frequently asked questions
Which plan do I need to use webhooks?
Webhooks are a Pro feature. A Free-plan workspace cannot create endpoints, and a workspace that downgrades keeps its existing endpoints but stops sending deliveries to them until it upgrades again.
How do I confirm a delivery really came from ReSlug?
Check the X-Reslug-Signature header against an HMAC-SHA256 of the timestamp and raw request body, computed with your endpoint's secret. A delivery with a signature that does not match should be rejected.
What happens if my endpoint is down when an event fires?
ReSlug retries the delivery with backoff for about seven hours. If an endpoint keeps failing across many consecutive events it is automatically disabled, and you can resume it with one click once your receiver is back.
Does link.clicked fire for bots and link-preview crawlers?
No. Known bots and crawlers, including the requests that generate social link-preview cards, are excluded from both link.clicked and bio_page.viewed, so those events reflect human traffic only.
Can I test an endpoint before relying on it?
Yes. The Send test event action on an endpoint fires a one-off test.ping delivery immediately, so you can confirm your receiver accepts it and that your signature verification is correct before any real event depends on it.