Skip to main content

Webhooks

Webhooks push StudioBase events to your other tools the moment they happen — no manual exports, no polling.

Go to Dashboard > Settings > Integrations > Webhooks to manage your endpoints.

Enabling webhooks

  1. Click Enable webhooks.
  2. Click Add endpoint, paste the HTTPS URL your tool gave you, and choose which events to receive (or check All events).
  3. Copy the signing secret shown after creation — you'll need it to verify deliveries. It's only shown once, but you can re-reveal it later with Reveal secret in the endpoint's Edit dialog.

Disabling webhooks stops new events from being recorded; deliveries already queued will still finish their retry cycles.

Events

EventFires when
booking.createdA class booking is created (paid checkout or class-pack credit)
booking.cancelledA booking is cancelled
checkin.completedA client checks in (self check-in, kiosk, or instructor)
payment.completedA class checkout payment completes
refund.issuedA refund is issued for a booking
pingYou click Send test event

Booking-related events also include class context — class_name, class_start_time, and instructor_name — so you can build messages like "Alex checked in to Morning Yoga Flow at 9:00" without extra lookups.

Every delivery is a JSON POST shaped like:

{
  "id": "9b2f…",
  "type": "booking.created",
  "version": 1,
  "created_at": "2026-06-10T14:30:00+00:00",
  "studio": { "id": "…", "slug": "your-studio" },
  "data": {
    "booking_id": "…",
    "guest_email": "…",
    "class_name": "Morning Yoga Flow",
    "class_start_time": "2026-06-12T09:00:00+00:00",
    "instructor_name": "Jordan Lee"
  }
}

The id is stable across retries — use it to deduplicate if your receiver sees the same event twice.

Verifying signatures

Deliveries are signed with the Standard Webhooks scheme — headers webhook-id, webhook-timestamp, and webhook-signature (v1,<base64 HMAC-SHA256 of "id.timestamp.body">, keyed by your secret). Use any Standard Webhooks library, or verify manually. Both examples below also enforce a 5-minute replay window by rejecting timestamps older than 300 seconds:

const crypto = require("crypto");

function verify(secret, headers, rawBody) {
  // Reject stale timestamps (replay protection).
  const ts = Number(headers["webhook-timestamp"]);
  if (!Number.isFinite(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;

  const key = Buffer.from(secret.slice("whsec_".length), "base64");
  const signedContent = `${headers["webhook-id"]}.${ts}.${rawBody}`;
  const expected = crypto.createHmac("sha256", key).update(signedContent).digest();

  return headers["webhook-signature"].split(" ").some((part) => {
    if (!part.startsWith("v1,")) return false;
    const provided = Buffer.from(part.slice(3), "base64");
    return provided.length === expected.length && crypto.timingSafeEqual(provided, expected);
  });
}
import base64, hashlib, hmac, time

def verify(secret: str, headers: dict, raw_body: str) -> bool:
    ts = headers["webhook-timestamp"]
    if abs(time.time() - int(ts)) > 300:
        return False
    key = base64.b64decode(secret[len("whsec_"):])
    signed = f'{headers["webhook-id"]}.{ts}.{raw_body}'
    expected = base64.b64encode(hmac.new(key, signed.encode(), hashlib.sha256).digest()).decode()
    return any(
        hmac.compare_digest(p[len("v1,"):], expected)
        for p in headers["webhook-signature"].split(" ")
        if p.startswith("v1,")
    )

Delivery and retries

Respond with any 2xx status within 10 seconds. Anything else is retried up to 7 times on a backoff schedule (30s, 2m, 10m, 30m, 2h, 6h, 12h) before the delivery is marked failed.

After 5 deliveries in a row exhaust their retries, the endpoint is automatically disabled. Once your receiver is fixed, re-check Active in the endpoint's Edit dialog — re-activating resets its failure count.

Troubleshooting

Open Deliveries next to any endpoint to see every attempt with its HTTP status and error. Redeliver queues the delivery for the next worker run (within about a minute); Send test event fires a ping so you can verify your receiver end-to-end.

Need Help?

Contact support at support@studiobase.org if you have questions about webhooks.

Last updated June 11, 2026

Navigation