Bupple
Automate with Bupple

Automate with Bupple

Webhooks

Every event you can send from Bupple to your own URL, what each call carries, and how to check that a call really came from Bupple.

A webhook makes Bupple the start of your workflow: each time something you picked happens in your workspace, Bupple POSTs it to your URL. Zapier's Catch Hook, n8n's Webhook node, Make's Custom webhook, Clay's webhook source, HubSpot's When a webhook is received trigger — or your own server — all take it.

You add one in Settings › Webhooks: the URL, where its events come from (the whole workspace, one brand or one campaign) and which events it gets. Webhooks in Platform 101 walks through the screens, the test button and the delivery log. This page is what your tool receives.

An automation's result has its own webhook

To send one automation's finished work somewhere, you do not need a workspace webhook: add A webhook under Send the result on the automation's page. See Sending results out. The call is signed the same way.

What your URL receives

A POST with a JSON body:

{
  "id": "5f0e2a8c-3d41-4b9e-9a77-1c2d3e4f5a6b",
  "type": "videostudio.editor.job.finish.completed.v1",
  "created_at": "2026-11-10T09:30:00.000Z",
  "workspace_id": "…",
  "brand_id": "…",
  "campaign_id": null,
  "data": { "…": "the event's own fields, plus a copy of what it is about" }
}
  • id is the event's id. It is the same on every retry and every resend, so your tool can skip an event it has already handled.
  • type is the event's name — one of the names in the tables below.
  • data keeps every field of the event and adds a copy of what it is about, read when the call was made: the file with a 7-day download link, the post with its caption, accounts and links, the automation run with its drafts and outputs, the brand's and campaign's names. data_complete: false means part of that copy could not be read in time; the call was sent anyway.

Each event in Settings › Webhooks has an Example of its exact body.

The headers:

HeaderWhat it is
bupple-signaturet=<unix seconds>,v1=<signature> — see below
bupple-event-idThe same as id
bupple-event-typeThe same as type
bupple-delivery-idThis delivery — a resend is a new delivery of the same event
user-agentBupple-Webhooks/1.0

Answer quickly, with a 2xx

Any 2xx answer means delivered. Anything else — a 3xx too, because redirects are not followed — is a failed try, and Bupple tries again by itself, waiting longer each time, for several hours. A webhook that keeps failing for a day is switched off, and the workspace's owners and admins are told. Answer first and do the slow work afterwards.

Check that a call came from Bupple

When you add a webhook, Bupple shows its signing secret once (whsec_…). The bupple-signature header is an HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with that whole secret, in hex. To check it: read the raw body before any JSON parsing, rebuild the signature, compare, and refuse a timestamp that is too old.

check-bupple-signature.mjs (Node 18+)
import crypto from 'node:crypto'

