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" }
}idis 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.typeis the event's name — one of the names in the tables below.datakeeps 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 downloadlink, 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: falsemeans 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:
| Header | What it is |
|---|---|
bupple-signature | t=<unix seconds>,v1=<signature> — see below |
bupple-event-id | The same as id |
bupple-event-type | The same as type |
bupple-delivery-id | This delivery — a resend is a new delivery of the same event |
user-agent | Bupple-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.
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
| Event | What happened | What the call carries |
|---|---|---|
workflows.startlink.call.receive.completed.v1 | Startlink call receive completed | Its own fields |
workflows.workflow.run.finish.completed.v1 | Automation run finish completed | The automation and the run — why it started, how it ended, its drafts and every output, files with a download link |
Superagent
| Event | What happened | What the call carries |
|---|---|---|
agents.task.subagent.handoff.completed.v1 | Task specialist handoff completed | Its own fields |
agents.task.subagent.handoff.failed.v1 | Task specialist handoff failed | Its own fields |
agents.task.subagent.handoff.requested.v1 | Task specialist handoff requested | Its own fields |
agents.task.subagent.handoff.started.v1 | Task specialist handoff started | Its own fields |
Campaigns
| Event | What happened | What the call carries |
|---|---|---|
campaigns.campaign.goal.reach.completed.v1 | Campaign goal reach completed | The campaign — its name and status |
campaigns.campaign.lifecycle.delete.completed.v1 | Campaign lifecycle delete completed | The campaign — its name and status |
Media Library
| Event | What happened | What the call carries |
|---|---|---|
storage.asset.comment.add.completed.v1 | Asset comment add completed | The file — name, type, size, folder and a link to download it |
storage.asset.context.extract.completed.v1 | Asset context extract completed | The file — name, type, size, folder and a link to download it |
storage.asset.context.extract.failed.v1 | Asset context extract failed | The file — name, type, size, folder and a link to download it |
storage.asset.context.extract.requested.v1 | Asset context extract requested | The file — name, type, size, folder and a link to download it |
storage.asset.context.extract.started.v1 | Asset context extract started | The file — name, type, size, folder and a link to download it |
storage.asset.derivation.compute.completed.v1 | Asset derivation compute completed | The file — name, type, size, folder and a link to download it |
storage.asset.derivation.compute.failed.v1 | Asset derivation compute failed | The file — name, type, size, folder and a link to download it |
storage.asset.derivation.compute.requested.v1 | Asset derivation compute requested | The file — name, type, size, folder and a link to download it |
storage.asset.file.copy.completed.v1 | Asset file copy completed | The file — name, type, size, folder and a link to download it |
storage.asset.file.copy.requested.v1 | Asset file copy requested | The file — name, type, size, folder and a link to download it |
storage.asset.file.create.failed.v1 | Asset file create failed | The file — name, type, size, folder and a link to download it |
storage.asset.file.create.requested.v1 | Asset file create requested | The file — name, type, size, folder and a link to download it |
storage.asset.file.create.started.v1 | Asset file create started | The file — name, type, size, folder and a link to download it |
storage.asset.file.delete.completed.v1 | Asset file delete completed | The file — name, type, size, folder and a link to download it |
storage.asset.file.delete.requested.v1 | Asset file delete requested | The file — name, type, size, folder and a link to download it |
storage.asset.file.move.completed.v1 | Asset file move completed | The file — name, type, size, folder and a link to download it |
storage.asset.file.rename.completed.v1 | Asset file rename completed | The file — name, type, size, folder and a link to download it |
storage.asset.file.upload.completed.v1 | Asset file upload completed | The file — name, type, size, folder and a link to download it |
storage.asset.file.upload.failed.v1 | Asset file upload failed | The file — name, type, size, folder and a link to download it |
storage.asset.file.upload.requested.v1 | Asset file upload requested | The file — name, type, size, folder and a link to download it |
storage.asset.generation.render.failed.v1 | Asset generation render failed | The file — name, type, size, folder and a link to download it |
storage.asset.generation.render.requested.v1 | Asset generation render requested | The file — name, type, size, folder and a link to download it |
storage.asset.lifecycle.process.failed.v1 | Asset lifecycle process failed | The file — name, type, size, folder and a link to download it |
storage.asset.lifecycle.process.started.v1 | Asset lifecycle process started | The file — name, type, size, folder and a link to download it |
storage.asset.lifecycle.ready.completed.v1 | Asset lifecycle ready completed | The file — name, type, size, folder and a link to download it |
storage.asset.processing.job.completed.v1 | Asset processing job completed | The file — name, type, size, folder and a link to download it |
storage.asset.processing.job.failed.v1 | Asset processing job failed | The file — name, type, size, folder and a link to download it |
storage.asset.realtime.probe.completed.v1 | Asset realtime probe completed | The file — name, type, size, folder and a link to download it |
storage.asset.realtime.probe.requested.v1 | Asset realtime probe requested | The file — name, type, size, folder and a link to download it |
storage.asset.realtime.thumbnail.completed.v1 | Asset realtime thumbnail completed | The file — name, type, size, folder and a link to download it |
storage.asset.realtime.thumbnail.requested.v1 | Asset realtime thumbnail requested | The file — name, type, size, folder and a link to download it |
storage.asset.tag.add.completed.v1 | Asset tag add completed | The file — name, type, size, folder and a link to download it |
storage.asset.transcript.transcribe.completed.v1 | Asset transcript transcribe completed | The file — name, type, size, folder and a link to download it |
storage.asset.transcript.transcribe.failed.v1 | Asset transcript transcribe failed | The file — name, type, size, folder and a link to download it |
storage.asset.transcript.transcribe.requested.v1 | Asset transcript transcribe requested | The file — name, type, size, folder and a link to download it |
storage.asset.transcript.transcribe.started.v1 | Asset transcript transcribe started | The file — name, type, size, folder and a link to download it |
storage.asset.version.derive.completed.v1 | Asset version derive completed | The file — name, type, size, folder and a link to download it |
storage.asset.version.derive.failed.v1 | Asset version derive failed | The file — name, type, size, folder and a link to download it |
storage.asset.version.derive.requested.v1 | Asset version derive requested | The file — name, type, size, folder and a link to download it |
storage.asset.version.transcode.completed.v1 | Asset version transcode completed | The file — name, type, size, folder and a link to download it |
storage.asset.version.transcode.failed.v1 | Asset version transcode failed | The file — name, type, size, folder and a link to download it |
storage.asset.version.transcode.requested.v1 | Asset version transcode requested | The file — name, type, size, folder and a link to download it |
storage.asset.version.transcode.started.v1 | Asset version transcode started | The file — name, type, size, folder and a link to download it |
storage.folder.folder.create.completed.v1 | Folder create completed | Its own fields |
storage.folder.folder.delete.completed.v1 | Folder delete completed | Its own fields |
storage.folder.folder.move.completed.v1 | Folder move completed | Its own fields |
storage.folder.folder.rename.completed.v1 | Folder rename completed | Its own fields |
Posts
| Event | What happened | What the call carries |
|---|---|---|
scheduler.post.external.publish.completed.v1 | Post external publish completed | The social account it was posted from |
scheduler.post.publish.render.completed.v1 | Post publish render completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.publish.render.failed.v1 | Post publish render failed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.publish.render.requested.v1 | Post publish render requested | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.publish.render.started.v1 | Post publish render started | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.schedule.cancel.completed.v1 | Post schedule cancel completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.schedule.create.accepted.v1 | Post schedule create accepted | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.schedule.create.completed.v1 | Post schedule create completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.schedule.create.requested.v1 | Post schedule create requested | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.schedule.reschedule.completed.v1 | Post schedule reschedule completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.socialaccount.account.connect.completed.v1 | Social account account connect completed | The social account — network, handle, name and status |
scheduler.socialaccount.account.disconnect.completed.v1 | Social account account disconnect completed | The social account — network, handle, name and status |
Inbox
| Event | What happened | What the call carries |
|---|---|---|
scheduler.inbox.comment.receive.completed.v1 | Inbox comment receive completed | Its own fields |
scheduler.inbox.message.receive.completed.v1 | Inbox message receive completed | Its own fields |
scheduler.inbox.reply.send.completed.v1 | Inbox reply send completed | Its own fields |
Analytics
| Event | What happened | What the call carries |
|---|---|---|
scheduler.brand.engagement.drop.completed.v1 | Brand engagement drop completed | The brand — its name |
scheduler.brand.engagement.rise.completed.v1 | Brand engagement rise completed | The brand — its name |
scheduler.post.analytics.outperform.completed.v1 | Post analytics outperform completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.post.analytics.sync.completed.v1 | Post analytics sync completed | The post — caption, networks and accounts, scheduled and published times, status, links, numbers, and its media with download links |
scheduler.socialaccount.analytics.sync.completed.v1 | Social account analytics sync completed | The social account — network, handle, name and status |
scheduler.socialaccount.followers.milestone.completed.v1 | Social account followers milestone completed | The social account — network, handle, name and status |
Brand
| Event | What happened | What the call carries |
|---|---|---|
brand.asset.copy.create.completed.v1 | Asset copy create completed | The file — name, type, size, folder and a link to download it |
brand.asset.copy.delete.completed.v1 | Asset copy delete completed | The file — name, type, size, folder and a link to download it |
brand.block.content.edit.completed.v1 | Block content edit completed | The brand — its name |
brand.block.lifecycle.add.completed.v1 | Block lifecycle add completed | The brand — its name |
brand.block.lifecycle.remove.completed.v1 | Block lifecycle remove completed | The brand — its name |
brand.block.lifecycle.reorder.completed.v1 | Block lifecycle reorder completed | The brand — its name |
brand.block.version.restore.completed.v1 | Block version restore completed | The brand — its name |
brand.brand.lifecycle.create.completed.v1 | Brand lifecycle create completed | The brand — its name |
brand.brand.lifecycle.delete.completed.v1 | Brand lifecycle delete completed | The brand — its name |
brand.brand.lifecycle.delete.requested.v1 | Brand lifecycle delete requested | The brand — its name |
brand.brand.profile.create.completed.v1 | Brand profile create completed | The brand — its name |
Imagine
| Event | What happened | What the call carries |
|---|---|---|
prism.generation.cost.read.completed.v1 | Generation cost read completed | Its own fields |
prism.generation.request.process.completed.v1 | Generation request process completed | The file it made — name, type, size and a link to download it |
prism.generation.request.process.failed.v1 | Generation request process failed | The file it made — name, type, size and a link to download it |
prism.generation.request.submit.requested.v1 | Generation request submit requested | The file it made — name, type, size and a link to download it |
Web Search, Link Reader and Social Reader
| Event | What happened | What the call carries |
|---|---|---|
brightdata.read.social.scrape.requested.v1 | Read social scrape requested | Its own fields |
exa.search.query.run.requested.v1 | Search query run requested | Its own fields |
firecrawl.scrape.page.extract.requested.v1 | Scrape page extract requested | Its own fields |
supadata.read.post.extract.requested.v1 | Read post extract requested | Its own fields |
Video
| Event | What happened | What the call carries |
|---|---|---|
video.project.media.render.completed.v1 | Project media render completed | Its own fields |
video.project.media.render.failed.v1 | Project media render failed | Its own fields |
video.project.media.render.started.v1 | Project media render started | Its own fields |
Video Editor and Design Editor
| Event | What happened | What the call carries |
|---|---|---|
videostudio.editor.job.finish.completed.v1 | A video or design is finished | The 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.v1 | A video or design failed | The 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
| Event | What happened | What the call carries |
|---|---|---|
profile.user.account.create.completed.v1 | User account create completed | Its own fields |
profile.user.account.delete.completed.v1 | User account delete completed | Its own fields |
profile.user.role.update.completed.v1 | User role update completed | Its own fields |
profile.workspace.group.create.completed.v1 | Workspace group create completed | Its own fields |
profile.workspace.group.delete.completed.v1 | Workspace group delete completed | Its own fields |
profile.workspace.group.update.completed.v1 | Workspace group update completed | Its own fields |
profile.workspace.invite.accept.completed.v1 | Workspace invite accept completed | The person — name and email |
profile.workspace.invite.create.completed.v1 | Workspace invite create completed | Its own fields |
profile.workspace.invite.revoke.completed.v1 | Workspace invite revoke completed | Its own fields |
profile.workspace.invite.update.completed.v1 | Workspace invite update completed | Its own fields |
profile.workspace.member.remove.completed.v1 | Workspace member remove completed | The person — name and email |
profile.workspace.member.update.completed.v1 | Workspace member update completed | The person — name and email |
profile.workspace.workspace.create.completed.v1 | Workspace create completed | Its own fields |
profile.workspace.workspace.delete.completed.v1 | Workspace delete completed | Its own fields |
profile.workspace.workspace.update.completed.v1 | Workspace update completed | Its own fields |
Credits and billing
| Event | What happened | What the call carries |
|---|---|---|
billing.invoice.document.issue.completed.v1 | Invoice document issue completed | The workspace's credits after it |
billing.reservation.credits.confirm.completed.v1 | Reservation credits confirm completed | Its own fields |
billing.reservation.credits.release.completed.v1 | Reservation credits release completed | Its own fields |
billing.reservation.credits.reserve.completed.v1 | Reservation credits reserve completed | Its own fields |
billing.reservation.credits.settle.completed.v1 | Reservation credits settle completed | Its own fields |
billing.subscription.package.cancel.completed.v1 | Subscription package cancel completed | The workspace's credits after it |
billing.subscription.package.purchase.completed.v1 | Subscription package purchase completed | The workspace's credits after it |
billing.subscription.package.resume.completed.v1 | Subscription package resume completed | The workspace's credits after it |
billing.usage.provider.record.requested.v1 | Usage provider record requested | Its own fields |
billing.wallet.credits.charge.completed.v1 | Wallet credits charge completed | The workspace's credits after it |
billing.wallet.credits.charge.failed.v1 | Wallet credits charge failed | The workspace's credits after it |
billing.wallet.credits.grant.completed.v1 | Wallet credits grant completed | The workspace's credits after it |
billing.wallet.credits.refund.completed.v1 | Wallet credits refund completed | The workspace's credits after it |
billing.wallet.credits.topup.completed.v1 | Wallet credits topup completed | The workspace's credits after it |
entitlement.plan.override.set.completed.v1 | Plan override set completed | Its own fields |
Integrations
| Event | What happened | What the call carries |
|---|---|---|
integration.credential.key.remove.completed.v1 | Credential key remove completed | Its own fields |
integration.credential.key.set.completed.v1 | Credential key set completed | Its own fields |
integration.credential.key.verify.completed.v1 | Credential key verify completed | Its own fields |
integration.credential.key.verify.failed.v1 | Credential key verify failed | Its own fields |
integration.embedding.model.set.completed.v1 | Embedding model set completed | Its own fields |
integration.embedding.vectors.reembed.completed.v1 | Embedding vectors reembed completed | Its own fields |
integration.embedding.vectors.reembed.failed.v1 | Embedding vectors reembed failed | Its own fields |
Schedules
| Event | What happened | What the call carries |
|---|---|---|
cron.schedule.fire.dispatch.completed.v1 | Schedule fire dispatch completed | The schedule — its title, timing, and when it runs next |
cron.schedule.fire.dispatch.failed.v1 | Schedule fire dispatch failed | The schedule — its title, timing, and when it runs next |
cron.schedule.fire.dispatch.requested.v1 | Schedule fire dispatch requested | The schedule — its title, timing, and when it runs next |
Notifications
| Event | What happened | What the call carries |
|---|---|---|
notifications.delivery.message.dispatch.requested.v1 | Delivery message dispatch requested | Its own fields |
What to read next
- When a post goes live — a webhook into your CRM.
- Finished video to your tools — a webhook that saves the file where your team keeps it.
Sending results out
End an automation by sending what it made to a webhook, a public link, a Slack channel or a teammate's email — after every real run that finishes well.
API reference
Every route of the Bupple API — its parameters, its body and its answers — drawn from the same OpenAPI document Zapier, n8n and Make import.