Skip to main content
Webhooks are awkward to develop against. Your handler has to be reachable from the internet before you can see a single event, which usually means deploying unfinished code or running a tunnel. Forwarding removes that. The Bachs CLI holds an outbound connection to Bachs and hands each event to a port on your machine, so you can write and debug your handler against real signed events with nothing deployed and no public URL.
This guide assumes the CLI is installed and paired with your account. If it is not, install it and run bachs login first. It takes about a minute.

Start forwarding

Point the CLI at the port your handler listens on.
Forward every event
Output
Copy the signing secret into your local environment. It is created for this session, so your production endpoint’s secret stays in production while your verification code runs against real signed requests. To forward only what you are working on, name the events:
Forward two event types

Send yourself an event

Leave listen running and open a second terminal. You do not need a real payment to exercise your handler:
Emit a sample event
The event goes through the ordinary delivery path, so it is signed and recorded exactly like a real one. It is sandbox only, for the good reason that a fake collection.succeeded in production could have you fulfil an order nobody paid for. You can also redeliver something that already happened:
Replay a past event
Every delivery prints as it arrives, with the status your handler returned and how long it took:
Terminal
A ✓ means your handler returned a 2xx. Anything else shows the status or the connection error inline, which is usually enough to find the problem without adding logging.
Seeing nothing at all? Your endpoint filter may not include the type you are sending. bachs events list --undelivered shows events that matched no destination.

Verify the signature

This is the part worth getting right locally, because a handler that verifies incorrectly usually still looks fine until it starts rejecting live traffic. Each forwarded request carries X-Bachs-Signature-V2 in the form t={timestamp},v1={signature}. Read the raw body before parsing it, because re-serializing JSON changes the bytes and breaks verification.
Verify a forwarded request
Accept the request if any v1 value matches. The header carries one signature per currently valid secret, so a handler that checks only the first will start rejecting deliveries during a secret rotation.
Because the forwarded request is signed with this session’s own secret, the code above is the same code you will run in production. Only the secret differs.

How it works

Your machine opens the connection outbound to Bachs, so nothing needs to reach you. There is no public URL, no inbound port, and no firewall change, and it works behind NAT and on corporate networks because it is an ordinary outgoing HTTPS connection. A session is a webhook destination like any other, so event filtering, delivery records, and the Events view all behave the same way. The only difference is the last step: instead of sending to a URL, Bachs hands the event to the connection your machine is holding, and the CLI sends it to your local port. Press Ctrl-C and the session closes. Your registered destinations are untouched: starting a session changes nothing in your account, and stopping one leaves nothing behind. If your machine sleeps or loses its network, the CLI reconnects on its own and tells you while it is trying.
Deliveries to a forwarding session are not retried. If your handler is down, your machine is asleep, or your code returns a 500, the event is shown as failed and dropped. You are watching the terminal, so a backlog arriving hours later would not help you. Registered URL destinations retry as normal.

Replaying without the CLI

Replay is a plain API call and needs no session. It works against your registered destinations too, which makes it useful in production and not only while developing:
Replay over HTTP
Response

Going live

Forwarding works against production too. bachs whoami tells you which environment you are paired with, and the CLI marks a live session so you can tell the two apart while forwarding. Your customers’ real events reach your machine on a live session, so use the sandbox unless you have a reason not to. Once your handler is deployed, register its URL as a destination and it receives events the same way, with retries. See Setting up webhooks.

Next steps

  • Bachs CLI for everything else the CLI does, including calling any API operation from the terminal.
  • Setting up webhooks for registering a destination your server can receive on.
  • Replay webhook events for the full replay API, including lookup by charge or reference.
  • Events to inspect deliveries and responses in the dashboard.