Webhooks & Events

Receive real-time notifications when resources change in anny. Register a webhook subscription, and the platform will POST event payloads to your URL.

For general request conventions, see JSON-API Conventions. For authentication, see Authentication.


Prerequisites

  • A valid Bearer token with admin access
  • An HTTPS endpoint capable of receiving POST requests
  • Organization context (?o={organization_id})

Creating Webhooks via the Admin Dashboard

The easiest way to set up webhooks is through the anny admin dashboard:

  1. Navigate to Organization Settings → API → Webhooks
  2. Click Create Webhook
  3. Enter your HTTPS endpoint URL, select the events to subscribe to, and save

For a step-by-step walkthrough with screenshots, see the help center article on webhooks.


Creating a Webhook Subscription via API

Request path documentation: paths/admin/webhooks.yaml

POST /api/v1/webhook-subscriptions?o={org_id}

{
  "data": {
    "type": "webhook-subscriptions",
    "attributes": {
      "name": "My Integration",
      "url": "https://example.com/webhooks/anny",
      "events": ["bookings.created", "bookings.updated", "orders.created"]
    }
  }
}

Attributes

Attribute Type Required Description
name string Yes Descriptive label for the subscription
url string Yes HTTPS endpoint to receive webhook POSTs
events string[] Yes Array of event identifiers to subscribe to
custom_headers object No Additional headers sent with each webhook request
is_active boolean No Defaults to true. Set to false to pause delivery.

Response

The response includes a signing_key — store this securely. It is auto-generated (64-character random string) and used to verify payload signatures.

{
  "data": {
    "type": "webhook-subscriptions",
    "id": "ws-uuid",
    "attributes": {
      "name": "My Integration",
      "url": "https://example.com/webhooks/anny",
      "events": ["bookings.created", "bookings.updated", "orders.created"],
      "signing_key": "a1b2c3...64chars",
      "is_active": true,
      "failure_count": 0,
      "created_at": "2026-03-25T10:00:00+00:00"
    }
  }
}

Event Catalog

Bookings

Event Triggered when
bookings.created A new booking is created
bookings.updated Booking attributes change (status, dates, etc.)
bookings.started Booking start time is reached
bookings.ended Booking end time is reached
bookings.checked-in Customer checks in
bookings.checked-out Customer checks out
bookings.deleted Booking is permanently deleted

Orders

Event Triggered when
orders.created Checkout is completed and order is placed
orders.updated Order attributes change
orders.deleted Order is permanently deleted

Invoices

Event Triggered when
invoices.created Invoice is generated
invoices.finalised Invoice is locked and assigned a number
invoices.updated Invoice attributes change
invoices.deleted Invoice is deleted

Customers

Event Triggered when
customers.created Customer record is created
customers.updated Customer data changes
customers.deleted Customer is deleted

Subscriptions (Plans)

Event Triggered when
subscriptions.created Subscription is created
subscriptions.started Subscription period begins
subscriptions.updated Subscription attributes change
subscriptions.renewed Subscription renews for a new period
subscriptions.charged Subscription payment is processed
subscriptions.suspended Subscription is paused
subscriptions.canceled Subscription is cancelled
subscriptions.reactivated Suspended subscription resumes
subscriptions.ended Subscription expires

Timeslots

Event Triggered when
timeslots.created Timeslot is created
timeslots.updated Timeslot changes
timeslots.started Timeslot start time is reached
timeslots.ended Timeslot end time is reached
timeslots.deleted Timeslot is deleted

Communities

Event Triggered when
community-accounts.joined Member joins a community
community-accounts.left Member leaves a community

Payload Structure

Every webhook delivery is a POST request with Content-Type: application/json. The payload uses a normalized flat JSON format — not JSON-API.

{
  "event": "bookings.updated",
  "event_id": "evt-a1b2c3d4-...",
  "webhook_id": "ws-uuid",
  "triggered_at": "2026-03-25T10:00:00+00:00",
  "data": {
    "id": "b1",
    "type": "bookings",
    "start_date": "2026-04-01T10:00:00+02:00",
    "end_date": "2026-04-01T11:00:00+02:00",
    "status": "accepted",
    "resource": {
      "id": "r1",
      "type": "resources",
      "name": "Meeting Room A",
      "slug": "meeting-room-a"
    },
    "service": {
      "id": "s1",
      "type": "services",
      "name": "Standard Hourly"
    },
    "customer": {
      "id": "c1",
      "type": "customers",
      "first_name": "Jane",
      "last_name": "Doe"
    }
  }
}

Key differences from JSON-API

JSON-API (management endpoints) Webhook payload
Attributes Nested under data.attributes Flat on data top level
Relationships Under data.relationships as ID references Nested as full objects under their name
Side-loaded included array Not used — relations are inline
Content-Type application/vnd.api+json application/json

Included relations per entity

Entity Included relations
Bookings resource, resource.parent, service, customer, customer.address
Orders customer, bookings
Invoices customer, order
Customers address
Subscriptions customer, plan
Timeslots resource, service
Community Accounts customer, community

Note: Included relations and fieldsets may vary by event. The table above shows typical inclusions.


Signature Verification

Every webhook request includes a Signature header containing an HMAC SHA-256 hash of the request body, signed with your subscription's signing_key.

Verifying the Signature

received_signature = request.headers["Signature"]
expected_signature = HMAC-SHA256(signing_key, request.body)

if received_signature != expected_signature:
    reject request (return 401)

Important: Always verify the signature before processing the payload. This prevents spoofed requests.


Retry Policy

If your endpoint doesn't respond with a 2xx status code within 10 seconds, the delivery is retried:

Attempt Timing
1st Immediate
2nd Exponential backoff
3rd Exponential backoff

After 3 failed attempts for a single event, that delivery is abandoned.


Auto-Deactivation

If deliveries fail repeatedly across events, the subscription's failure_count increments. After 5 consecutive failures, the subscription is automatically deactivated:

  • is_active is set to false
  • failure_count resets to 0
  • Organization admins receive a notification about the deactivation

To reactivate, update the subscription:

PATCH /api/v1/webhook-subscriptions/{id}?o={org_id}

{
  "data": {
    "type": "webhook-subscriptions",
    "id": "{id}",
    "attributes": {
      "is_active": true
    }
  }
}

Managing Subscriptions

List All Subscriptions

GET /api/v1/webhook-subscriptions?o={org_id}

Update Events

PATCH /api/v1/webhook-subscriptions/{id}?o={org_id}

{
  "data": {
    "type": "webhook-subscriptions",
    "id": "{id}",
    "attributes": {
      "events": ["bookings.created", "bookings.updated", "customers.created"]
    }
  }
}

Delete a Subscription

DELETE /api/v1/webhook-subscriptions/{id}?o={org_id}

Best Practices

  1. Respond quickly — return 200 immediately and process the payload asynchronously. The 10-second timeout is strict.
  2. Handle duplicates — use event_id to deduplicate. The same event may be delivered more than once on retries.
  3. Verify signatures — always validate the Signature header before trusting the payload.
  4. Subscribe selectively — only subscribe to events you actually process to minimize traffic.
  5. Monitor failure_count — periodically check subscription status to catch issues before auto-deactivation.

Normalized JSON via Accept Header

Webhook management endpoints (and all other API GET endpoints) also support Accept: application/json to receive the same flat/normalized format used in webhook payloads.

GET /api/v1/webhook-subscriptions?o={org_id}
Accept: application/json

This returns attributes at the top level instead of nested under data.attributes, matching the webhook payload structure.

POST and PATCH requests must still use Content-Type: application/vnd.api+json with standard JSON-API format.