Webhooks
slim.to can POST to a URL of yours whenever something happens on a link: someone opens it, converts on it, or submits a form on a hosted page. Point a webhook at Slack, Zapier, Make, n8n, or any HTTPS endpoint you run.
Webhooks are a Pro / Team feature. On Free, creating one returns a 403
with "upgrade_required": true.
Set one up
Dashboard: open Dashboard → Integrations, paste the URL, optionally give it a label, and click Add Webhook.
API (session or API key auth):
curl -s -X POST https://slim.to/api/v1/webhooks \
-H "X-API-Key: $SLIMTO_API_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://hooks.zapier.com/hooks/catch/…", "label": "Zapier flow"}'
Body fields:
| Field | ||
|---|---|---|
url |
required | Any https:// endpoint. Slack incoming-webhook URLs are auto-detected |
label |
optional | A name for the dashboard list |
link_id |
optional | Fire only for this link. Omit to fire for every link you own |
Events
Every event is a JSON POST with the shape below. There is no signature
header today; if you need to verify the sender, use a URL with an
unguessable path (as Slack, Zapier and Make already do).
link.opened
Fires once per new viewer session, for both redirect links and hosted files.
{
"event": "link.opened",
"link": {
"id": "52cab9d5-…",
"slug": "abc123",
"title": "My doc",
"short_url": "https://slim.to/abc123"
},
"viewer": {
"country": "US",
"city": "New York",
"device": "desktop",
"browser": "Chrome",
"os": "macOS",
"referrer": "https://mail.google.com/"
},
"timestamp": "2026-09-12T10:00:00+00:00"
}
conversion
Fires when the viewer page reports a conversion event (a CTA click, a
scroll-depth milestone, or a custom conversion). viewer carries the
conversion details instead of the device summary:
{
"event": "conversion",
"link": { "id": "…", "slug": "abc123", "title": "Pricing", "short_url": "https://slim.to/abc123" },
"viewer": {
"type": "cta_click",
"value": "Book a demo",
"variant_id": "v2",
"session_id": "…",
"country": "US",
"device": "mobile"
},
"timestamp": "…"
}
variant_id is set when the link is running an A/B split test.
form.submitted
Fires when someone submits the form on a hosted page:
{
"event": "form.submitted",
"link": { "id": "…", "slug": "abc123", "title": "Waitlist", "short_url": "https://slim.to/abc123" },
"viewer": {
"id": "…",
"email": "ada@example.com",
"name": "Ada",
"data": { "email": "ada@example.com", "name": "Ada", "company": "Analytical Engines" },
"created_at": "…"
},
"timestamp": "…"
}
Slack
Paste a Slack Incoming Webhook URL (https://hooks.slack.com/…) and
slim.to sends a formatted Block Kit message instead of raw JSON — link title,
location, device and browser for opens; name and email for form submissions;
type, value and variant for conversions.
Delivery
- Deliveries are fire-and-forget with a 10-second timeout. There are no retries, so make your endpoint accept quickly and process asynchronously.
- A webhook with
is_active: falseis kept but skipped. - Per-link webhooks (
link_idset) and global webhooks both fire for the same event; you get one POST per matching webhook.
Manage
| Method | Path | |
|---|---|---|
GET |
/api/v1/webhooks |
List yours — {"webhooks": [...]} |
POST |
/api/v1/webhooks |
Create (body above), returns the webhook |
PATCH |
/api/v1/webhooks/<id> |
{"is_active": false} to pause, {"label": "…"} to rename |
DELETE |
/api/v1/webhooks/<id> |
Remove |
Each webhook object: id, link_id (null for global), url, label,
is_active, created_at.
Other ways to get notified
- Email on open —
PATCH /api/v1/links/<id>with{"notify_on_open": true}, or the toggle in the link's settings. Available on every plan. - Slack without a webhook — the same email notification works with a Slack email-to-channel address.
- Polling —
GET /api/v1/analytics/activityreturns your most recent opens, downloads and link creations across all links; see the API quickstart.