Skip to main content
A webhook route has two halves: a bucket receives inbound requests at a public URL, and a forwarder delivers them to your target. Provisioning means creating both, wiring the forwarder to the bucket, and confirming the topology. Both are write mutations — see Safe mutations.
For the common case, repost init --name "Stripe production" --target https://api.example.com/webhooks --json creates both halves in one idempotent call — re-running with the same name and target returns the existing route instead of duplicating it. Use the step-by-step flow below when you need to configure the bucket or forwarder beyond init’s defaults. Run repost docs schema "init" for its exact output shape.

Create a bucket

The bucket’s internal_domain is its receiving URL — point the provider at https://<internal_domain>. The name is a positional argument, not a flag.
Capture bucket.id (needed to attach a forwarder) and bucket.slug (used by every diagnostic command).
--response-mode decides how the bucket answers the provider:
  • QUEUE (default) — acknowledge immediately with --ack-status-code / --ack-body, then forward asynchronously. Best for reliability.
  • PROXY — forward synchronously and return the target’s response, bounded by --proxy-timeout-ms. Use only when the provider needs the real downstream response.

Create a forwarder

Attach a forwarder to the bucket by slug. Bucket ID is accepted for compatibility, but agents should prefer the slug from repost bucket list. The name is positional; for an EXTERNAL forwarder (the default type), --target is required.
Retry and rate behavior is set at creation. The defaults are sensible for most targets:
--rate-limit-per-second is a persistent cap on all deliveries from this forwarder — it’s what tames the burst when you resume after a deploy. It is not the same as replay --rate, which throttles a single replay job.

Provision idempotently

init is idempotent; the individual create commands are not.
bucket create and forwarder create generate a fresh idempotency key each run, so a blind retry creates a duplicate. When you use them instead of init, check existence first and only create what is missing.
1

List before creating

repost bucket list --json and repost forwarder list --bucket <bucket-slug> --json. Match on name / slug / target_url.
2

Create only the gap

If the bucket exists, reuse its id. If a forwarder with that target exists, reuse it. Create only what the lists do not already contain.
3

Record the IDs

Persist the returned bucket.id and forwarder.id so later runs skip creation entirely.

Inspect the topology

bucket get returns the bucket plus its active forwarders — the authoritative view of one route.

Verify end to end

Provisioning is not done until a real request flows through. Send a test webhook to https://<internal_domain>, then confirm both halves:
A clean expect (exit 0) proves the bucket received the request. Running forwards chain on that event_id then shows the delivery attempt — a SUCCEEDED status proves the forwarder delivered. Together they confirm the route is live end to end. (Filter failures with forwards search --failed, not a status: query — see Search & filters.)

Continue

Guard deployments

Pause and resume the forwarders you just created.

Diagnose webhooks

Inspect what the new route receives and delivers.

Forwarders

Path modes, transforms, and the complete forwarder model.