> ## Documentation Index
> Fetch the complete documentation index at: https://repost.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a Forwarder and Connect It to Your Webhook Bucket

> Create external or internal Repost forwarders, choose transparent or locked path routing, and configure delivery timeout and retry behavior.

A forwarder is a destination attached to a bucket. When a bucket receives a webhook, each active forwarder decides where that request should be delivered and how delivery should behave. You can attach multiple forwarders to a queued bucket or exactly one forwarder to a proxy bucket.

## Destination types

Pick the forwarder type that matches where your webhook traffic should land. The type is a creation-time decision — you cannot change an external forwarder to internal, or vice versa, after it has been created.

<CardGroup cols={2}>
  <Card title="External forwarder" icon="globe">
    Sends webhook requests to a public `http` or `https` endpoint, such as a production service, staging environment, or partner API.
  </Card>

  <Card title="Internal forwarder" icon="laptop">
    Holds events for a connected CLI session, then delivers them to a local destination such as `localhost:3000`. Use this type during local development.
  </Card>
</CardGroup>

<Note>
  Forwarder type is set at creation and cannot be changed. If you need to switch from external delivery to CLI delivery — or the reverse — create a new forwarder with the correct type.
</Note>

## Path modes

Path mode controls whether Repost preserves the original incoming request path or always sends traffic to a single fixed URL.

<Tabs>
  <Tab title="Transparent">
    Repost treats your configured destination as a base URL and appends the original request path to it.

    | Incoming request   | Forwarded to                              |
    | ------------------ | ----------------------------------------- |
    | `/webhooks/stripe` | `https://api.example.com/webhooks/stripe` |
    | `/webhooks/github` | `https://api.example.com/webhooks/github` |

    Use transparent mode when your server already handles multiple provider paths and you want those paths preserved end-to-end.
  </Tab>

  <Tab title="Locked">
    Repost ignores the original request path and always delivers to the exact URL you configure.

    | Incoming request   | Forwarded to                      |
    | ------------------ | --------------------------------- |
    | `/webhooks/stripe` | `https://api.example.com/webhook` |
    | `/webhooks/github` | `https://api.example.com/webhook` |

    Use locked mode when all incoming traffic should be routed to a single handler regardless of the path.
  </Tab>
</Tabs>

## Create a forwarder

You can create a forwarder when setting up a bucket for the first time, or later from the bucket's Forwarders page.

<Steps>
  <Step title="Name the forwarder">
    Choose a name that describes the destination, such as `production-api`, `local-webhooks`, or `analytics-worker`. Names must be unique within a bucket.
  </Step>

  <Step title="Choose external or internal">
    Select **External** to target a public HTTP endpoint. Select **Internal** to target a developer machine through the Repost CLI.
  </Step>

  <Step title="Choose transparent or locked routing">
    Select **Transparent** to preserve the provider path. Select **Locked** to send all traffic to one fixed destination URL.
  </Step>

  <Step title="Enter the protocol and destination">
    Choose `http` or `https` from the protocol selector, then enter `host[:port][/path]` without the protocol prefix. Internal forwarders default to `http`.
  </Step>

  <Step title="Set the request timeout">
    The default timeout is `20000` ms. You can set any value between `5000` and `60000` ms in steps of `1000` ms.
  </Step>

  <Step title="Configure delivery controls when available">
    Queued buckets expose retry and rate-limit controls during creation. Proxy buckets hide those controls because the provider connection is waiting on a single synchronous destination response.
  </Step>
</Steps>

## Bucket mode rules

The bucket's response mode determines which forwarder controls are available to you.

<CardGroup cols={2}>
  <Card title="Queued bucket" icon="clock">
    Supports multiple forwarders, retry configuration, replay operations, and per-forwarder rate limits.
  </Card>

  <Card title="Proxy bucket" icon="repeat">
    Supports exactly one forwarder. Retry configuration and rate limiting are not available because one destination owns the upstream response.
  </Card>
</CardGroup>

<Warning>
  A proxy bucket rejects a second forwarder and rejects any retry or rate-limit settings. Create a queued bucket when you need multiple destinations or asynchronous delivery controls.
</Warning>

## Delivery controls

These values are stored on the forwarder. All of them can be adjusted from the forwarder's settings page after creation, subject to the bucket mode rules above.

<AccordionGroup>
  <Accordion title="Timeout">
    Allowed range: `5000`–`60000` ms in `1000` ms steps. Default: `20000` ms. Repost marks a delivery attempt as timed out if the destination does not respond within this window.
  </Accordion>

  <Accordion title="Retries (queue buckets only)">
    Allowed range: `0`–`3`. Default at creation: `3`. Set retries to `0` to disable them. Repost retries connection failures and responses with status `408`, `429`, or `5xx`. All other `4xx` responses are treated as final.
  </Accordion>

  <Accordion title="Retry delay (queue buckets only)">
    Allowed range: `5000`–`60000` ms. Default: `15000` ms. This sets the initial retry window. Retry waits use full jitter — Repost picks a delay between `0` and the current window, floors it at `1000` ms, then grows the window by the backoff multiplier after each attempt.
  </Accordion>

  <Accordion title="Backoff multiplier (queue buckets only)">
    Allowed range: `0.5x`–`3.0x`. Default: `2.0x`. The retry window is multiplied by this value after each failed attempt.
  </Accordion>

  <Accordion title="Max retry delay (queue buckets only)">
    Allowed range: `60000`–`1800000` ms. Default: `900000` ms. The retry window is capped at this value regardless of how many times the backoff multiplier is applied.
  </Accordion>

  <Accordion title="Rate limit (queue buckets only)">
    Off by default. When enabled, delivery is capped at `5`–`500` requests per second in steps of `5`.
  </Accordion>
</AccordionGroup>

<Note>
  Retry waits use full jitter. Repost picks a delay between `0` and the current retry window, floors it at `1000` ms, then grows the window by the backoff multiplier until it is capped by the max retry delay.
</Note>

## External target restrictions

When you create an external forwarder, Repost validates the destination before saving. The following targets are blocked:

* `localhost` and loopback addresses
* Private or reserved IP ranges
* Single-label hostnames (e.g. `myserver` with no domain)
* Internal-only hostnames
* Hostnames that resolve via DNS to any of the above blocked addresses

## Common errors

<AccordionGroup>
  <Accordion title="Name is already taken">
    Forwarder names must be unique within a bucket. Choose a different name or rename the existing forwarder first.
  </Accordion>

  <Accordion title="Proxy bucket already has a forwarder">
    Proxy buckets support exactly one forwarder. To add a second destination, convert your setup to a queued bucket.
  </Accordion>

  <Accordion title="Retry or rate limit rejected for proxy">
    Proxy forwarders do not support retry configuration or rate limiting. These controls are available only on queued bucket forwarders.
  </Accordion>

  <Accordion title="External target is not allowed">
    The destination you entered points to a blocked address. Use a public hostname that resolves to a non-private IP address.
  </Accordion>

  <Accordion title="Forwarder type cannot be changed">
    Type is set at creation and is immutable. Create a new forwarder with the correct type instead.
  </Accordion>

  <Accordion title="Delete is blocked by an active replay">
    A forwarder cannot be deleted while a replay job is pending, estimating, processing, or paused. Cancel the replay or wait for it to complete before deleting.
  </Accordion>
</AccordionGroup>
