- Drawer webhook triggers (
buttons drawer ... trigger webhook+buttons webhook listen) — n8n-style auth, the request body delivered into the workflow as${inputs.webhook.body}, and an optional public Cloudflare URL. Use this when you need the payload. - Button webhook triggers (
buttons trigger add ... --webhook+buttons serve) — a single shared token, no tunnel, and a body that is read then discarded (the press uses the trigger’s own args). Use this for a simple body-less ping on a port you already serve.
Drawer webhook trigger
buttons webhook listen runs the foreground dispatcher and (unless you pass --no-tunnel) brings up a Cloudflare tunnel so third-party services can reach the path. When a POST arrives the drawer is pressed with the request materialized as ${inputs.webhook.body} (plus .headers, .query, .method, .path, .received_at).
Only the webhook kind is implemented for drawer triggers; other kinds error out. The tunnel requires cloudflared on PATH; run buttons webhook setup once to configure a stable named tunnel, or skip it and buttons webhook listen uses an ephemeral quick tunnel.
Flags
/<drawer-name>. A path is globally unique across drawers; reusing one another drawer owns is rejected.
Any secret-bearing value accepts $ENV{VAR_NAME}, resolved at match time, so a committed drawer.json carries the auth shape but not the raw secret.
Auth example
Local testing
Dry-run a webhook drawer without the listener —--webhook-body synthesizes inputs.webhook:
Button webhook trigger
To fire a single button on a POST, attach a webhook trigger to it and runbuttons serve (the local REST API server, which also runs the trigger engine unless you pass --no-triggers):
- Auth is the single shared
--token, checked against theX-Buttons-Tokenheader or?token=query param (constant-time). Omit--tokenfor an open endpoint. - The body is read and discarded — v1 does not map it into args. The press uses the
--argvalues you configured on the trigger. - No Cloudflare tunnel. The path is mounted on whatever interface
buttons servebinds (loopback by default), and the handler returns202 Acceptedimmediately.
buttons trigger list [button] and buttons trigger rm <button> <trigger-id>. The same buttons trigger add command also supports --cron --schedule "0 */6 * * *" and --watch --path ./file.