Webhooks

Push signal events to your endpoint in real time as Autobound ingests new signals. No polling required.

Webhooks let you receive signal events pushed directly to an endpoint you control — no polling, no cron jobs. When Autobound ingests new signals that match your subscription, your endpoint receives an HTTP POST with the full signal payload within minutes.

Why use webhooks instead of polling?

  • Lower latency — You get signals as they arrive, not on a fixed schedule
  • No wasted calls — You don't pay credits to poll for new data; credits are only consumed on actual deliveries
  • Simpler architecture — No need to store a "last checked" cursor or manage polling loops

Credit note: Managing webhook subscriptions (create, update, list, delete) is always free. Credits are consumed when a signal event is delivered to your endpoint — not when you set up the subscription.


Create a Subscription

Register your endpoint and tell Autobound which signal types you want delivered. If you omit signal_types, you'll receive all signal types.

curl -X POST https://signals.autobound.ai/v1/webhooks \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/signals",
    "signal_types": ["work-milestones", "news", "8k"],
    "description": "CRM enrichment feed"
  }'

Request body:

FieldTypeRequiredDescription
urlstringYesHTTPS endpoint to receive events. Must be publicly accessible.
signal_typesstring[]NoFilter to specific signal types. Omit to receive all types.
descriptionstringNoHuman-readable label for this subscription

Response:

{
  "id": "wh_abc123",
  "url": "https://your-app.com/webhooks/signals",
  "signal_types": ["work-milestones", "news", "8k"],
  "description": "CRM enrichment feed",
  "signing_secret": "whsec_...",
  "status": "active",
  "created_at": "2026-03-05T00:00:00Z"
}

Save the signing_secret — you'll use it to verify that incoming events are genuine Autobound deliveries. It's only shown once (but can be rotated).


Event Payload

Each delivery is a POST to your endpoint. The body is a standard signal object — identical to what you'd get from the REST API — plus an event field indicating the event type.

Headers sent with every delivery:

Content-Type: application/json
x-autobound-signature: sha256=<hmac>
x-autobound-event: signal.created
x-autobound-delivery: del_xyz789

Body:

{
  "event": "signal.created",
  "signal_id": "7dfdb4b4-c0b4-4620-aca6-e7263123028e",
  "signal_type": "work-milestones",
  "signal_subtype": "jobChange",
  "signal_name": "Job Change",
  "detected_at": "2026-03-04T00:00:00Z",
  "association": "contact",
  "company": { "..." },
  "contact": { "..." },
  "data": { "..." }
}

Respond with any 2xx status to acknowledge delivery. Anything else is treated as a failure and retried with exponential backoff.


Verifying Signatures

Always verify the x-autobound-signature header before processing an event. This confirms the payload came from Autobound and hasn't been tampered with.

const crypto = require("crypto");

function verifySignature(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected)
  );
}

Use crypto.timingSafeEqual (not ===) to prevent timing attacks.


Managing Subscriptions

List all your subscriptions:

GET /v1/webhooks

Get a specific subscription:

GET /v1/webhooks/:id

Update a subscription — change the URL, signal type filter, or pause/resume:

PATCH /v1/webhooks/:id
{
  "signal_types": ["work-milestones", "news"],
  "status": "paused"
}

Delete a subscription:

DELETE /v1/webhooks/:id

Testing Your Endpoint

Before going live, send a test event to confirm your endpoint is receiving and parsing payloads correctly:

curl -X POST https://signals.autobound.ai/v1/webhooks/wh_abc123/test \
  -H "x-api-key: YOUR_API_KEY"

This sends a synthetic signal event to your endpoint — same format as a real delivery, so you can validate your signature verification and parsing logic end-to-end.


Backfilling Historical Signals

When you first connect a new subscription, you may want historical signals — not just new ones going forward. The replay endpoint delivers historical signals matching your subscription's filter to your endpoint.

curl -X POST https://signals.autobound.ai/v1/webhooks/wh_abc123/replay \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "since": "2026-01-01",
    "signal_types": ["work-milestones"]
  }'

Backfill deliveries consume credits at the same rate as live deliveries.


Delivery Logs & Failures

View recent delivery attempts and their outcomes:

GET /v1/webhooks/:id/deliveries
{
  "deliveries": [
    {
      "id": "del_xyz789",
      "status": "success",
      "http_status": 200,
      "attempt": 1,
      "delivered_at": "2026-03-05T10:23:00Z"
    },
    {
      "id": "del_abc456",
      "status": "failed",
      "http_status": 500,
      "attempt": 3,
      "delivered_at": "2026-03-05T09:10:00Z"
    }
  ]
}

Failed deliveries that exhaust all retries land in the dead-letter queue, accessible at GET /v1/webhooks/:id/dead. You can replay individual failed deliveries via POST /v1/webhooks/:id/replay.


Rotating Your Signing Secret

If your signing secret is ever exposed, rotate it immediately:

POST /v1/webhooks/:id/rotate-secret

Returns a new signing_secret. Update your verification code with the new secret before rotating to avoid dropping legitimate events during the transition.