Browser WebSocket
Conecte-se à API WebSocket do finlight.me diretamente de um navegador web usando a API WebSocket nativa. Isso é ideal para painéis, terminais de trading e qualquer aplicação frontend que precise de atualizações de artigos em tempo real sem um proxy do lado do servidor.
A API WebSocket do navegador não suporta cabeçalhos personalizados. A autenticação é feita por meio de parâmetros de consulta em vez do cabeçalho x-api-key. Sua chave de API ficará visível na URL do WebSocket — use esta abordagem apenas em ambientes onde isso seja aceitável (ex.: painéis autenticados). Nunca exponha sua chave de API em código do lado do cliente acessível ao público.
Como funciona
- Conecte-se a
wss://wss.finlight.me(enriquecido) ouwss://wss.finlight.me/raw(raw) com sua chave de API como parâmetro de consulta - Inscreva-se enviando uma mensagem JSON com seus critérios de filtro e um
clientNonce - Receba uma mensagem
admitconfirmando sua conexão, seguida de mensagenssendArticleà medida que os artigos chegam - Mantenha ativa a conexão enviando mensagens
pinga cada 25 segundos - Desconecte-se chamando
ws.close()
URLs de conexão
- Name
Enriquecido- Type
- wss://wss.finlight.me
- Description
Artigos com enriquecimento completo: análise de sentimento, extração de entidades, categorias e conteúdo completo (conforme seu nível de assinatura).
- Name
Raw- Type
- wss://wss.finlight.me/raw
- Description
Artigos raw de baixa latência sem enriquecimento. Melhor para casos de uso em que a velocidade vem primeiro e você precisa dos artigos o mais rápido possível.
Parâmetros de consulta
- Name
apiKey- Type
- string
- Description
Sua chave de API do finlight. Usada para autenticação, já que o WebSocket do navegador não pode definir cabeçalhos personalizados.
- Name
takeover- Type
- string
- Description
Defina como
"true"para substituir automaticamente a conexão mais antiga quando seu limite de conexões simultâneas for atingido.
- Name
clientVersion- Type
- string
- Description
Identificador opcional para sua aplicação cliente. Ex.:
"my-dashboard/1.0"
Mensagem de inscrição
Após a conexão abrir, envie uma mensagem JSON para se inscrever nos artigos. O servidor responderá com uma mensagem admit e então começará a enviar os artigos correspondentes.
- Name
clientNonce- Type
- string
- Description
Um identificador único (ex.: UUID) para esta requisição de inscrição. O servidor o devolve na resposta
admit.
- Name
query- Type
- string
- Description
Consulta de busca para encontrar artigos relevantes. Suporta consultas avançadas.
- Name
sources- Type
- string[]
- Description
Filtra por domínios de fonte. Ex.:
["www.reuters.com", "www.cnbc.com"]
- Name
excludeSources- Type
- string[]
- Description
Exclui domínios de fonte específicos.
- Name
tickers- Type
- string[]
- Description
Filtra por símbolos de ticker. Ex.:
["AAPL", "NVDA"](somente enriquecido)
- Name
countries- Type
- string[]
- Description
Filtra por códigos de país em ISO 3166-1 alpha-2. Ex.:
["US", "DE"](somente enriquecido)
- Name
language- Type
- string
- Description
Filtra por idioma (ISO 639-1). O padrão é
en, que retorna apenas inglês e exclui outros idiomas — consulte Idioma e cobertura.
Mensagens do servidor
O servidor envia mensagens JSON com um campo action que indica o tipo de mensagem:
- Name
admit- Type
- object
- Description
Enviada após um handshake bem-sucedido. Contém
leaseId,serverNow(marca de tempo) e seuclientNonce.
- Name
sendArticle- Type
- object
- Description
Um novo artigo que corresponde à sua inscrição. Os dados do artigo estão no campo
data.
- Name
pong- Type
- object
- Description
Resposta ao seu batimento
ping.
- Name
preempted- Type
- object
- Description
Sua conexão foi substituída por outra sessão (quando outro cliente se conectou com
takeover: true).
- Name
error- Type
- object
- Description
Ocorreu um erro. Verifique o campo
dataouerrorpara os detalhes.
Exemplo completo
Um cliente WebSocket de navegador mínimo e independente de framework, com reconexão automática e batimento:
- Autentica-se via parâmetros de consulta
- Envia uma mensagem de inscrição ao conectar
- Mantém um intervalo de batimento de 25 segundos
- Reconecta-se com recuo exponencial (de 500 ms a 10 s)
- Trata todos os tipos de mensagens do servidor
Browser Client
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"
}
]
}
}
Enriquecido vs Raw
| Função | Enriquecido (/) | Raw (/raw) |
|---|---|---|
| Análise de sentimento | Sim | Não |
| Extração de entidades (empresas) | Sim (depende do nível) | Não |
| Categorias | Sim | Não |
| Conteúdo completo | Sim (depende do nível) | Não |
| Latência | Padrão | A mais baixa |
Filtro: tickers | Sim | Não |
Filtro: countries | Sim | Não |
Filtro: query, sources, language | Sim | Sim |
As inscrições do Raw WebSocket suportam apenas os filtros query, sources, excludeSources e language. Os filtros de ticker e país são ignorados silenciosamente no endpoint raw.
O que vem a seguir?
- Revise a página de Inscrição enriquecida para o modelo de artigo completo e todos os campos disponíveis
- Confira Inscrição raw para detalhes específicos de raw
- Aprenda sobre Criação de consultas avançadas para refinar seus filtros
- Use a API REST para buscas de artigos históricos junto com seu fluxo em tempo real