Listener Documentation

Authentication

Production deployments authenticate via OpenID Connect (OIDC) using Keycloak. End users sign in through the application's /login/index.html page, which obtains and refreshes access tokens automatically.

For local development or migration, a legacy OAuth2 password grant is available at POST /api/auth/token when SQUAWK_STUB_AUTH_ENABLED=true. It accepts application/x-www-form-urlencoded data with grant_type=password, username, and password.

You can inspect the current user's roles and identity via GET /api/auth/me.

WebSocket Connections

Append ?token=<jwt> to the WebSocket URL:

const wsUrl = 'wss://example.com/api/ws?token=' + encodeURIComponent(token)
const client = new SquawkWebSocket(wsUrl, audioContext)

HTTP API Requests

Include an Authorization: Bearer <jwt> header. The built-in API client adds this header automatically once a user is authenticated.

Get a Token (stub auth only)

Not authenticated

SquawkWebSocket Library

The easiest way to integrate with Squawk is using the SquawkWebSocket library. This standalone ES module handles WebSocket connections, audio playback, and stream management.

Quick Start

import { SquawkWebSocket } from 'https://example.com/lib/listener_websocket.js'

const token = 'your_jwt_token'
const audioContext = new (window.AudioContext || window.webkitAudioContext)()
const client = new SquawkWebSocket('wss://example.com/api/ws?token=' + encodeURIComponent(token), audioContext)

client.on('connected', () => {
  console.log('Connected!')
  client.subscribe(['asset:equities'])
})

client.on('stream_start', (msg) => {
  console.log('Stream started:', msg.keywords)
})

client.connect()

API Reference

Constructor

new SquawkWebSocket(url: string, audioContext: AudioContext)
Parameter Type Required Description
url string Required WebSocket endpoint URL
audioContext AudioContext Required Browser AudioContext instance for audio playback

Methods

Method Parameters Description
connect() none Connect to the WebSocket server
disconnect() none Disconnect from the server
subscribe() keywords: string[] Subscribe to keywords
unsubscribe() keywords: string[] Unsubscribe from keywords
ping() none Send a keepalive ping
get_status() none Get current connection status
unlock_audio() none Unlock audio after user gesture (call in response to click/tap)
is_audio_locked() none Check if audio is locked due to autoplay policy
on() event: string,
handler: function
Listen for events

Events

Event Data Description
connected none WebSocket connected
disconnected CloseEvent WebSocket disconnected. Check event.code — 4003 means auth failed
stream_start StreamStartMessage Audio stream started (receives StreamStartMessage)
stream_end { session_id: string } Audio stream ended
subscribed { keywords: string[] } Subscription confirmed
clip_received ClipMessage Historical clip received
audio_locked none Autoplay blocked - user interaction needed. Call unlock_audio() after user gesture.
audio_unlocked none Audio successfully unlocked after user interaction
error Error Error occurred
status_change ConnectionStatus Connection status changed

WebSocket Endpoint

WS /api/ws

Connect to this endpoint to establish a WebSocket connection for receiving audio streams. The server accepts text commands (JSON) and sends both text messages (JSON metadata) and binary messages (audio data).

Client-to-Server Messages

Subscribe

Subscribe to one or more keywords to receive matching audio streams.

{
  "type": "subscribe",
  "keywords": ["asset:equities", "region:us"]
}

Unsubscribe

Remove subscriptions for specific keywords.

{
  "type": "unsubscribe",
  "keywords": ["asset:equities"]
}

Ping

Keep the connection alive. The server will respond with a pong.

{
  "type": "ping"
}

Server-to-Client Messages

Stream Start

Sent when a broadcaster starts streaming audio matching your subscribed keywords.

{
  "type": "stream_start",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "keywords": ["asset:equities"],
  "content_type": "audio/webm;codecs=opus",
  "timestamp": "2024-01-15T10:30:00Z"
}

Stream End

Sent when the broadcaster stops streaming.

{
  "type": "stream_end",
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}

Clip

Sent when a historical clip is available. Followed by binary audio data.

{
  "type": "clip",
  "clip_id": "clip-123",
  "keywords": ["asset:equities"],
  "content_type": "audio/webm",
  "size_bytes": 102456,
  "timestamp": "2024-01-15T10:00:00Z"
}

Subscribed

Confirmation that your subscription was registered.

{
  "type": "subscribed",
  "keywords": ["asset:equities"]
}

Error

Sent when an error occurs.

{
  "type": "error",
  "message": "Invalid message format"
}

Binary Audio Data

After a stream_start message, the server sends binary audio chunks as ArrayBuffer messages. The SquawkWebSocket library automatically handles these and feeds them to the audio element.

Similarly, after a clip message, the next binary message contains the complete clip audio data.

Live Demo

This demo uses the SquawkWebSocket library to connect to /api/ws and subscribes to asset:equities. When a broadcaster transmits with this keyword, audio will play automatically.

Disconnected

Demo Source Code

JavaScript

CSS

HTML