Developers
Webhooks — real-time events from Stayo
Subscribe to events in Stayo in real time: new bookings, check-ins and check-outs, cancellations and successful payments. Signed delivery, test delivery, secret rotation and delivery history.
Automatic dispatch
Events are sent in real time when something happens in Stayo — no polling jobs or scheduling.
Signed deliveries
Every payload is signed with HMAC-SHA256 and your signing secret so you can verify that the request comes from Stayo.
Rotate secrets
Rotate the signing secret whenever you want directly from /settings/webhooks — without losing history.
Test delivery
Send a test event to your endpoint with one click and verify that the signature and payload arrive.
Delivery history
See all outgoing requests with status code, time, payload and response. Failed deliveries can be replayed.
Multiple endpoints
Register several URLs per event — build your own integrations, ops alerts or separate environments.
Events
Subscribe per endpoint to the events you're interested in.
| Event | When it's sent |
|---|---|
| booking.created | Sent when a new booking is created — via front desk, booking engine or an external channel. |
| booking.checked_in | Sent when a guest is checked in. |
| booking.checked_out | Sent when a guest is checked out. |
| booking.cancelled | Sent when a booking is cancelled. |
| payment.succeeded | Sent when a payment is completed (card, Swish, invoice and more). |
Example payload
All webhooks are sent as POST with JSON. Signature and event type are in the headers, so you can route and verify before parsing the payload.
- • Stayo-Event — the event type.
- • Stayo-Signature — timestamp + HMAC-SHA256.
- • Stayo-Delivery — unique ID per delivery (for idempotency).
POST https://din-app.example.com/stayo/webhook
Content-Type: application/json
Stayo-Event: booking.created
Stayo-Signature: t=1737200000,v1=9f2c...ab12
Stayo-Delivery: whd_01HXYZ...
{
"id": "evt_01HXYZ...",
"type": "booking.created",
"created": "2026-08-12T09:14:22Z",
"data": {
"booking": {
"id": "bk_01HXYZ...",
"status": "confirmed",
"channel": "direct",
"arrival": "2026-08-20",
"departure": "2026-08-23",
"guest": { "name": "Anna Andersson", "email": "anna@example.com" },
"total": { "amount": 4200, "currency": "SEK" }
}
}
}Verify the signature
Compute HMAC-SHA256 over {timestamp}.{rawBody} with your signing secret and compare with v1 in Stayo-Signature. Use a constant-time comparison.
Reject requests where the timestamp is older than a few minutes to protect against replay.
import crypto from "node:crypto";
export function verifyStayoSignature(
rawBody: string,
header: string,
secret: string,
) {
const [tPart, v1Part] = header.split(",");
const timestamp = tPart.split("=")[1];
const signature = v1Part.split("=")[1];
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex"),
);
}Manage webhooks in Stayo
Under Settings → Webhooks in Stayo (/settings/webhooks) you can:
- • Add and remove endpoints per event.
- • View and rotate the signing secret.
- • Send a test delivery to an endpoint.
- • Browse delivery history with status and payload.
- • Replay failed deliveries.
- • Pause an endpoint temporarily without losing its configuration.
Want to build an integration with Stayo?
Combine webhooks with our public API — we'll help you get started and give you access to the OpenAPI specification and a test environment.