Webhooks

Webhooks allow your application to receive real-time HTTP callbacks when events occur in SDX. Instead of polling the API for changes, SDX pushes data to your endpoint as it happens.

Setting up a webhook

Via the API

curl -X POST https://api.sdx.dev/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/sdx",
    "events": ["meter.reading.created", "benchmark.updated"],
    "secret": "whsec_your_signing_secret"
  }'

Via the UI

Navigate to Settings > API > Webhooks > Add Endpoint. Enter the URL, select the events you want to receive, and save.

Event types

EventDescription
property.createdA new property was created
property.updatedA property's details were modified
property.archivedA property was archived
building.createdA new building was added to a property
building.updatedA building's details were modified
meter.reading.createdA new meter reading was submitted
meter.reading.updatedAn existing meter reading was modified
meter.reading.deletedA meter reading was removed
benchmark.updatedA building's benchmark scores were recalculated
report.generatedA compliance or custom report was generated
data_quality.changedA building's data quality grade changed
dividend.statement.availableA new Data Dividend statement is ready

Use * to subscribe to all event types.

Payload format

Every webhook delivery is an HTTP POST with a JSON body:

{
  "id": "evt_a1b2c3d4e5",
  "type": "meter.reading.created",
  "created_at": "2026-01-15T10:30:00Z",
  "data": {
    "building_id": "bld_123",
    "meter_id": "mtr_456",
    "reading": {
      "id": "rdg_789",
      "start_date": "2026-01-01",
      "end_date": "2026-01-31",
      "consumption": 42350,
      "unit": "kWh"
    }
  }
}

Verifying signatures

Every webhook request includes a signature header that you should verify to confirm the request came from SDX.

Header: X-SDX-Signature

The signature is an HMAC-SHA256 hex digest of the raw request body using your webhook secret:

import hmac
import hashlib

def verify_webhook(payload_body, signature, secret):
    expected = hmac.new(
        secret.encode("utf-8"),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

Always use constant-time comparison to prevent timing attacks.

Delivery behaviour

  • Timeout — SDX waits up to 10 seconds for your endpoint to respond with a 2xx status code.
  • Retries — Failed deliveries are retried up to 5 times with exponential backoff (1 min, 5 min, 30 min, 2 hours, 12 hours).
  • Ordering — Events are delivered in approximate chronological order but strict ordering is not guaranteed. Use the created_at timestamp for sequencing.
  • Idempotency — Your endpoint may receive the same event more than once. Use the id field to deduplicate.

Monitoring

View delivery history and status under Settings > API > Webhooks > [Endpoint] > Deliveries. Each delivery shows the HTTP status code, response body (first 1 KB), and latency.

Failed deliveries are highlighted with the error reason (timeout, connection refused, non-2xx status).

Disabling and deleting

Webhooks can be paused (temporarily stops deliveries) or deleted (permanently removes the subscription and purges delivery history). Both actions are available in the UI and via the API.

If an endpoint fails for 7 consecutive days, SDX automatically disables it and sends a notification to the API key owner.

Next steps