创建我的第一个广告活动
Webhooks

Signed notices when something happens in your workspace.

Each event reaches your server as a POST with JSON, signed with Standard Webhooks. All 13 catalog events are emitted today.

See the 13 eventsVerify the signature
Anatomy of a delivery

What your server receives.

A POST request with four things: the signature, the timestamp, the event name and a JSON body with id, event, createdAt and data.

HTTP
POST /tu/endpoint HTTP/1.1
content-type: application/json
user-agent: BannerMotion-Webhooks/1
webhook-id: evt_p0q8w2e6r4t1
webhook-timestamp: 1759382964
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
x-bm-event: banner.generated
x-bm-delivery: dlv_k29x8m1q4a7z
x-bm-signature: sha256=3b1f...   # de compatibilidad

{
  "id": "evt_p0q8w2e6r4t1",
  "event": "banner.generated",
  "createdAt": "2025-10-02T05:29:24.100Z",
  "data": {
    "jobId": "job_x4k2m9q1a7bz",
    "campaignId": "cmp_8f2a1c3d4e5f",
    "creativeId": "crt_3a9c0d1e2f4b",
    "versionNo": 1,
    "source": "api"
  }
}
HeaderWhat it is
webhook-idThe event id (evt_…), the same as in the body. It does not change across retries.
webhook-timestampUnix seconds of the send.
webhook-signatureStandard Webhooks: v1,<base64 of the HMAC-SHA256>. Two signatures separated by a space during a rotation.
x-bm-eventThe event name, for example banner.generated.
x-bm-deliveryThe id of this delivery (dlv_…).
x-bm-signaturePrevious signature, for compatibility: sha256=<hex>.
Create the webhook

In Integrations & API click Add endpoint, enter your server's address, check the events and click Create endpoint. Copy the secret (whsec_…): it is shown only once.

Test it

In the endpoint menu, Send test event: you receive a signed webhook.test. It does not count toward the automatic pause.

The same id, always

webhook-id is the event id (evt_…) and it is also in the body. It does not change across the retries of a delivery: use it to discard repeats.

Verify the signature

Check that the notice is from BannerMotion.

We sign with Standard Webhooks, so any of its libraries works. The SDKs ship verifyWebhook / verify_webhook ready to use.

  1. Use the exact bodyThe text as it arrived, before converting it to JSON.
  2. Build the signed contentwebhook-id.webhook-timestamp.body
  3. Compute the HMAC-SHA256The key is the bytes of the base64 that follows whsec_ in your secret. The result goes in base64, with the v1, prefix.
  4. Compare in constant timeWith each v1,… signature in the header. During a secret rotation two arrive, separated by a space.
  5. Reject the old and the repeatedTimestamps more than 5 minutes from your clock, and events you already processed (by id).
import { verifyWebhook } from "@bannermotion/sdk";

// rawBody: el cuerpo EXACTO recibido, como texto (antes de convertirlo a JSON).
// Durante una rotación del secreto pasa los dos: [nuevo, anterior].
const event = await verifyWebhook(process.env.BM_WEBHOOK_SECRET, req.headers, rawBody);
// lanza BannerMotionError ("invalid_signature") si la firma o la hora no valen
if (alreadyProcessed(event.id)) return; // las entregas pueden repetirse
CompatibilityX-BM-Signature (sha256= plus the body's HMAC in hexadecimal, with the full secret) still arrives for now. In new integrations use webhook-signature.
Delivery and retries

Respond fast; we keep trying.

Up to 3 attempts

Waits of 5 and 30 seconds between attempts. The same delivery, with the same webhook-id and the same payload.

8 seconds per attempt

Respond with a 2xx as soon as possible and process the event afterwards.

A redirect is a failure

If you respond with a 3xx, we do not follow it: it counts as a failed attempt.

Automatic pause

After 5 consecutive failures the webhook pauses itself and receives no more events until you reactivate it. Manual tests do not count.

Manual retry

Deliveries that exhausted their attempts are retried with Retry, under Recent deliveries.

Up to 10 webhooks

That is the maximum per workspace. Each one chooses its events.

Secret rotation

With Rotate secret, the previous one keeps signing for 24 hours as a second signature, so you can switch without losing events.

Public addresses only

Public http and https addresses are accepted, without a username or password. Private, local and metadata networks are rejected.

Deliveries can repeat

Identify each event by its id and treat repeats as already processed.

See the webhooks reference in the documentation

Connect your notices in minutes.

Webhooks and the API are on the Team, Agency and Enterprise plans; the Starter plan does not include them.

Create my first campaignRead the documentation