Overview
Register a public HTTPS endpoint in Dashboard → Developer → Webhooks. s.id will POST a signed JSON payload to your URL when a subscribed event occurs. Deliveries that fail (non-2xx or timeout) are retried up to 3 times total, with delays of 0s, 5s, and 30s.
Available Events
link.createdFired when a new link is createdlink.updatedFired when a link's URL or title is changedlink.archivedFired when a link is archivedlink.clickedFired on each redirect (per-click event)microsite.publishedFired when a microsite is publishedqr.scannedFired when a QR code is scannedPayload Structure
Every webhook POST contains a JSON body with the event name, the relevant resource, and a UTC timestamp.
{
"event": "link.created",
"link": {
"id": 123,
"short": "mylink",
"short_url": "https://s.id/mylink",
"long_url": "https://example.com/long-url",
"title": "My Link",
"created": "2026-06-22T10:00:00Z"
},
"timestamp": "2026-06-22T10:00:00Z"
}Verifying Signatures
Every delivery includes an X-SID-Signature: sha256=<hex> header. Compute HMAC-SHA256 of the raw request body using your webhook secret and compare with timing-safe equality.
Always verify the signature before processing the event. Never trust the payload without verifying the HMAC.
Node.js
const crypto = require('crypto');
function verifySignature(secret, rawBody, sigHeader) {
const expected = 'sha256=' +
crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(sigHeader),
Buffer.from(expected),
);
}Go
func verifySignature(secret, body []byte, sig string) bool {
mac := hmac.New(sha256.New, secret)
mac.Write(body)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(sig), []byte(expected))
}Setup
1Go to Dashboard → Developer → Webhooks and click Add Webhook.
2Enter your HTTPS endpoint URL and select the events you want to subscribe to.
3Copy the webhook secret, it is shown only once.
4In your server, verify the X-SID-Signature header before processing.
5Return HTTP 2xx within 10 seconds. Failed deliveries are retried up to 3 times; after 5 consecutive failed deliveries the webhook is automatically disabled.