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

# Stream webhook events live with Server-Sent Events

> Connect to GET /log-stream to receive captured webhook events in real time over Server-Sent Events, without polling the /logs query endpoint.

The `/log-stream` endpoint pushes captured webhook events to connected clients over Server-Sent Events (SSE) as they arrive. Use it when you want immediate visibility into incoming traffic without writing a polling loop against `/logs`.

The main difference from `/logs` is timing: `/logs` queries the stored read model and is better for filtering historical events or building reports, while `/log-stream` delivers events the moment they are captured, which is useful for watching a live test, monitoring a staging environment, or debugging a flaky integration in real time.

## Connecting to the stream

Send a `GET` request to `/log-stream` and keep the connection open. The server holds the connection and sends events as they are captured.

```bash theme={null}
curl -N "https://<run-id>.runs.apify.net/log-stream"
```

<Note>
  The `-N` flag disables curl's output buffering so SSE frames appear as they arrive rather than being held until the buffer fills.
</Note>

### Authentication

When `authKey` is configured, include your key as a Bearer token:

```bash theme={null}
curl -N "https://<run-id>.runs.apify.net/log-stream" \
  -H "Authorization: Bearer YOUR_KEY"
```

You can also pass the key as a query parameter: `?key=YOUR_KEY`.

## Wire format

The stream uses plain SSE `data:` frames for event payloads. Comment lines starting with `:` carry connection and keepalive traffic.

```text theme={null}
: connected

data: {"id":"evt_123","webhookId":"wh_abc123","method":"POST","statusCode":200}

: heartbeat

data: {"id":"evt_124","webhookId":"wh_abc123","method":"POST","statusCode":200}

: heartbeat
```

* The server sends `: connected` immediately after the connection is established.
* Heartbeats (`: heartbeat`) are sent every **30 seconds** as SSE comments to keep the connection alive through proxies and load balancers.
* Event frames use the `data:` field only — there is no named `event:` type in the current implementation.
* Event payloads are the live ingestion events produced during capture, not the paginated response shape from `/logs`.

## Concurrent client limit

The server allows up to **100** concurrent SSE connections. When this limit is reached, new connection attempts receive `503 Service Unavailable`. Existing connections are not affected.

## Filtering events

The `/log-stream` endpoint does not support server-side filtering by webhook ID or other fields. If you only want events from a specific webhook, filter them client-side after parsing the `data:` payload.

## Browser / EventSource example

```javascript theme={null}
const stream = new EventSource(
  "https://<run-id>.runs.apify.net/log-stream"
);

stream.onmessage = (event) => {
  const data = JSON.parse(event.data);

  // Filter locally for a specific webhook
  if (data.webhookId === "wh_abc123") {
    console.log("Captured event:", data);
  }
};

stream.onerror = (err) => {
  console.error("Stream error:", err);
  stream.close();
};
```

<Tip>
  When `authKey` is configured, `EventSource` does not support custom headers directly. Pass the key as a query parameter instead: `new EventSource("/log-stream?key=YOUR_KEY")`.
</Tip>
