Skip to main content

Webhooks API

Webhooks allow you to receive real-time notifications when events occur in EquipDash, enabling automated workflows and integrations.

What is a Webhook?โ€‹

A webhook is an HTTP callback that sends data to your server when something happens:

  1. An event occurs in EquipDash (e.g., new booking created)
  2. EquipDash sends an HTTP POST request to your URL
  3. Your server receives the event data and takes action
EquipDash                          Your Server
โ”‚ โ”‚
โ”‚ Event: booking.created โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ”‚
โ”‚ POST /your-webhook-url โ”‚
โ”‚ { event, data, timestamp } โ”‚
โ”‚ โ”‚
โ”‚ โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
โ”‚ 200 OK โ”‚
โ”‚ โ”‚

Webhook Structureโ€‹

Webhook
โ”œโ”€โ”€ name (identifier)
โ”œโ”€โ”€ url (your endpoint)
โ”œโ”€โ”€ events[] (subscribed events)
โ”œโ”€โ”€ secret (for signature verification)
โ”œโ”€โ”€ is_active
โ”œโ”€โ”€ failure_count
โ””โ”€โ”€ last_triggered_at

Available Eventsโ€‹

Booking Eventsโ€‹

EventTriggered When
booking.createdNew booking is created
booking.updatedBooking details change
booking.cancelledBooking is cancelled
booking.completedBooking marked complete
booking.picked_upRental items are picked up
booking.returnedRental items are returned
booking.checked_inCustomer checks in for an experience
booking.no_showStaff mark the booking as a no-show
booking.status_changedBooking status changes

Payment Eventsโ€‹

EventTriggered When
payment.receivedPayment is processed
payment.refundedPayment is refunded
payment.balance_dueA balance reminder is sent

Customer Eventsโ€‹

EventTriggered When
customer.createdNew customer added
customer.updatedCustomer details change
customer.deletedCustomer is deleted

Product Eventsโ€‹

EventTriggered When
product.createdNew product added
product.updatedProduct details change
product.archivedProduct is archived

Experience Eventsโ€‹

EventTriggered When
experience.createdNew experience added
experience.updatedExperience details change
experience.archivedExperience is archived

Other Eventsโ€‹

EventTriggered When
form_response.submittedWaiver or form submitted
voucher.soldGift card/voucher purchased
voucher.redeemedVoucher applied to booking

Booking requests, inventory, sessions, shifts, the workshop, store products, surveys, promo codes, agents, bundles, the waitlist and memberships have events too. Webhook Events lists every one.

API Endpointsโ€‹

MethodEndpointDescriptionScope Required
GET/v1/webhooksList all webhookswebhooks:read
GET/v1/webhooks/{id}Get a single webhookwebhooks:read
POST/v1/webhooksCreate a new webhookwebhooks:write
PATCH/v1/webhooks/{id}Update a webhookwebhooks:write
DELETE/v1/webhooks/{id}Delete a webhookwebhooks:write
GET/v1/webhooks/eventsList available eventswebhooks:read
POST/v1/webhooks/{id}/regenerate-secretGenerate new secretwebhooks:write

Webhook Payload Formatโ€‹

All webhook payloads follow this structure:

{
"id": "evt_8fK2pQ7xLm4Vn9Rt3Wc1",
"event": "booking.created",
"created_at": "2026-01-15T12:00:00+00:00",
"data": {
// The record the event is about, e.g. the full booking object
}
}

id names the event and stays the same when a delivery is retried, so use it to skip a repeat. See Webhook Events for a full example.

Mixed bookings

A booking that holds both rentals and experiences fires one booking.created event (not one per type โ€” no fan-out, no double-counting). Its data.type is "mixed" and data.line_types is ["rental", "experience"]. Branch on line_types rather than type if you need to route the rental and experience halves separately. See Bookings โ†’ Line Types.

Verifying Webhook Signaturesโ€‹

Each webhook request includes an X-Webhook-Signature header. Always verify this signature:

$payload = file_get_contents('php://input');
$signature = hash_hmac('sha256', $payload, $your_webhook_secret);

if (hash_equals($signature, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'])) {
// Valid - process the webhook
http_response_code(200);
} else {
// Invalid - reject the request
http_response_code(401);
}

Failure Handlingโ€‹

  • Webhooks must respond with 2xx status within 30 seconds
  • Failed deliveries are retried with exponential backoff
  • After 10 consecutive failures, the webhook is automatically disabled
  • Re-enable by updating is_active: true after fixing your endpoint

Common Use Casesโ€‹

Sync Bookings to External Calendarโ€‹

curl -X POST "https://app.equipdash.com/api/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Calendar Sync",
"url": "https://your-app.com/webhooks/calendar",
"events": ["booking.created", "booking.updated", "booking.cancelled"]
}'

Send Notificationsโ€‹

Subscribe to events and send SMS/email notifications:

{
"name": "Customer Notifications",
"url": "https://your-app.com/webhooks/notify",
"events": ["booking.created", "booking.no_show", "payment.received"]
}

Update Inventory Systemsโ€‹

Keep external inventory in sync:

{
"name": "Inventory Sync",
"url": "https://your-app.com/webhooks/inventory",
"events": ["product.created", "product.updated", "booking.created"]
}

Best Practicesโ€‹

  1. Always verify signatures - Never process unverified webhooks
  2. Respond quickly - Return 200 immediately, process async if needed
  3. Handle duplicates - Same event may be delivered more than once
  4. Use HTTPS - Always use HTTPS URLs in production
  5. Monitor failures - Check failure_count regularly
  6. Rotate secrets - Periodically regenerate webhook secrets