Webhooks

In: a service posts its own shape to your source's webhook URL and it arrives as a notification. Out: a destination that receives every notification as a signed POST.

Webhooks in

Every source has a webhook URL next to its key. Paste it where the service asks for one and the service's own payload is mapped into a title, a body, a priority, a link and fields; the source's rules do the rest.

https://youlmk.com/w/k_7hq2nk3f9qd8w4

Creating a source from the integrations catalogue picks the mapping and shows where to paste, step by step, for Sentry, GitHub, Stripe, Vercel, Netlify, Railway, Render, Fly.io, Datadog, Better Stack, Grafana, PagerDuty, Supabase, Neon, PlanetScale, Lemon Squeezy, Paddle, Zapier, Make, n8n and Slack workflows. Anything else uses the generic mapping.

Service
How it is read
GitHub
The event name comes from the X-GitHub-Event header. Releases, workflow runs, pull requests, security alerts and pushes each get a title, the repository as the link, and one card per event kind. Signed with a secret YouLMK makes for you.
Stripe
id, type and data.object. Failed, disputed, refunded, past due and requires_action events arrive as high; the amount and status become fields. Signed with the secret Stripe shows you.
Sentry
Issue alerts. fatal becomes critical, error becomes high, warning normal, the rest low. The culprit and the rule become fields; the issue is the link.
Everything else
Any JSON. The most title-like field (title, text, message, subject, name, summary, event, status, description) becomes the title; a url, html_url, web_url, link, permalink or dashboard_url becomes the link; up to six shallow fields arrive as rows; type, event or action becomes the group.

Signatures

The key in the URL is what authorises a delivery. Where the service signs as well, the signature is a second lock: a GitHub source is created with a signing secret you paste into GitHub, and a Stripe source takes the signing secret Stripe shows you, on the source's page. Once a secret is set, an unsigned or badly signed delivery answers 401 with the reason and writes nothing. The source's page says whether the lock is on.

Answers

The same as the HTTP API: 200 with the notification's id and receipt, 400 for a body that is not JSON, 401, 410, 413 over 8 KB, 429 with Retry-After. Most services retry on anything but a 2xx, so a rate limit is not a lost event.

Webhook out

On the Watch plan a URL you own can be a destination. It receives every notification the account delivers to it as one POST, signed, with the payload the sender wrote plus the source, the reach and the receipt. Add it from the You tab, under Destinations; the secret (whs_ and 32 characters) is shown once.

{
"id": "ntf_…", "receipt": "rcpt_…", "event": "notification",
"source": { "name": "deploy.sh", "type": "script" },
"reach": "banner", "priority": "normal",
"title": "api deployed · v2.4.1", "body": "production · 4 min 12 s",
"url": "https://example.com/deploys/2041", "url_label": "Open",
"fields": { "Service": "api" }, "icon_url": "https://youlmk.com/icons/…png",
"count": 1, "received_at": "2026-09-11T14:02:11.000Z"
}
Header
Value
X-YouLMK-Signature
HMAC-SHA256 of the raw body with the destination's secret, lowercase hex.
X-YouLMK-Receipt
The receipt id, the same one the sender got back.
X-YouLMK-Event
notification, or test for the sample sent from the destination's page.
User-Agent
YouLMK/1.0 (+https://youlmk.com/docs/webhook-out)

Verify by computing the HMAC-SHA256 of the raw body with your secret and comparing it, in constant time, with the header. Reach reads badge, banner or break_through; Silent never leaves the app. count is how many events the card holds when grouping joined them.

// Node
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-youlmk-signature"]));

Delivery and retries

Each POST has 10 seconds and redirects are not followed. Anything but a 2xx is retried 3 times, 30 seconds apart and doubling, with a little jitter. 10 consecutive final failures pause the destination and send you one Banner; resume it from its page. A test from the destination's page is signed the same way, carries "event": "test", and never counts as a failure.

Next

Destinations · Payload reference