Skip to content

SSE Endpoints

API reference for Server-Sent Events endpoints.

Subscribe to Topic

Establish an SSE connection to receive events for a topic.

Request

GET /events/{topic} HTTP/1.1
Host: proxy.example.com
Authorization: Bearer <jwt-token>
Accept: text/event-stream
Cache-Control: no-cache

Path Parameters

Parameter Type Description
topic string Topic name to subscribe to

Headers

Header Required Description
Authorization Yes* Bearer token for authentication
Accept No Should be text/event-stream
Cache-Control No Set to no-cache for real-time
Last-Event-ID No Resume from specific event ID

*Required when require_authentication = true

Response

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Access-Control-Allow-Origin: *
X-Accel-Buffering: no

Event Stream Format

event: message
id: 1703894400000-001
data: {"type": "notification", "message": "Hello!"}

event: message
id: 1703894400001-002
data: {"type": "update", "data": {"count": 42}}

: keepalive

Event Fields

Field Description
event Event type (default: "message")
id Unique event identifier
data Event payload (JSON or text)
retry Reconnection interval (ms)

Example: curl

curl -N "http://localhost:8080/events/notifications" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Accept: text/event-stream"

Example: JavaScript

const eventSource = new EventSource(
  'http://localhost:8080/events/notifications',
  {
    headers: {
      'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIs...'
    }
  }
);

eventSource.addEventListener('message', (e) => {
  const data = JSON.parse(e.data);
  console.log('Received:', data);
});

eventSource.addEventListener('error', (e) => {
  if (e.eventPhase === EventSource.CLOSED) {
    console.log('Connection closed');
  }
});

Example: Python

import sseclient
import requests

url = 'http://localhost:8080/events/notifications'
headers = {
    'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIs...',
    'Accept': 'text/event-stream'
}

with requests.get(url, headers=headers, stream=True) as response:
    client = sseclient.SSEClient(response)
    for event in client.events():
        print(f"Event: {event.event}")
        print(f"ID: {event.id}")
        print(f"Data: {event.data}")

Example: Go

package main

import (
    "bufio"
    "fmt"
    "net/http"
    "strings"
)

func main() {
    req, _ := http.NewRequest("GET",
        "http://localhost:8080/events/notifications", nil)
    req.Header.Set("Authorization", "Bearer eyJhbGciOiJIUzI1NiIs...")
    req.Header.Set("Accept", "text/event-stream")

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    scanner := bufio.NewScanner(resp.Body)
    for scanner.Scan() {
        line := scanner.Text()
        if strings.HasPrefix(line, "data: ") {
            fmt.Println("Received:", line[6:])
        }
    }
}

Error Responses

401 Unauthorized

Authentication failed.

HTTP/1.1 401 Unauthorized
Content-Type: text/plain

Authentication required

Causes: - Missing Authorization header - Invalid JWT token - Expired JWT token - Webhook verification failed

403 Forbidden

Not authorized for this topic.

HTTP/1.1 403 Forbidden
Content-Type: text/plain

Access denied to topic

429 Too Many Requests

Rate limit exceeded.

HTTP/1.1 429 Too Many Requests
Content-Type: text/plain
Retry-After: 60

Rate limit exceeded

503 Service Unavailable

Server at capacity.

HTTP/1.1 503 Service Unavailable
Content-Type: text/plain
Retry-After: 30

Too many connections

Reconnection

SSE clients automatically reconnect on disconnection.

Last-Event-ID

Send the last received event ID to resume:

GET /events/notifications HTTP/1.1
Last-Event-ID: 1703894400000-001

The server may replay missed events (implementation-dependent).

Retry Interval

The server can suggest a retry interval:

retry: 5000

Clients should wait this many milliseconds before reconnecting.

Health Check

Check proxy health status.

Request

GET /health HTTP/1.1
Host: proxy.example.com

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "status": "healthy",
  "connections": 12345,
  "uptime_seconds": 86400
}

CORS

Cross-Origin Resource Sharing headers are included:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type, Last-Event-ID

Configure allowed origins:

[http]
cors_allowed_origins = "https://app.example.com"

Rate Limits

Default rate limits per IP:

Limit Value
Requests per window 100
Window duration 60 seconds

Configure in proxy.toml:

[http]
rate_limit_per_ip = 100
rate_limit_window_sec = 60

Next Steps