Skip to content

Webhook API Endpoints

All webhook subscription endpoints require admin authentication.

List Subscriptions

GET /v1/webhook-subscriptions

List all webhook subscriptions for the current organization.

Auth: Admin only.

Response (200):

json
{
  "data": [
    {
      "id": 1,
      "uid": "a1b2c3d4-...",
      "url": "https://hook.eu1.make.com/abc123",
      "description": "Slack notifications via Make",
      "events": ["appointment.created", "appointment.cancelled"],
      "is_active": true,
      "created_at": "2025-01-15T10:30:00Z"
    }
  ]
}

Note: signing_secret is never returned in list responses. It's only shown once at creation time.


Create Subscription

POST /v1/webhook-subscriptions

Create a new webhook subscription.

Auth: Admin only.

Request:

json
{
  "url": "https://hook.eu1.make.com/abc123",
  "description": "Slack notifications via Make",
  "events": ["appointment.created", "appointment.cancelled"]
}

Validation:

  • url: Required, must be HTTPS
  • events: Required, non-empty array. Each must be a valid event type or "*" for all events
  • signing_secret: Generated server-side (32 random bytes, hex-encoded, prefixed with whsec_)

Response (201):

json
{
  "data": {
    "id": 1,
    "uid": "a1b2c3d4-...",
    "url": "https://hook.eu1.make.com/abc123",
    "description": "Slack notifications via Make",
    "events": ["appointment.created", "appointment.cancelled"],
    "signing_secret": "whsec_a1b2c3d4e5f6g7h8...",
    "is_active": true,
    "created_at": "2025-01-15T10:30:00Z"
  }
}

IMPORTANT: The signing_secret is only returned in this response. Store it securely — you'll need it to verify webhook signatures. It cannot be retrieved later.


Update Subscription

PATCH /v1/webhook-subscriptions/{uid}

Update a subscription (URL, events, active status).

Auth: Admin only.

Request:

json
{
  "events": ["*"],
  "is_active": false
}

Updatable fields:

  • url — Change the delivery endpoint
  • description — Update the description
  • events — Modify event subscriptions
  • is_active — Enable/disable the subscription

Response (200):

json
{
  "data": {
    "id": 1,
    "uid": "a1b2c3d4-...",
    "url": "https://hook.eu1.make.com/abc123",
    "description": "Slack notifications via Make",
    "events": ["*"],
    "is_active": false,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T14:20:00Z"
  }
}

Note: The signing secret cannot be changed. If you need a new secret, delete the subscription and create a new one.


Delete Subscription

DELETE /v1/webhook-subscriptions/{uid}

Delete a subscription and all its delivery history.

Auth: Admin only.

Response (204): No content.

Note: This action is permanent. All delivery history for this subscription will be deleted.


List Delivery Events

GET /v1/webhook-subscriptions/{uid}/events

List recent delivery attempts for a subscription (for debugging).

Auth: Admin only.

Query Parameters:

  • status (optional) — Filter by status: pending, delivered, failed, exhausted
  • page (optional, default: 1) — Page number
  • page_size (optional, default: 25) — Results per page

Example:

GET /v1/webhook-subscriptions/a1b2c3d4-..../events?status=failed&page=1&page_size=25

Response (200):

json
{
  "data": [
    {
      "id": 5678,
      "event_type": "appointment.created",
      "status": "failed",
      "attempts": 3,
      "last_status_code": 500,
      "last_error": "Internal Server Error",
      "next_retry_at": "2025-07-15T15:30:00Z",
      "created_at": "2025-07-15T14:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "page_size": 25,
    "total": 142
  }
}

Test Subscription

POST /v1/webhook-subscriptions/{uid}/test

Send a test event to verify the subscription URL is reachable.

Auth: Admin only.

Response (200):

json
{
  "status": "delivered",
  "status_code": 200,
  "latency_ms": 142
}

Response (400) — Delivery Failed:

json
{
  "status": "failed",
  "status_code": 500,
  "error": "Internal Server Error"
}

How it works:

  • Sends a webhook.test event with a dummy payload
  • Delivery is synchronous (no retry)
  • Returns the result immediately
  • Useful for verifying endpoint configuration before going live

Test event payload:

json
{
  "id": "evt_test_01HQ3K5M7N8P9R0S",
  "event": "webhook.test",
  "timestamp": "2025-07-15T14:30:00Z",
  "organization_id": 42,
  "data": {
    "message": "This is a test webhook delivery"
  }
}

Error Responses

All endpoints return standard error responses:

400 Bad Request:

json
{
  "error": "invalid_request",
  "message": "URL must use HTTPS"
}

401 Unauthorized:

json
{
  "error": "unauthorized",
  "message": "Authentication required"
}

403 Forbidden:

json
{
  "error": "forbidden",
  "message": "Admin access required"
}

404 Not Found:

json
{
  "error": "not_found",
  "message": "Webhook subscription not found"
}