Эта страница переведена машинным способом. Английская версия является источником и может быть точнее или новее. Открыть на английском

Browser WebSocket

Подключайтесь к WebSocket API finlight.me напрямую из веб-браузера с помощью нативного WebSocket API. Это идеально для панелей, торговых терминалов и любых фронтенд-приложений, которым нужны обновления статей в реальном времени без серверного прокси.


Как это работает

  1. Подключитесь к wss://wss.finlight.me (обогащённый) или wss://wss.finlight.me/raw (raw), указав ключ API как параметр запроса
  2. Подпишитесь, отправив JSON-сообщение с вашими критериями фильтра и clientNonce
  3. Получите сообщение admit, подтверждающее ваше подключение, а затем сообщения sendArticle по мере поступления статей
  4. Поддерживайте соединение, отправляя сообщения ping каждые 25 секунд
  5. Отключитесь, вызвав ws.close()

URL подключения

  • Name
    Обогащённый
    Type
    wss://wss.finlight.me
    Description

    Статьи с полным обогащением: анализ тональности, извлечение сущностей, категории и полное содержимое (в зависимости от уровня подписки).

  • Name
    Raw
    Type
    wss://wss.finlight.me/raw
    Description

    Низколатентные raw-статьи без обогащения. Лучше всего для случаев, где скорость прежде всего и нужно получать статьи как можно быстрее.

Параметры запроса

  • Name
    apiKey
    Type
    string
    Description

    Ваш ключ API finlight. Используется для аутентификации, поскольку браузерный WebSocket не может задавать пользовательские заголовки.

  • Name
    takeover
    Type
    string
    Description

    Установите "true", чтобы автоматически заменять самое старое подключение при достижении лимита одновременных подключений.

  • Name
    clientVersion
    Type
    string
    Description

    Необязательный идентификатор вашего клиентского приложения. Напр. "my-dashboard/1.0"


Сообщение подписки

После открытия подключения отправьте JSON-сообщение для подписки на статьи. Сервер ответит сообщением admit, а затем начнёт отправлять подходящие статьи.

  • Name
    clientNonce
    Type
    string
    Description

    Уникальный идентификатор (напр., UUID) для этого запроса подписки. Сервер возвращает его в ответе admit.

  • Name
    query
    Type
    string
    Description

    Поисковый запрос для поиска релевантных статей. Поддерживает расширенные запросы.

  • Name
    sources
    Type
    string[]
    Description

    Фильтрация по доменам источников. Напр. ["www.reuters.com", "www.cnbc.com"]

  • Name
    excludeSources
    Type
    string[]
    Description

    Исключает определённые домены источников.

  • Name
    tickers
    Type
    string[]
    Description

    Фильтрация по тикерам. Напр. ["AAPL", "NVDA"] (только обогащённый)

  • Name
    countries
    Type
    string[]
    Description

    Фильтрация по кодам стран в ISO 3166-1 alpha-2. Напр. ["US", "DE"] (только обогащённый)

  • Name
    language
    Type
    string
    Description

    Фильтрация по языку (ISO 639-1). По умолчанию en — возвращает только английский и исключает другие языки — см. Язык и охват.


Сообщения сервера

Сервер отправляет JSON-сообщения с полем action, указывающим тип сообщения:

  • Name
    admit
    Type
    object
    Description

    Отправляется после успешного рукопожатия. Содержит leaseId, serverNow (метка времени) и ваш clientNonce.

  • Name
    sendArticle
    Type
    object
    Description

    Новая статья, соответствующая вашей подписке. Данные статьи находятся в поле data.

  • Name
    pong
    Type
    object
    Description

    Ответ на ваш «сердечный ритм» ping.

  • Name
    preempted
    Type
    object
    Description

    Ваше подключение было заменено другой сессией (когда другой клиент подключился с takeover: true).

  • Name
    error
    Type
    object
    Description

    Произошла ошибка. Подробности см. в поле data или error.


WEBSOCKETБраузер

Полный пример

