How-to guide

Deliver events to a BuildShip workflow

A BuildShip workflow with an API trigger is an HTTP endpoint — which makes it a perfectly ordinary Queuey delivery target. Put a queue in front of it and every event reaches the workflow with retries, per-key ordering and a dead-letter queue, instead of depending on the workflow being up and fast at the exact moment the event happened.

1 — Get the workflow’s URL

In BuildShip, give the workflow a REST API Call trigger, ship it, and copy the endpoint URL. If you protect the trigger (you should), note the header name and key it expects.

2 — Point a queue at it

In the Queuey console, set the queue’s target to the trigger URL and pick the auth mode that matches what the trigger expects:

queue target
Target URL:  https://<your-project>.buildship.run/orders-sync
Auth:        API key   (header name + value your trigger expects)
             — or Bearer / Basic / OAuth2 client credentials

Each delivery now POSTs the event body to the workflow. With a Supabase-fed queue (see the Supabase guide), the workflow receives the row change exactly as Supabase shaped it:

what the workflow receives
POST /orders-sync HTTP/1.1
Host: <your-project>.buildship.run
X-Api-Key: <the key your BuildShip trigger expects>
Content-Type: application/json

{
  "type": "INSERT",
  "table": "orders",
  "schema": "public",
  "record": { "id": 1042, "customer_id": "ACME", "status": "placed" },
  "old_record": null
}

A 2xx from the trigger counts as delivered. Anything else — timeouts, 5xx, rate limits — is handled by the queue’s retry policy, and gives up into the dead-letter queue rather than into thin air.

3 — Keep the workflow idempotent

Delivery is at-least-once: a retry after an ambiguous failure can run the workflow twice for one event. Have the workflow treat some stable value — the row’s record.id plus the operation, or the event id if you deliver with an envelope — as “already processed” and exit early on a repeat. If the workflow’s effect is not safe to repeat (it charges, emails, or increments), say so in the queue’s retry policy: Queuey’s default on an ambiguous timeout is to hold and ask, not to blindly retry — see reliable delivery.

Answer fast, work slow
BuildShip workflows can run long — AI nodes especially. Configure the trigger to respond as soon as the work is accepted rather than when it finishes; a trigger that takes longer than the delivery timeout looks like a failing target and will be retried. Accept fast, then let the workflow run.

Why not trigger BuildShip straight from Supabase?

Supabase Database Webhooks are sent fire-and-forget via pg_net: short timeout, no durable retry, no record of what failed. If the workflow is redeploying, cold, or rate-limited when the row changes, the trigger never happened — and BuildShip’s own retry settings cannot help, because they retry nodes inside a workflow that already started, not triggers that never arrived. With Queuey in between, the fragile hop is a fast 202 into durable storage, and the hop to BuildShip is retried until the workflow takes it — with the full attempt history in the console when you want to know why something was slow.

Related