Bupple

Webhooks

Get notified when things happen in Bupple

Bupple webhooks send a signed HTTPS POST to your URL for every event in your workspace, or only the ones you pick — a post goes out, a file lands, an automation run finishes, a campaign reaches its goal. Owners and admins add them in Settings › Webhooks; point one at n8n, Zapier, Make or your own script.

Available events

Choose every event, or pick the ones you want. Here are four; Settings › Webhooks lists them all, grouped by app, with an example body for each.

scheduler.post.publish.render.completed.v1

A post went out on a network from Bupple.

Includes

post_idexternal_post_idspublished_atpost
storage.asset.file.upload.completed.v1

A file was uploaded to the Media Library.

Includes

asset_idcontent_typesize_bytesfile
workflows.workflow.run.finish.completed.v1

An automation run finished with a result (test runs are not sent).

Includes

workflow_idrun_idrun_kindfinished_atworkflowrun
campaigns.campaign.goal.reach.completed.v1

A campaign reached 50%, 80% or 100% of its goal.

Includes

campaign_idtargetvaluepercentcampaign

Webhook Payload

Consistent, predictable structure

Every delivery has the same envelope. The type field names the event; data holds what the event published plus a readable copy of what it is about — the post, the file, the run — with download links that last seven days.

example delivery
{
"id": "<event id, the same on every retry>",
"type": "workflows.workflow.run.finish.completed.v1",
"created_at": "2026-10-15T14:32:11.000Z",
"workspace_id": "<workspace id>",
"brand_id": "<brand id>",
"campaign_id": null,
"data": {
"workflow_id": "<automation id>",
"run_id": "<run id>",
"run_kind": "scheduled",
"workflow": { "id": "…", "name": "…" },
"run": { … },
"data_complete": true
}
}

Signature Verification

Verify every request is from Bupple

Each request carries a bupple-signature header: t=<unix time>,v1=<hex>, an HMAC-SHA256 of the time, a dot and the raw body, keyed with your whsec_ secret. Each retry is signed again with a fresh time, so you can refuse an old one. The bupple-event-type and bupple-delivery-id headers name the event and the delivery.

verify-webhook.ts
import crypto from 'crypto'
 
export function verifyWebhook(
rawBody: string,
header: string, // the bupple-signature header
secret: string, // your whsec_ secret
): boolean {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex')
if (typeof parts.v1 !== 'string' || parts.v1.length !== expected.length) return false
return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
}

Set up in 3 steps

All three happen in Settings › Webhooks. Want an automation to run on an event inside Bupple instead? See Automations.

1

Add your endpoint

In Settings › Webhooks, a workspace admin adds an https URL and picks its scope: the whole workspace, one brand, or one campaign. The signing secret is shown once.

2

Pick the events

Every event, or only the ones you choose. Settings shows what each event carries and an example body, and sends a test delivery when you ask.

3

Check the signature, answer 2xx

Verify the bupple-signature header with your secret, then answer with a 2xx. Use the event id (also in the bupple-event-id header) to ignore a delivery you already handled.

Automatic Retries

Any answer other than a 2xx is tried again 1 min, 5 min, 30 min, 2 h and 6 h later — six tries in all. Every attempt is in the delivery log, and you can resend any delivery.

HMAC Signatures

Every request is signed with the endpoint’s secret. Rotate the secret at any time.

Switched off, not silent

An endpoint with 15 failed deliveries in a row and no success for 24 hours is switched off, and the workspace’s owners and admins are told.

Ready to subscribe to events?

Add your first endpoint in Settings › Webhooks.

No credit card required · Cancel anytime