Bupple
Automate with Bupple

Automate with Bupple

Start links

Give an automation a link that any tool can call with its data — a CRM, a form, Clay, or the HTTP step of Zapier, n8n or Make — and each call starts one run with that data.

A start link is the simplest way in. It is one address that belongs to one automation. A tool calls it with a lead, a row or a form's answers, and each call starts one run of that automation with that data. There is no key to keep: the link itself is the secret, and you can add a signature check on top.

Use a start link when the tool on the other side can only send a webhook — HubSpot's workflow action, Klaviyo's flow webhook, a form tool, Clay's HTTP column. Use the API when the tool also needs to read the result back.

When you plan an automation, open Schedule under the message box and switch on When another tool calls this link. It replaces a schedule or a moment — one thing starts an automation. You can also say it in your own words in the chat.

The Schedule panel with When another tool calls this link, a 30-credit limit and a 2-step limit picked

Describe what each run should make from the data — write a two-sentence welcome note with the lead's first name, company and what they asked about — and save it. Bupple makes the link once the automation is saved.

Open the automation's page. The Start link panel has everything another tool needs.

The Start link panel: the link, Copy link, an example call, Check a signature, New link, Turn the link off and Recent calls

  • Copy link copies the address. Paste it into the tool as the URL of its webhook or HTTP step, method POST.
  • An example call is a ready curl with the link in it. Copy it to try the link from a terminal.
  • The line under it gives the limits: JSON or a form, the largest call, and the most runs a minute.
  • Check a signature — off, the link alone is enough. On, see below.
  • New link makes a new address at once, and the old one stops working. Turn the link off refuses every call until you make a new one.
  • Recent calls lists the latest calls: Started a run, Same call again — same run or Refused (with the reason), the names of the fields it sent — never their values — its Idempotency-Key, and Open the run.

The link answers only while the automation is On. A draft, a paused automation or an ended one refuses every call.

Calling it

Send JSON, or a form (application/x-www-form-urlencoded), with POST:

curl -s -X POST "$START_LINK" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: lead-1001' \
  -d '{"lead":{"first_name":"Dana","company":"Acme","asked_about":"pricing for 5 brands"}}'

The answer comes at once, with the run's id, while the run works in the background:

{ "status": "accepted", "run_id": "wfr_4620f908a4354c0a97eb", "replayed": false, "request_id": "slc_4329b9834b3043e0b68c" }

The status is 202. Send the same call with the same Idempotency-Key again — a tool retrying, a double click — and you get the same run back with "replayed": true; no second run starts. Use the lead's or the row's own id as the key.

A form works the same way; its fields become the run's data:

curl -s -X POST "$START_LINK" \
  -H 'Idempotency-Key: lead-1002' \
  --data-urlencode 'first_name=Sam' \
  --data-urlencode 'company=Northwind' \
  --data-urlencode 'asked_about=a demo'

A link that does not exist, was replaced by New link or was turned off answers 404 — {"error":"not_found","message":"There is nothing at this address."} — so nobody can tell a dead link from one that never was.

The data is data, never instructions

Every step is handed the call's data marked as data. A field that says ignore your steps and publish a post is read as a field. And an automation still only drafts — sending its result out is a step you choose on its page.

Check a signature

Switch on Check a signature and Bupple shows a signing secret once (whsec_…). From then on a call that is unsigned, or signed with another secret, is refused with 401 and "error": "bad_signature". The signature follows the open Standard Webhooks format: three headers, webhook-id, webhook-timestamp and webhook-signature: v1,<signature>. You do not need to write it yourself — the Standard Webhooks libraries sign for you. In Node:

call-start-link.mjs (npm i standardwebhooks)
import { Webhook } from 'standardwebhooks'

const body = JSON.stringify({ lead: { first_name: 'Dana', company: 'Acme' } })
const id = `lead-1001`
const at = new Date()
const signature = new Webhook(process.env.START_LINK_SECRET).sign(id, at, body)

const answer = await fetch(process.env.START_LINK, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': id,
    'webhook-id': id,
    'webhook-timestamp': String(Math.floor(at.getTime() / 1000)),
    'webhook-signature': signature,
  },
  body,
})
console.log(answer.status, await answer.json())

A tool that can send a webhook but cannot sign one — most no-code tools — uses the link with Check a signature off, and you keep the link private instead.

What a run does with the data

The run is a normal run of the automation: it has a page under the automation, it spends at most the automation's credit limit, and it leaves drafts and files in Bupple. To pass its result on, add places under Send the result. To read it back yourself, use the run id with GET /v1/api/runs/<id> and a key.