Skip to content

Endpoints & Destinations

An endpoint is where you send webhooks. A destination is where SignalBin sends them next.

Creating an endpoint

Every endpoint gets a hosted URL in the form:

https://signalbin.work/{workspace-slug}/{endpoint-slug}

Point a webhook source (Stripe, GitHub, your own backend, whatever) at that URL, and every request it sends gets captured, stored, and shown in your workspace. No configuration is required beyond creating the endpoint.

To create one:

  1. Go to Endpoints in the sidebar and click New endpoint.
  2. Fill in Name, which is only a display label.
  3. Fill in Slug, which becomes part of the URL. The box comes pre-filled with a generated value; Generate swaps in a different one.
  4. Click Create endpoint. The endpoint is enabled immediately and ready to receive traffic.

Your endpoints are listed under the Receiving endpoints heading, with the full URL in the URL column. Click an endpoint's name (or Manage in its row menu, the button with three dots) to open its detail page, where the Overview tab repeats the same address as the Capture URL.

TIP

Endpoint slugs are long by design (24 to 64 characters, lowercase letters, digits, and hyphens) so a leaked or guessed URL isn't a realistic way to reach your endpoint. That said, an endpoint URL isn't a secret on its own. See below if you need to gate who can post to it.

The row menu also holds Rename, Disable, and Delete. Disabling an endpoint stops ingestion without deleting anything: the hosted URL starts behaving as though the endpoint never existed, and captures already stored stay visible. Senders see a "not found" error (404 endpoint_not_found).

The shared secret

Each endpoint can have an optional shared secret, which is a value the sender has to present before SignalBin will store anything.

An endpoint created in the web app starts without one. To add a secret, find the endpoint in the Endpoints list, open its row menu, and choose Rotate and reveal secret. SignalBin generates the value, copies it to your clipboard, and shows it once in a dialog with a Copy secret button. After you close that dialog only a short preview remains in the Secret column, so store the full value with your sender while you have it.

When a secret is set, a request is only accepted if it presents a matching value, either as a header or as a query parameter:

bash
curl -X POST https://signalbin.work/{workspace-slug}/{endpoint-slug} \
  -H "X-SignalBin-Secret: $ENDPOINT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"hello":"world"}'
https://signalbin.work/{workspace-slug}/{endpoint-slug}?secret={value}

A request that doesn't carry the right secret is turned away and never stored. The sender gets an authentication error (401 invalid_endpoint_secret). The secret query parameter is redacted out of the stored capture, so it won't show up in the webhook detail view.

Rotate and reveal secret invalidates the old value the moment you use it, so update your sender before rotating or its next request will be turned away. To go back to accepting anything sent to the URL, choose Remove secret from the same row menu and confirm with Remove secret in the dialog.

WARNING

The shared secret is access control, not payload signing. It's a static string checked on the way in, and it says nothing about the authenticity of the request body. SignalBin has no signing scheme of its own anywhere in the capture or forwarding path. See Headers & Signature Passthrough for how a provider's own signature headers are handled.

Network allowlist

Each endpoint can also restrict inbound traffic to specific source addresses, independent of the shared secret. If both are configured, a request must satisfy both to be captured.

Open the endpoint and go to its Network allowlist tab. Type a CIDR range or a bare IP into the box (it suggests 203.0.113.0/24 or 203.0.113.42 as examples) and click Add entry. Entries go in one at a time and appear below as removable chips, up to 20 of them. Click the small x on a chip to drop it.

A bare IP is accepted and normalized to a single-address CIDR (/32 for IPv4, /128 for IPv6) once saved. An empty list, the default, means any source can send to the endpoint. Requests are matched against the real client IP, resolved from X-Forwarded-For behind SignalBin's own reverse proxy.

A request from an address outside the allowlist is turned away and never stored. The sender gets a "forbidden" error (403 ip_not_allowed).

WARNING

Test deliveries sent from the play icon on the Endpoints page bypass both the shared secret and the network allowlist, since they aren't real inbound network requests. Don't be surprised when a test succeeds against a restrictive allowlist.

Destinations

A destination is a URL that receives a copy of everything an endpoint captures. Open the endpoint, go to its Destinations tab, and click Add destination.

Fan-out is unconditional: every enabled destination gets its own copy of every request the endpoint captures. There's no filtering, no routing rules, and no first-match-wins. If you have three enabled destinations, one incoming webhook becomes three outbound deliveries.

An endpoint can have up to 10 destinations. To pause delivery without losing the configuration, open the destination's row menu and choose Disable. That's usually the better move than deleting it. The same menu holds Edit and Delete.

Per-destination settings

The Add destination dialog asks for these. Editing an existing one opens the same dialog under the title Edit destination, with Save changes at the bottom.