/** True when `rawBody` was signed by Bupple with `secret` in the last five minutes. */
export function isFromBupple(rawBody, signatureHeader, secret, toleranceSeconds = 300) {
  const parts = (signatureHeader ?? '').split(',').map((p) => p.trim().split('='))
  const t = Number(parts.find(([k]) => k === 't')?.[1])
  const sent = parts.filter(([k]) => k === 'v1').map(([, v]) => v)
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`, 'utf8').digest('hex')
  return sent.some((v) => v.length === expected.length && crypto.timingSafeEqual(Buffer.from(v), Buffer.from(expected)))
}

In a tool without code, check it with the tool's own HMAC step: n8n's Crypto node (Hmac, SHA256, hex) or Make's sha256(text; hex; key) function, over <t>.<raw body>. Zapier needs Catch Raw Hook (the plain Catch Hook does not pass the headers) and a Code by Zapier step. If your tool cannot check it, keep the URL secret and treat it like a password.

Every event you can send

The catalogue grows when Bupple adds an event, and Send every event includes the new ones. The tables are the catalogue as of November 2026; Settings › Webhooks always lists the current one. Bupple's own internal events are never sent.

Automations

EventWhat happenedWhat the call carries
workflows.startlink.call.receive.completed.v1Startlink call receive completedIts own fields
workflows.workflow.run.finish.completed.v1Automation run finish completedThe automation and the run — why it started, how it ended, its drafts and every output, files with a download link

Superagent

EventWhat happenedWhat the call carries
agents.task.subagent.handoff.completed.v1Task specialist handoff completedIts own fields
agents.task.subagent.handoff.failed.v1Task specialist handoff failedIts own fields
agents.task.subagent.handoff.requested.v1Task specialist handoff requestedIts own fields
agents.task.subagent.handoff.started.v1Task specialist handoff startedIts own fields

Campaigns

EventWhat happenedWhat the call carries
campaigns.campaign.goal.reach.completed.v1Campaign goal reach completedThe campaign — its name and status
campaigns.campaign.lifecycle.delete.completed.v1Campaign lifecycle delete completedThe campaign — its name and status

Media Library

EventWhat happenedWhat the call carries
storage.asset.comment.add.completed.v1Asset comment add completedThe file — name, type, size, folder and a link to download it
storage.asset.context.extract.completed.v1Asset context extract completedThe file — name, type, size, folder and a link to download it
storage.asset.context.extract.failed.v1Asset context extract failedThe file — name, type, size, folder and a link to download it
storage.asset.context.extract.requested.v1Asset context extract requestedThe file — name, type, size, folder and a link to download it
storage.asset.context.extract.started.v1Asset context extract startedThe file — name, type, size, folder and a link to download it
storage.asset.derivation.compute.completed.v1Asset derivation compute completedThe file — name, type, size, folder and a link to download it
storage.asset.derivation.compute.failed.v1Asset derivation compute failedThe file — name, type, size, folder and a link to download it
storage.asset.derivation.compute.requested.v1Asset derivation compute requestedThe file — name, type, size, folder and a link to download it
storage.asset.file.copy.completed.v1Asset file copy completedThe file — name, type, size, folder and a link to download it
storage.asset.file.copy.requested.v1Asset file copy requestedThe file — name, type, size, folder and a link to download it
storage.asset.file.create.failed.v1Asset file create failedThe file — name, type, size, folder and a link to download it
storage.asset.file.create.requested.v1Asset file create requestedThe file — name, type, size, folder and a link to download it
storage.asset.file.create.started.v1Asset file create startedThe file — name, type, size, folder and a link to download it
storage.asset.file.delete.completed.v1Asset file delete completedThe file — name, type, size, folder and a link to download it
storage.asset.file.delete.requested.v1Asset file delete requestedThe file — name, type, size, folder and a link to download it
storage.asset.file.move.completed.v1Asset file move completedThe file — name, type, size, folder and a link to download it
storage.asset.file.rename.completed.v1Asset file rename completedThe file — name, type, size, folder and a link to download it
storage.asset.file.upload.completed.v1Asset file upload completedThe file — name, type, size, folder and a link to download it
storage.asset.file.upload.failed.v1Asset file upload failedThe file — name, type, size, folder and a link to download it
storage.asset.file.upload.requested.v1Asset file upload requestedThe file — name, type, size, folder and a link to download it
storage.asset.generation.render.failed.v1Asset generation render failedThe file — name, type, size, folder and a link to download it
storage.asset.generation.render.requested.v1Asset generation render requestedThe file — name, type, size, folder and a link to download it
storage.asset.lifecycle.process.failed.v1Asset lifecycle process failedThe file — name, type, size, folder and a link to download it
storage.asset.lifecycle.process.started.v1Asset lifecycle process startedThe file — name, type, size, folder and a link to download it
storage.asset.lifecycle.ready.completed.v1Asset lifecycle ready completedThe file — name, type, size, folder and a link to download it
storage.asset.processing.job.completed.v1Asset processing job completedThe file — name, type, size, folder and a link to download it
storage.asset.processing.job.failed.v1Asset processing job failedThe file — name, type, size, folder and a link to download it
storage.asset.realtime.probe.completed.v1Asset realtime probe completedThe file — name, type, size, folder and a link to download it
storage.asset.realtime.probe.requested.v1Asset realtime probe requestedThe file — name, type, size, folder and a link to download it
storage.asset.realtime.thumbnail.completed.v1Asset realtime thumbnail completedThe file — name, type, size, folder and a link to download it
storage.asset.realtime.thumbnail.requested.v1Asset realtime thumbnail requestedThe file — name, type, size, folder and a link to download it
storage.asset.tag.add.completed.v1Asset tag add completedThe file — name, type, size, folder and a link to download it
storage.asset.transcript.transcribe.completed.v1Asset transcript transcribe completedThe file — name, type, size, folder and a link to download it
storage.asset.transcript.transcribe.failed.v1Asset transcript transcribe failedThe file — name, type, size, folder and a link to download it
storage.asset.transcript.transcribe.requested.v1Asset transcript transcribe requestedThe file — name, type, size, folder and a link to download it
storage.asset.transcript.transcribe.started.v1Asset transcript transcribe startedThe file — name, type, size, folder and a link to download it
storage.asset.version.derive.completed.v1Asset version derive completedThe file — name, type, size, folder and a link to download it
storage.asset.version.derive.failed.v1Asset version derive failedThe file — name, type, size, folder and a link to download it
storage.asset.version.derive.requested.v1Asset version derive requestedThe file — name, type, size, folder and a link to download it
storage.asset.version.transcode.completed.v1Asset version transcode completedThe file — name, type, size, folder and a link to download it
storage.asset.version.transcode.failed.v1Asset version transcode failedThe file — name, type, size, folder and a link to download it
storage.asset.version.transcode.requested.v1Asset version transcode requestedThe file — name, type, size, folder and a link to download it
storage.asset.version.transcode.started.v1Asset version transcode startedThe file — name, type, size, folder and a link to download it
storage.folder.folder.create.completed.v1Folder create completedIts own fields
storage.folder.folder.delete.completed.v1Folder delete completedIts own fields
storage.folder.folder.move.completed.v1Folder move completedIts own fields
storage.folder.folder.rename.completed.v1Folder rename completedIts own fields

Posts

EventWhat happenedWhat the call carries
scheduler.post.external.publish.completed.v1Post external publish completedThe social account it was posted from
scheduler.post.publish.render.completed.v1Post publish render completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.publish.render.failed.v1Post publish render failedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.publish.render.requested.v1Post publish render requestedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.publish.render.started.v1Post publish render startedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.schedule.cancel.completed.v1Post schedule cancel completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.schedule.create.accepted.v1Post schedule create acceptedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.schedule.create.completed.v1Post schedule create completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.schedule.create.requested.v1Post schedule create requestedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.schedule.reschedule.completed.v1Post schedule reschedule completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.socialaccount.account.connect.completed.v1Social account account connect completedThe social account — network, handle, name and status
scheduler.socialaccount.account.disconnect.completed.v1Social account account disconnect completedThe social account — network, handle, name and status

Inbox

EventWhat happenedWhat the call carries
scheduler.inbox.comment.receive.completed.v1Inbox comment receive completedIts own fields
scheduler.inbox.message.receive.completed.v1Inbox message receive completedIts own fields
scheduler.inbox.reply.send.completed.v1Inbox reply send completedIts own fields

Analytics

EventWhat happenedWhat the call carries
scheduler.brand.engagement.drop.completed.v1Brand engagement drop completedThe brand — its name
scheduler.brand.engagement.rise.completed.v1Brand engagement rise completedThe brand — its name
scheduler.post.analytics.outperform.completed.v1Post analytics outperform completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.post.analytics.sync.completed.v1Post analytics sync completedThe post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links
scheduler.socialaccount.analytics.sync.completed.v1Social account analytics sync completedThe social account — network, handle, name and status
scheduler.socialaccount.followers.milestone.completed.v1Social account followers milestone completedThe social account — network, handle, name and status

Brand

EventWhat happenedWhat the call carries
brand.asset.copy.create.completed.v1Asset copy create completedThe file — name, type, size, folder and a link to download it
brand.asset.copy.delete.completed.v1Asset copy delete completedThe file — name, type, size, folder and a link to download it
brand.block.content.edit.completed.v1Block content edit completedThe brand — its name
brand.block.lifecycle.add.completed.v1Block lifecycle add completedThe brand — its name
brand.block.lifecycle.remove.completed.v1Block lifecycle remove completedThe brand — its name
brand.block.lifecycle.reorder.completed.v1Block lifecycle reorder completedThe brand — its name
brand.block.version.restore.completed.v1Block version restore completedThe brand — its name
brand.brand.lifecycle.create.completed.v1Brand lifecycle create completedThe brand — its name
brand.brand.lifecycle.delete.completed.v1Brand lifecycle delete completedThe brand — its name
brand.brand.lifecycle.delete.requested.v1Brand lifecycle delete requestedThe brand — its name
brand.brand.profile.create.completed.v1Brand profile create completedThe brand — its name

Imagine

EventWhat happenedWhat the call carries
prism.generation.cost.read.completed.v1Generation cost read completedIts own fields
prism.generation.request.process.completed.v1Generation request process completedThe file it made — name, type, size and a link to download it
prism.generation.request.process.failed.v1Generation request process failedThe file it made — name, type, size and a link to download it
prism.generation.request.submit.requested.v1Generation request submit requestedThe file it made — name, type, size and a link to download it
EventWhat happenedWhat the call carries
brightdata.read.social.scrape.requested.v1Read social scrape requestedIts own fields
exa.search.query.run.requested.v1Search query run requestedIts own fields
firecrawl.scrape.page.extract.requested.v1Scrape page extract requestedIts own fields
supadata.read.post.extract.requested.v1Read post extract requestedIts own fields

Video

EventWhat happenedWhat the call carries
video.project.media.render.completed.v1Project media render completedIts own fields
video.project.media.render.failed.v1Project media render failedIts own fields
video.project.media.render.started.v1Project media render startedIts own fields

Video Editor and Design Editor

EventWhat happenedWhat the call carries
videostudio.editor.job.finish.completed.v1A video or design is finishedThe main file it made (name, type, size and a link to download it) and every file it made, each with its own download link
videostudio.editor.job.finish.failed.v1A video or design failedThe main file it made (name, type, size and a link to download it) and every file it made, each with its own download link

Workspace and people

EventWhat happenedWhat the call carries
profile.user.account.create.completed.v1User account create completedIts own fields
profile.user.account.delete.completed.v1User account delete completedIts own fields
profile.user.role.update.completed.v1User role update completedIts own fields
profile.workspace.group.create.completed.v1Workspace group create completedIts own fields
profile.workspace.group.delete.completed.v1Workspace group delete completedIts own fields
profile.workspace.group.update.completed.v1Workspace group update completedIts own fields
profile.workspace.invite.accept.completed.v1Workspace invite accept completedThe person — name and email
profile.workspace.invite.create.completed.v1Workspace invite create completedIts own fields
profile.workspace.invite.revoke.completed.v1Workspace invite revoke completedIts own fields
profile.workspace.invite.update.completed.v1Workspace invite update completedIts own fields
profile.workspace.member.remove.completed.v1Workspace member remove completedThe person — name and email
profile.workspace.member.update.completed.v1Workspace member update completedThe person — name and email
profile.workspace.workspace.create.completed.v1Workspace create completedIts own fields
profile.workspace.workspace.delete.completed.v1Workspace delete completedIts own fields
profile.workspace.workspace.update.completed.v1Workspace update completedIts own fields

Credits and billing

EventWhat happenedWhat the call carries
billing.invoice.document.issue.completed.v1Invoice document issue completedThe workspace's credits after it
billing.reservation.credits.confirm.completed.v1Reservation credits confirm completedIts own fields
billing.reservation.credits.release.completed.v1Reservation credits release completedIts own fields
billing.reservation.credits.reserve.completed.v1Reservation credits reserve completedIts own fields
billing.reservation.credits.settle.completed.v1Reservation credits settle completedIts own fields
billing.subscription.package.cancel.completed.v1Subscription package cancel completedThe workspace's credits after it
billing.subscription.package.purchase.completed.v1Subscription package purchase completedThe workspace's credits after it
billing.subscription.package.resume.completed.v1Subscription package resume completedThe workspace's credits after it
billing.usage.provider.record.requested.v1Usage provider record requestedIts own fields
billing.wallet.credits.charge.completed.v1Wallet credits charge completedThe workspace's credits after it
billing.wallet.credits.charge.failed.v1Wallet credits charge failedThe workspace's credits after it
billing.wallet.credits.grant.completed.v1Wallet credits grant completedThe workspace's credits after it
billing.wallet.credits.refund.completed.v1Wallet credits refund completedThe workspace's credits after it
billing.wallet.credits.topup.completed.v1Wallet credits topup completedThe workspace's credits after it
entitlement.plan.override.set.completed.v1Plan override set completedIts own fields

Integrations

EventWhat happenedWhat the call carries
integration.credential.key.remove.completed.v1Credential key remove completedIts own fields
integration.credential.key.set.completed.v1Credential key set completedIts own fields
integration.credential.key.verify.completed.v1Credential key verify completedIts own fields
integration.credential.key.verify.failed.v1Credential key verify failedIts own fields
integration.embedding.model.set.completed.v1Embedding model set completedIts own fields
integration.embedding.vectors.reembed.completed.v1Embedding vectors reembed completedIts own fields
integration.embedding.vectors.reembed.failed.v1Embedding vectors reembed failedIts own fields

Schedules

EventWhat happenedWhat the call carries
cron.schedule.fire.dispatch.completed.v1Schedule fire dispatch completedThe schedule — its title, timing, and when it runs next
cron.schedule.fire.dispatch.failed.v1Schedule fire dispatch failedThe schedule — its title, timing, and when it runs next
cron.schedule.fire.dispatch.requested.v1Schedule fire dispatch requestedThe schedule — its title, timing, and when it runs next

Notifications

EventWhat happenedWhat the call carries
notifications.delivery.message.dispatch.requested.v1Delivery message dispatch requestedIts own fields