Gareth Wilson Gareth Wilson

Guide to Attentive Webhooks: Features and Best Practices

Published


Attentive webhooks notify your systems about SMS and email subscriber activity: someone subscribes, a message is sent, an email is opened. If you're syncing subscriber state to a CRM, triggering downstream automation, or building analytics off Attentive activity, webhooks are how you react without polling.

This guide covers how Attentive webhooks work, the events you can subscribe to, how to verify the x-attentive-hmac-sha256 signature, the delivery behavior, and the best practices for running them in production.

What are Attentive webhooks?

Attentive webhooks are HTTP POSTs sent to an endpoint you configure, each carrying a JSON payload about a subscriber event. Payloads include a type, a timestamp (Unix milliseconds), and company and subscriber objects. You subscribe to the event types you care about, and Attentive signs each delivery so you can confirm it came from Attentive.

The signature scheme is a plain HMAC in the x-attentive-hmac-sha256 header with no timestamp, so there's no built-in replay protection; that's yours to add.

Attentive webhook features

FeatureDetails
ConfigurationDashboard (custom app > Webhooks, "Universal") or Webhooks API (POST /webhooks)
Signature headerx-attentive-hmac-sha256
Signature schemehex HMAC-SHA256 of the raw body, keyed with the per-webhook signing key
Replay protectionNone; no timestamp in the signature
Payloadtype, timestamp (Unix ms), company, subscriber
RetriesExponential backoff for up to 3 days on non-2xx
Auto-disableEndpoints failing for multiple consecutive days
OrderingNot guaranteed
Delivery timeoutUndocumented
SDKNo official server-side SDK

Common events

Attentive groups events by channel. SMS and email subscriber events are the common ones:

EventFires when
sms.subscribedA subscriber opts in to SMS
sms.sentAn SMS is sent to a subscriber
email.openedA subscriber opens an email
email.sentAn email is sent to a subscriber
email.unsubscribedA subscriber opts out of email

Subscribe only to the events you process, and consult Attentive's webhook reference for the full list.

Setting up Attentive webhooks

Configure webhooks in the Attentive dashboard (your custom app's Webhooks tab, "Universal" type), or via the Webhooks API using the "Subscription" type:

curl -X POST "https://api.attentivemobile.com/v1/webhooks" \
  -H "Authorization: Bearer $ATTENTIVE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://your-app.example.com/webhook", "subscriptions": ["sms.subscribed", "email.opened"] }'

Attentive shows the per-webhook signing key (a "client secret") in the webhook settings; copy it into your environment.

Securing Attentive webhooks

Each delivery carries an x-attentive-hmac-sha256 header: a hex-encoded HMAC-SHA256 of the raw request body, keyed with your per-webhook signing key. Recompute it over the exact bytes and compare in constant time.

const crypto = require("crypto");

const SIGNING_KEY = process.env.ATTENTIVE_SIGNING_KEY;

function verify(rawBody, signature) {
  const expected = crypto.createHmac("sha256", SIGNING_KEY).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["x-attentive-hmac-sha256"])) {
    return res.sendStatus(401);
  }

  res.sendStatus(200); // acknowledge fast
  processQueue.add(JSON.parse(req.body)); // process asynchronously
});

The same check in Python (matching Attentive's own example, which uses hmac.compare_digest):

import hashlib
import hmac
import os

SIGNING_KEY = os.environ["ATTENTIVE_SIGNING_KEY"].encode()


def verify(raw_body: bytes, signature: str) -> bool:
    expected = hmac.new(SIGNING_KEY, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature or "")

Attentive webhook limitations and pain points

No timestamp, so no replay protection

The Problem: The signature covers the body only. A captured, validly signed payload can be replayed later and it will still verify, so signature verification alone doesn't prove a request is fresh.

Why It Happens: Attentive's scheme is a plain body HMAC without a signed timestamp.

Workarounds:

  • Make processing idempotent so a replayed payload has no additional effect.
  • Dedupe on identifiers in the payload rather than trusting each POST as unique.
  • Use the payload's timestamp to reject implausibly old deliveries if you need a freshness check.

How Hookdeck Can Help: Hookdeck deduplicates deliveries at the edge, filtering replays and retries before they reach your app. See our guide to webhook idempotency.

Ordering is not guaranteed

The Problem: Events can arrive out of order. A state machine that assumes, say, sms.subscribed always precedes sms.sent will get into impossible states.

Why It Happens: Parallel delivery doesn't preserve per-subscriber ordering.

Workarounds:

  • Sort by the payload timestamp rather than trusting receipt order.
  • Treat each event as a trigger to re-check current state, not as the authoritative sequence.

How Hookdeck Can Help: Hookdeck's queueing and replay let you re-process events in a controlled order during recovery. See our guide to webhook ordering.

Auto-disable after sustained failures

The Problem: Attentive retries non-2xx deliveries with exponential backoff for up to 3 days, and endpoints that fail for multiple consecutive days are auto-disabled. Once disabled, you receive nothing until you re-enable.

Why It Happens: Attentive stops delivering to endpoints that look persistently broken.

Workarounds:

  • Acknowledge with a 2xx fast so transient downstream issues don't accumulate as failures.
  • Monitor webhook status and re-enable promptly after fixing an outage.

How Hookdeck Can Help: Hookdeck always accepts deliveries from Attentive and absorbs downstream failures itself, keeping your webhook active while it retries to your service on a schedule you control.

Undocumented delivery timeout

The Problem: Attentive doesn't document a specific response timeout, so you can't rely on a known budget for synchronous work in your handler.

Why It Happens: The timeout simply isn't published.

Workarounds:

  • Acknowledge as fast as possible and process asynchronously; assume the budget is small.
  • Do no blocking work before responding.

How Hookdeck Can Help: Hookdeck acknowledges Attentive within milliseconds and forwards to your endpoint on a timeout you control, so an unknown upstream budget stops being a risk.

Best practices

Verify with the per-webhook signing key

Compute hex HMAC-SHA256 over the raw body with the signing key and compare in constant time using crypto.timingSafeEqual / hmac.compare_digest.

Add your own replay protection

Since there's no signed timestamp, dedupe on payload identifiers and use the timestamp field to reject stale deliveries if you need freshness.

Acknowledge fast, process asynchronously

Return 2xx immediately and defer work to a queue, especially given the undocumented timeout. See why to process webhooks asynchronously.

Don't assume ordering

Sort by the payload timestamp and design handlers to tolerate out-of-order events.

Monitor for auto-disable

Watch webhook status and re-enable quickly after any sustained failure so you don't silently miss events.

Make Attentive webhooks production-ready

Hookdeck verifies x-attentive-hmac-sha256, deduplicates, and durably queues every subscriber event

Conclusion

Attentive webhooks give you SMS and email subscriber activity in real time, verified with a straightforward x-attentive-hmac-sha256 HMAC over the raw body. The things to plan around are what the scheme leaves out: no timestamp means no replay protection, ordering isn't guaranteed, the delivery timeout is undocumented, and sustained failures auto-disable the webhook.

That puts replay protection, idempotency, ordering tolerance, fast acknowledgement, and status monitoring on you. Hookdeck verifies the signature, deduplicates, and durably queues every event at the edge, so your systems process verified, unique subscriber events and a bad day downstream never disables your Attentive webhook.

Get started with Hookdeck for free and handle Attentive webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.