FieldWhat it doesLimits
URLWhere the request is relayed.Must be http:// or https:// with a host, up to 2048 characters.
NameDisplay label only, shown in delivery history.Up to 120 characters.
MethodForces a specific HTTP verb regardless of the method the original request used. Leave it on Keep original to preserve the captured method.One of GET, POST, PUT, PATCH, DELETE.
Strip headersComma-separated header names removed before relaying.Up to 20 names, each up to 512 characters.
Add headersName and value pairs added before relaying, applied after stripping and overwriting any captured header of the same name.Up to 20 pairs, names and values up to 512 characters each.

A destination created through the web app starts enabled. One created through the API or MCP starts disabled unless you explicitly ask for enabled.

The Destinations table shows each destination's Status: Enabled or Disabled, plus a count of consecutive failed deliveries once there have been any. To see the outcome of a specific delivery attempt, open the captured webhook and read its Deliveries section.

WARNING

Updating a destination replaces every field. An update that omits stripHeaders or addHeaders clears them rather than leaving them alone, so send the full configuration each time you change one field through the API.

Target URL restrictions

A destination URL is refused at save time if its host resolves to a loopback, link-local, private, or unspecified address, or to the cloud metadata address 169.254.169.254. In the app you'll see "That URL isn't allowed - it must be a public http/https address"; over the API it's destination_target_not_allowed. The check exists so a destination can't be used to make SignalBin's servers call back into their own internal network.

A host that doesn't resolve yet is allowed, since a target may simply not be deployed at the time you configure it. The same address check runs again when the connection is actually made, so a URL that starts resolving somewhere internal later is still refused at that point.

How delivery works

Fan-out runs in the background. The provider that sent the webhook gets its response as soon as the capture is stored, so a slow or dead destination never delays or fails the original request, and delivery problems surface in the webhook's Deliveries section rather than in that response.

BehaviorValue
Attempts per destinationUp to 3 (first attempt plus 2 retries)
Retried onTransport failures and 5xx responses
Not retried on4xx responses, which count as a delivered payload the target rejected
Delay between attempts500ms, then 2s
Timeout per attempt10s
Budget per captured webhook30s across all of its destinations
RedirectsReturned to SignalBin as-is, never followed
ConcurrencyAll destinations for one capture are dialed at the same time

Every attempt is recorded on the captured webhook, so the same list shows both automatic fan-out and manual replays. See Webhooks & Replay for the fields it records.

Destination health tracks reachability rather than acceptance. A 4xx response means the target is up and answering, so it resets the consecutive failure count even though it isn't a 2xx.

Outbound deliveries aren't metered. Your credit is consumed by capturing a webhook, not by the copies fanned out from it.

Headers on relayed requests

Destinations receive the request as the provider sent it, not the redacted copy stored for display, so signature headers arrive with their real values.

Two adjustments always happen, on top of whatever strip and inject rules you configure:

  • Connection-scoped headers are dropped, since they describe the link the request arrived on rather than the message: Connection, Content-Length, Host, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailer, Transfer-Encoding, and Upgrade.
  • An X-Signalbin-Relay-Count header is added, carrying the number of hops the request has taken. A request that already carries a count of 1 or more is not relayed again, which is what stops a destination pointed back at a SignalBin ingest URL from looping.

Headers & Signature Passthrough covers what this means for verifying a provider's signature downstream.

Replays reuse destinations

Replaying a captured webhook delivers through the same destination configuration as fan-out, including strip and inject rules and the method override. See Webhooks & Replay.

The cli destination kind

When you run signalbin listen against an endpoint, it appears in the Destinations tab for the duration of the connection, tagged Live CLI session and showing a status of Connected. It's a visibility marker, not a real destination:

  • SignalBin's servers never dial it. Delivery to your terminal happens over the CLI's own SSE connection to GET /api/v1/events, not through the fan-out path.
  • It doesn't count against the 10-destination cap.
  • It disappears when the CLI session disconnects, and is swept automatically if a session dies without cleaning up after itself.
  • It has no row menu, so there's nothing to edit or delete. Stop the CLI and the row goes away.

If you're just trying to tail webhooks live while developing, signalbin listen is the right tool rather than a real http destination pointed at localhost, since a real destination can't reach your machine anyway.

API and MCP access

OperationRESTScopeMCP tool
List destinationsGET /api/v1/endpoints/{id}/destinationsendpoints:readlist_destinations
Create a destinationPOST /api/v1/endpoints/{id}/destinationsendpoints:writecreate_destination
Update a destinationPATCH /api/v1/endpoints/{id}/destinations/{destinationID}endpoints:writeupdate_destination
Delete a destinationDELETE /api/v1/endpoints/{id}/destinations/{destinationID}endpoints:writedelete_destination

The list response returns the endpoint alongside its destinations. See MCP Integration for connecting an MCP client.