Skip to main content
On your laptop you have no public URL for a webhook, and you do not need one: open the live event stream, GET /v1/stream, and your app’s events arrive over a WebSocket as they happen. It is resumable with after, so a restart of your process never loses an event.
TypeScript

How it works

  1. Connect to wss://api.flow.engineer/v1/stream with Authorization: Bearer $FLOW_MESSAGING_KEY. Filter with type (repeat it for several types).
  2. Every text frame is one JSON object. event frames carry the same event a webhook would receive.
  3. Reply over the API (POST /v1/conversations/{conversation_id}/messages), or send a send frame on the same socket; each send gets one ack or error frame back, matched by ref (your idempotency key).
  4. Keep the id of the last event you handled. When you reconnect, or when the server sends a reconnect frame before it restarts, connect again with after set to that ID: the stream replays everything after it, then goes live.
The TypeScript SDK’s flow.events.stream() does the reconnecting and resuming for you. In other languages use any WebSocket client that can set a header:
Python
See The live stream for the frame types and browser authentication.

Testing your webhook handler locally

If your production code is a webhook handler, you can still develop it on localhost: read the stream and pass each event to your handler function directly, then deploy the same handler behind a real webhook endpoint. The stream and your webhook endpoints read the same log and do not interfere: both receive events. The CLI wraps the stream for webhook handlers: listen --forward-to reads GET /v1/stream and POSTs each event to your local URL, signed like a real delivery.
  • Each event is POSTed with the same headers and signature as a real webhook delivery (Flow-Signature, Flow-Event-Id, Flow-Event-Type, Flow-Version), signed with FLOW_MESSAGING_WEBHOOK_SECRET (made and saved to .env if it is not set).
  • If your handler answers a message.received with {"reply": ...}, listen sends the reply into the conversation, with the event’s ID as the idempotency key, as the API does for real webhooks.
  • Flags: --events a,b (only these event types), --after evt_... (replay from this event first, then go live), --secret whsec_... (the signing secret to use). Without --forward-to, listen only prints events.

Tips

  • Use a test key while developing: only people who joined your sandbox can reach your agent.
  • To run past events through new code, find the event just before them with GET /v1/events and pass its ID as after.
  • The stream is for long-running processes. In production, serverless apps usually use webhooks.