Минимальный, не зависящий от фреймворка браузерный WebSocket-клиент с автоматическим переподключением и «сердечным ритмом»:

  • Аутентифицируется через параметры запроса
  • Отправляет сообщение подписки при подключении
  • Поддерживает интервал «сердечного ритма» 25 секунд
  • Переподключается с экспоненциальной задержкой (от 500 мс до 10 с)
  • Обрабатывает все типы сообщений сервера

Browser Client

WEBSOCKET
wss://wss.finlight.me
const API_KEY = 'YOUR_API_KEY'
const WSS_URL = 'wss://wss.finlight.me' // Use '/raw' path for raw articles

let ws = null
let pingInterval = null
let reconnectTimeout = null
let reconnectAttempt = 0

function connect(filters = {}) {
  const params = new URLSearchParams({
    apiKey: API_KEY,
    takeover: 'true',
    clientVersion: 'my-app/1.0',
  })
  const url = `${WSS_URL}?${params}`

  ws = new WebSocket(url)

  ws.onopen = () => {
    console.log('Connected')
    reconnectAttempt = 0

    // Send subscription with filters
    ws.send(JSON.stringify({
      clientNonce: crypto.randomUUID(),
      query: filters.query || '',
      language: filters.language || 'en',
      sources: filters.sources || [],
      tickers: filters.tickers || [],
      countries: filters.countries || [],
    }))

    // Start heartbeat
    pingInterval = setInterval(() => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
          action: 'ping',
          t: Date.now(),
        }))
      }
    }, 25000)
  }

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data)

    switch (msg.action) {
      case 'admit':
        console.log('Admitted, lease:', msg.leaseId)
        break
      case 'sendArticle':
        console.log('Article:', msg.data.title)
        // Handle the article here
        break
      case 'pong':
        break // Heartbeat OK
      case 'preempted':
        console.warn('Connection replaced')
        break
      case 'error':
        console.error('Server error:', msg.data || msg.error)
        break
    }
  }

  ws.onclose = (event) => {
    clearInterval(pingInterval)

    // Don't reconnect on policy violations
    if (event.code === 1008 || event.code === 4002) {
      console.error('Connection blocked')
      return
    }

    // Exponential backoff reconnect
    const delay = Math.min(500 * 2 ** reconnectAttempt, 10000)
    reconnectAttempt++
    console.log(`Reconnecting in ${delay}ms...`)
    reconnectTimeout = setTimeout(() => connect(filters), delay)
  }

  ws.onerror = () => console.error('WebSocket error')
}

function disconnect() {
  clearInterval(pingInterval)
  clearTimeout(reconnectTimeout)
  if (ws) ws.close(1000)
}

// Usage
connect({ query: 'Nvidia', language: 'en', countries: ['US'] })

admit Response

{
  "action": "admit",
  "leaseId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
  "serverNow": 1708185600000,
  "clientNonce": "your-uuid-here"
}

sendArticle Response

{
  "action": "sendArticle",
  "data": {
    "link": "https://www.reuters.com/technology/nvidia-2026-02-17",
    "source": "www.reuters.com",
    "title": "Nvidia Reports Record Revenue",
    "summary": "Nvidia announced record quarterly revenue...",
    "publishDate": "2026-02-17T10:30:00Z",
    "language": "en",
    "sentiment": "positive",
    "confidence": 0.92,
    "countries": ["US"],
    "categories": ["markets", "technology"],
    "companies": [
      {
        "name": "NVIDIA Corporation",
        "ticker": "NVDA",
        "country": "US"
      }
    ]
  }
}

Обогащённый vs Raw

ФункцияОбогащённый (/)Raw (/raw)
Анализ тональностиДаНет
Извлечение сущностей (компании)Да (зависит от уровня)Нет
КатегорииДаНет
Полное содержимоеДа (зависит от уровня)Нет
ЗадержкаСтандартнаяМинимальная
Фильтр: tickersДаНет
Фильтр: countriesДаНет
Фильтр: query, sources, languageДаДа

Что дальше?