Pool Brain
v1.0

WEBHOOK CONSUMER GUIDE

Real-time event notifications for your integration. Learn how to subscribe, verify, and process webhooks from Pool Brain.

Event-driven Asynchronous Secure At-least-once delivery

Introduction

This document explains how to subscribe to, receive, verify, and process webhooks generated by the system. It is intended for developers and integration partners who want to consume real-time event notifications such as customer creation, customer updates, job creation, and other operational events.

Webhooks are event-driven, asynchronous, secure, and at-least-once delivered.

What Are Webhooks?

Webhooks are HTTP callbacks that notify your system when specific events occur. Instead of polling APIs for changes, your application receives near real-time notifications whenever subscribed events happen.

Examples of currently supported events include:

  • Customer created
  • Customer status changed
  • One-time job created
  • One-time Job Deleted
  • One-time Job schedule Changed
  • Technician Route Changed

High-Level Delivery Model

  1. A business event occurs in the system (e.g., customer created).
  2. A background worker delivers the webhook to your endpoint.
  3. Delivery status is tracked and retried if needed.
Webhook delivery is fully decoupled from the core application, ensuring that webhook failures never impact application performance.

Subscribing to Webhooks

Set-up Instructions

  1. Navigate to Settings: Log in to Pool Brain and go to Settings > API > Webhooks
  2. Activate the “Use Webhooks” toggle setting
  3. Add Endpoint URL: Enter your HTTPS URL (e.g., https://api.yourdomain.com/webhooks)
  4. Select Events: Subscribe to the specific events you need (e.g., customer.created, job.one_time.created).
Note: Only subscribed events are delivered.
Pool Brain — Settings > API > Webhooks dashboard

Settings > API > Webhooks — Example dashboard view

Subscription Details

Webhook subscriptions are configured per company and define:

  • The HTTPS endpoint where webhooks will be delivered
  • Which events do you want to receive
  • A shared secret used for signature verification

Only explicitly subscribed events will trigger webhook notifications.

Webhook Events

Each webhook corresponds to a specific event type.

Event Naming Convention

Event names follow a dot-separated, past-tense format:

customer.created customer.status.changed job.created job.Deleted job.one_time.schedule.changed technician.route.changed

This naming convention ensures consistency and future extensibility.

Webhook Payload Structure

All webhooks use a consistent JSON envelope. The data attribute contains the specific event details.

Field Reference

Field Type Description
id String Unique UUID for this specific webhook delivery
event String The name of the event (e.g., customer.created)
company_id Integer The ID of the company where the event originated
timestamp String UTC timestamp of when the event occurred
data Object / Array The event payload. For grouped events, this will be an Array.

Standard Payload (Single Event)

By default, events are delivered individually.

JSON
{
  "id": "af1edcbb-4622-4653-8ee1-4cb9b2d242bd",
  "event": "customer.status.updated",
  "company_id": 40,
  "timestamp": "2026-02-13T06:42:24.705000Z",
  "data": {
    "customerId": 3930000,
    "displayName": "Chris Bale",
    "currentStatus": "inactive"
  }
}

Grouped Payload (Batched Events)

Used when multiple events of the same type occur simultaneously (e.g., Bulk Imports,one time route move) to reduce network traffic. Your integration must be able to handle data as an Array for grouping events.

JSON
{
  "id": "ddb2ecfe-c4e0-4536-8f00-ccbfbd40af0b",
  "event": "job.one_time.schedule.changed",
  "company_id": 40,
  "timestamp": "2026-02-13T07:12:50.910000Z",
  "data": [
    {
      "jobId": 2493251,
      "jobTitle": "Filter Clean",
      "technicianName": "Alina Grant",
      "currentRouteName": "North Route"
    },
    {
      "jobId": 2493495,
      "jobTitle": "Pump Repair",
      "technicianName": "Alina Grant",
      "currentRouteName": "North Route"
    }
  ]
}

Customer Events

customer.created Customer

Triggered when a new customer is created manually, via import, or sync.

Grouping Supported: Yes — bulk / sync scenarios

Payload data:

JSON
{
  "customerId": 1001,
  "displayName": "John Doe"
}
customer.status.updated Customer

Triggered when a customer status changes (e.g., Active to Inactive status, Lead status, or any other status).

Grouping Supported: No

Payload data:

JSON
{
  "customerId": 1001,
  "displayName": "John Doe",
  "currentStatus": "inactive"
}

Possible values for currentStatus: active, inactive, lead

Job Events

job.one_time.created Job

Triggered when a one-time job is Created.

Grouping Supported: No

Payload data:

JSON
{
  "jobNumber": "JOB-5501"
}
job.one_time.deleted Job

Triggered when a one-time job is permanently deleted.

Grouping Supported: No

Payload data:

JSON
{
  "jobNumber": "JOB-5501",
  "jobTitle": "Filter Cleaning"
}
job.one_time.schedule.changed Job

Triggered when a one-time job is moved, re-routed, or unscheduled.

Grouping Supported: Yes — bulk move

Payload data:

JSON
{
  "jobId": 2493251,
  "jobTitle": "Untitled Job",
  "technicianName": "Sourav Bhange",
  "currentRouteName": "North Route - Truck 1"
}

Route Events

technician.route.changed Route

Triggered when a technician is assigned or unassigned from a route.

Grouping Supported: No

Payload data:

JSON
{
  "technicianFirstName": "Mike",
  "technicianLastName": "Smith",
  "routeName": "North Route - Truck 1"
}

Webhook Security

HTTPS Requirement

All webhook endpoints must use HTTPS

To ensure that webhook requests originate from Pool Brain and not a malicious third party, every request includes a signature header. You must verify this signature before processing the data.

The Signature Header

Every request includes the HTTP header:

HTTP Header
X-Webhook-Signature: <HMAC-SHA256 hash of the request body>

How to Verify

  1. Capture: Obtain the raw bytes of the request body.
  2. Hash: Hash the body using HMAC-SHA256 and your unique Signing Secret (found in your Webhook set-up).
  3. Compare: Compare your generated hash with the value in the X-Webhook-Signature header. If they match, the request is legitimate.

Python Example

Python
import hmac
import hashlib

def verify_signature(request_body, signature_header, secret):
    # Ensure secret is bytes
    secret_bytes = secret.encode('utf-8')

    # Generate hash
    expected_signature = hmac.new(
        secret_bytes,
        request_body,
        hashlib.sha256
    ).hexdigest()

    # Secure comparison to prevent timing attacks
    return hmac.compare_digest(expected_signature, signature_header)

Retry & Failure Handling

If a webhook delivery fails due to network errors, timeouts, or non-2xx HTTP responses, the system automatically retries delivery.

Retry Schedule

  • Initial attempt
  • Retry after ~5 minutes
  • Retry after ~10 minutes
  • Retry after ~30 minutes

If all retries fail, the event is marked as permanently failed.

Expected Responses from Consumer

To acknowledge successful delivery, your endpoint must return:

HTTP status code 2xx (200–299)
Any other response is treated as a failure and will trigger a retry.

Best Practices for Consumers

  • Always respond quickly (within a few seconds)
  • Webhook endpoint will accept application / json content type
  • Process webhooks asynchronously
  • Do not perform long-running tasks in webhook handlers
  • Log received event IDs
  • Implement idempotency
  • Validate signatures on every request

Versioning & Backward Compatibility

Webhook payloads are versioned implicitly by event type and structure.

Breaking changes will:

  • Introduce new event types
  • Never modify existing payloads without notice

This ensures backward compatibility for existing consumers.

Monitoring & Troubleshooting

What to Monitor

  • Delivery frequency
  • Duplicate events
  • Failed processing attempts

Contact Support

If webhook issues are suspected, contact support with:

  • Event ID
  • Timestamp
  • Endpoint URL

Summary

This webhook framework provides a secure, scalable, and reliable mechanism for receiving real-time event notifications. It follows industry best practices and is designed to support high volume, fault tolerance, and long-term extensibility.

This document serves as the official guide for webhook consumers and should be reviewed and approved before enabling production integrations.