Docs/Webhooks
◆ Webhooks

Webhooks for every event.

Sixty-plus event types across inventory, CRM, service, payments, and listings. HMAC-SHA256 signed payloads. Exponential retry up to 72 hours with a dead-letter queue. Replay any event, from the dashboard or the API.

  • 60+ event types · at-least-once delivery
  • HMAC-SHA256 signatures · 5-minute timestamp window
  • Retry schedule: 1m, 5m, 30m, 2h, 8h, 24h, 72h
  • Replay single event or replay since timestamp
Register an endpoint Event catalog
Event catalog

Everything you can subscribe to.

Subscribe to a full resource (hull.*) or a specific event (hull.price_changed). Fan out to as many endpoints as you need — delivery is independent per endpoint.

Hull

6 events
  • hull.created
  • hull.updated
  • hull.price_changed
  • hull.sold
  • hull.syndicated
  • hull.photos_added

Lead

7 events
  • lead.created
  • lead.qualified
  • lead.assigned
  • lead.converted
  • lead.stalled
  • lead.sms_sent
  • lead.consent_captured

Deal

5 events
  • deal.opened
  • deal.offer_sent
  • deal.accepted
  • deal.funded
  • deal.cancelled

Service

4 events
  • service.opened
  • service.parts_ordered
  • service.completed
  • service.invoiced

Payment

3 events
  • payment.succeeded
  • payment.refunded
  • payment.failed

Listing

3 events
  • listing.published
  • listing.updated
  • listing.removed
Delivery mechanics

POST, headers, retry.

We POST a JSON body to your URL with three signing headers. Respond with any 2xx within 10 seconds. Anything else triggers retry.

Request headers

Boateros-Signature
Hex-encoded HMAC-SHA256 of timestamp + body, keyed by your endpoint secret.
Boateros-Event
Event type, e.g. hull.price_changed.
Boateros-Timestamp
ISO 8601. Reject requests older than 5 minutes.

Retry schedule

We retry any non-2xx or timeout with exponential backoff.

1 min5 min30 min2 hr8 hr24 hr72 hr → DLQ
Signature verification

Verify before you trust.

Always verify the signature before processing. Constant-time comparison prevents timing attacks. Reject requests older than 5 minutes to prevent replay.

verify.ts · Node.js
// Express middleware
import { createHmac, timingSafeEqual } from 'crypto';

export function verify(req, secret) {
  const sig = req.headers['boateros-signature'];
  const ts  = req.headers['boateros-timestamp'];
  const payload = ts + '.' + req.rawBody;
  const mac = createHmac('sha256', secret)
    .update(payload).digest('hex');
  return timingSafeEqual(
    Buffer.from(mac), Buffer.from(sig));
}
verify.py · Flask
# Flask view decorator
import hmac, hashlib
from flask import request, abort

def verify(secret: str) -> bool:
    sig = request.headers["Boateros-Signature"]
    ts  = request.headers["Boateros-Timestamp"]
    payload = f"{ts}.{request.data.decode()}"
    mac = hmac.new(secret.encode(),
        payload.encode(),
        hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, sig)
Delivery dashboard

Every event, every attempt.

The dashboard shows the last 30 days of delivery attempts for each endpoint. Filter by event type, status, or time range. Replay a single event or replay everything since a given timestamp.

  • Full request and response payloads

    Including the status code we got back, the response body, and the latency.

  • Replay single event

    Click replay. We resend with a new timestamp and signature, same payload.

  • Replay since timestamp

    For rebuilding state after an outage. Pick a moment, we redeliver everything since.

  • Secret rotation

    Dual-key rotation with a 7-day overlap window. No downtime.

Failure handling

When your endpoint goes dark.

After 72 hours of failure the event moves to your dead-letter queue. Your endpoint is marked unhealthy. You get an email and a Slack alert if configured.

Dead-letter queue

Events we couldn't deliver in 72h. Kept for 30 days. Drain via API.

Health alerts

Failure rate over 10% for 15 minutes → email, Slack, and PagerDuty hooks.

Circuit breaker

100% failure for 30m pauses delivery. Manually re-enable from the dashboard.