Skip to main content
API de odds ao vivo

API de odds ao vivo: odds em tempo real via WebSocket

Uma API de odds ao vivo envia ao seu código a odd de uma casa de apostas no momento em que ela muda. A Odds-API.io transmite odds pré-jogo e ao vivo de 450+ casas de apostas em 34 esportes por uma única conexão WebSocket, com placares ao vivo, status e relógio da partida no mesmo stream.

O streaming via WebSocket é um add-on para qualquer plano pago. O REST está incluído em todos os planos.

Casas de apostas
450+
Esportes
34
Latência
<150ms
Janela de reenvio
24h

Por que WebSocket em vez de polling

No polling você pede as odds em intervalos fixos e recebe, na maioria das vezes, dados sem mudança. Um WebSocket fica aberto e só transporta os preços que mudaram, então você vê cada mudança antes e trafega muito menos dados.

Por que WebSocket em vez de polling
RecursoPolling RESTWebSocket
Como as mudanças chegam até vocêVocê pergunta de novo a cada intervaloEnviadas assim que um preço muda
LatênciaSeu intervalo de polling mais a requisição<150ms
ConexõesUma nova requisição HTTP a cada consultaUma conexão que fica aberta
Mercados retiradosÉ preciso reler o evento para perceberMensagens explícitas deleted e no_markets
Ideal paraScripts, cargas históricas e consultas rápidasApps de apostas ao vivo, modelos in-play e scanners de arbitragem

Conecte-se em poucas linhas

Abra wss://api.odds-api.io/v3/ws com sua API key e os mercados que você quer. A primeira mensagem é uma boas-vindas que confirma seus filtros e, depois disso, as odds chegam conforme mudam.

Node.js
// npm i ws
import WebSocket from 'ws'

const API = 'https://api.odds-api.io/v3'
const apiKey = process.env.ODDS_API_KEY
const markets = 'ML,Spread,Totals'
const eventIds = '63017989,63017990' // up to 10, for example from GET /v3/events/live
const bookmakers = 'Bet365,Unibet' // the bookmakers selected on your account
const board = new Map()
let lastSeq = 0
let needsRebuild = false

function connect() {
  const params = new URLSearchParams({ apiKey, markets, eventIds, channels: 'odds,scores,status' })
  if (lastSeq) params.set('lastSeq', String(lastSeq))

  const ws = new WebSocket(`wss://api.odds-api.io/v3/ws?${params}`)

  ws.on('message', (raw) => {
    const msg = JSON.parse(raw)
    if (msg.type === 'resync_required') {
      needsRebuild = true
      return ws.close()
    }
    if (msg.seq > lastSeq) lastSeq = msg.seq
    const key = `${msg.id}:${msg.bookie}`

    if (msg.type === 'created' || msg.type === 'updated') board.set(key, msg.markets)
    if (msg.type === 'deleted' || msg.type === 'no_markets') board.delete(key)
    if (msg.type === 'score') console.log(msg.id, msg.scores.home, msg.scores.away)
  })

  ws.on('error', (err) => console.error('WebSocket error:', err.message || err.code))

  ws.on('close', async () => {
    if (needsRebuild) lastSeq = await rebuildFromRest()
    setTimeout(connect, 2000)
  })
}

// Replay was not possible: reload the subscription from REST and resume from its seq
async function rebuildFromRest() {
  for (let attempt = 1; ; attempt++) {
    try {
      const params = new URLSearchParams({ apiKey, eventIds, bookmakers, markets, includeSeq: 'true' })
      const res = await fetch(`${API}/odds/multi?${params}`)
      const seq = Number(res.headers.get('X-OddsAPI-Seq'))
      if (!res.ok || !(seq > 0)) throw new Error(`snapshot not usable: ${res.status}`)
      const events = await res.json()
      board.clear()
      for (const event of events) {
        for (const [bookie, odds] of Object.entries(event.bookmakers)) board.set(`${event.id}:${bookie}`, odds)
      }
      needsRebuild = false
      return seq
    } catch (err) {
      console.error(`${err.message}, retry ${attempt}`)
      await new Promise((resolve) => setTimeout(resolve, Math.min(30000, 1000 * 2 ** attempt)))
    }
  }
}

connect()
Python
# pip install websockets
import asyncio
import json
import os
from urllib.parse import urlencode

import websockets

params = urlencode({
    "apiKey": os.environ["ODDS_API_KEY"],
    "markets": "ML,Spread,Totals",
    "leagues": "england-premier-league",
    "status": "live",
})

async def main():
    async with websockets.connect(f"wss://api.odds-api.io/v3/ws?{params}") as ws:
        async for message in ws:
            msg = json.loads(message)
            if msg["type"] == "updated":
                for market in msg["markets"]:
                    print(msg["id"], msg["bookie"], market["name"], market["odds"][0])

asyncio.run(main())

A compressão é obrigatória

Seu cliente precisa oferecer permessage-deflate ao se conectar. Isso reduz a banda de 3 a 5 vezes, e uma conexão sem ela é recusada com HTTP 426. A maioria das bibliotecas cuida disso para você:

A compressão é obrigatória
PlataformaBibliotecaCompressão
Node.jswsAtivada por padrão
NavegadorWebSocket nativoAtivada por padrão
PythonwebsocketsAtivada por padrão
Pythonwebsocket-clientNão suportada, use websockets
PHPamphp/websocket-clientAtivada por padrão (requer zlib)
PHPtextalk/websocketNão suportada, use amphp/websocket-client
Gogorilla/websocketDefina EnableCompression = true
.NETClientWebSocketDefina DangerousDeflateOptions (.NET 6+)

Tipos de mensagem

Toda mensagem é um objeto JSON com um type. As mensagens de odds usam o mesmo formato do endpoint /v3/odds, então um único parser atende os dois.

created
Uma casa de apostas adicionou um evento que você assina
updated
As odds mudaram. A mensagem traz o conjunto atual completo dos seus mercados para aquele evento e aquela casa
deleted
O evento foi removido ou a casa de apostas ficou fora do ar
no_markets
O evento continua listado, mas nenhum dos seus mercados está aberto
score
O placar ao vivo mudou (canal scores)
status
O evento passou para pendente, ao vivo, liquidado ou cancelado, com o placar atual (canal status)
clock
Um snapshot do relógio da partida a cada 30 segundos, aproximadamente, para cada evento ao vivo com o relógio rodando

Substitua, nunca mescle

Um mercado suspenso fica de fora da próxima mensagem updated, em vez de vir sinalizado. Sobrescreva a cada mensagem o que você tem para aquele evento e aquela casa, e uma odd retirada some do seu app sozinha.

updated
{
  "type": "updated",
  "seq": 482917,
  "timestamp": 1723992773,
  "id": "63017989",
  "bookie": "Bet365",
  "markets": [
    {
      "name": "ML",
      "updatedAt": "2026-11-08T15:42:10Z",
      "odds": [{ "home": "1.85", "draw": "3.25", "away": "2.10" }]
    },
    {
      "name": "Totals",
      "updatedAt": "2026-11-08T15:42:10Z",
      "odds": [{ "hdp": 2.5, "over": "1.85", "under": "2.10" }]
    }
  ]
}

Canais e filtros

Escolha os streams que você quer com channels e restrinja-os com parâmetros de consulta para receber só os eventos que você exibe. Não é possível combinar leagues e eventIds.

Canais

odds
O padrão. created, updated, deleted e no_markets para as casas de apostas selecionadas na sua conta
scores
Mensagens score a cada mudança de placar, além de snapshots clock
status
Mensagens status para pendente, ao vivo, liquidado e cancelado, além de snapshots clock

Filtros

markets
Obrigatório para o canal odds. Até 40 nomes de mercado, como ML,Spread,Totals
sport
Até 10 esportes, como football,basketball
leagues
Até 20 slugs de liga, como england-premier-league
eventIds
Até 50 IDs de evento
status
live só para ao vivo, prematch só para pré-jogo

channels é uma lista de permissões. Envie channels=odds,scores,status para manter as odds junto com os placares; só channels=scores,status interrompe as odds.

Reconecte sem lacunas

Redes caem. Toda mensagem de odds traz um número seq, e o feed o usa para colocar você em dia após uma reconexão, em vez de obrigar você a começar do zero.

  1. 1

    Guarde o último seq

    Armazene o maior seq que você recebeu. Os seqs só aumentam dentro de uma conexão, mas são compartilhados por todos os assinantes, então um salto não é uma lacuna.

  2. 2

    Reconecte com lastSeq

    Adicione lastSeq à URL de conexão. Você recebe o estado mais recente de cada evento e casa de apostas que mudou enquanto você estava fora, e depois o stream ao vivo continua.

  3. 3

    Saiba quando você está ao vivo

    Adicione replayComplete=true para receber uma mensagem replay_complete quando a atualização terminar. Os dados de reenvio ficam guardados por até 24 horas.

  4. 4

    Reconstrua quando solicitado

    Se não for possível um reenvio limpo, você recebe resync_required. Busque um snapshot em /v3/odds com includeSeq=true e reconecte com o seq do header X-OddsAPI-Seq.

Cada API key pode manter duas conexões ao mesmo tempo, por exemplo uma principal e uma de reserva. Mais conexões sob solicitação.

Placares ao vivo e relógio da partida

Odds ao vivo fazem mais sentido ao lado do placar. Assine os canais scores e status na mesma conexão, ou consulte o estado atual via REST.

GET /v3/events/live
Todos os eventos em andamento agora, com o placar e um objeto clock. Filtre por esporte
clock
minute, playedSeconds, period, running e statusDetail, além dos acréscimos no futebol e de quem saca no tênis
Placares por período
Tempos, quartos, sets, prorrogação e pênaltis com o mesmo conjunto de chaves para todos os esportes
Relógio correndo
Conte a partir de playedSeconds enquanto running for true, e ajuste para o valor do servidor a cada snapshot

REST como alternativa: /odds e /odds/updated

Todo plano inclui a API REST, que entrega as mesmas odds ao vivo. Use-a para snapshots ou faça polling onde um socket não se encaixa.

GET /v3/odds
Um snapshot completo de um evento nas casas de apostas que você escolher. /v3/odds/multi aceita até 10 eventos em uma requisição
GET /v3/odds/updated
Um delta de verdade: só os mercados que mudaram desde since, que pode ter no máximo 90 segundos. Passe o header de resposta X-Next-Since como since na próxima chamada para continuar sem lacunas
includeSeq=true
Adiciona a posição atual do stream como X-OddsAPI-Seq, para você passar de um snapshot REST para o WebSocket sem perder nenhuma atualização

Um delta não consegue avisar que um mercado foi retirado, então um cliente que faz polling deve reler os eventos com /v3/odds de tempos em tempos. O WebSocket envia deleted e no_markets no lugar disso.

O que o feed de odds ao vivo cobre

Casas de apostas
450+, incluindo Bet365, DraftKings, FanDuel, BetMGM, Betfair Exchange e casas regionais na Europa, Ásia, Austrália e América Latina
Esportes
34, incluindo futebol, basquete, tênis, futebol americano, beisebol, hóquei no gelo, críquete e esports
Ao vivo
Odds ao vivo de todas as casas de apostas que oferecem apostas ao vivo, atualizadas aproximadamente a cada segundo
Mercados
Moneyline, spreads, totais, handicap asiático, escanteios, cartões e props de jogadores, conforme a casa de apostas
Latência
<150ms para as atualizações enviadas via WebSocket
Formato
O mesmo JSON de /v3/odds, via WebSocket e REST

Planos e acesso ao WebSocket

Todo plano pago inclui a API REST com odds ao vivo. O streaming via WebSocket é um add-on que você pode adicionar a qualquer plano.

  • O add-on custa o valor do plano de novo, ou seja, 2× o valor do plano no total, mensal ou anual
  • O stream traz todas as casas de apostas selecionadas na sua conta, então é o plano que define quantas casas você recebe
  • Placar, status e relógio da partida chegam na mesma conexão
  • Cancele em qualquer mês
Comparar planos →

Perguntas frequentes sobre a API de odds ao vivo

O que é uma API de odds ao vivo?

Uma API de odds ao vivo entrega ao seu código as odds atuais dos eventos em andamento, em JSON, e as mantém atualizadas conforme as casas de apostas mexem nos preços. A Odds-API.io transmite odds ao vivo e pré-jogo de 450+ casas de apostas via WebSocket e entrega as mesmas odds via REST.

Quão rápidas são as odds ao vivo?

As atualizações via WebSocket chegam com latência de <150ms, e as odds ao vivo são atualizadas aproximadamente a cada segundo. O polling via REST soma o seu intervalo de consulta, por isso recomendamos WebSocket para apps ao vivo.

O que acontece se minha conexão WebSocket cair?

Reconecte com o parâmetro lastSeq igual ao último seq que você recebeu. O servidor reenvia o estado mais recente de tudo o que mudou enquanto você estava fora, para quedas de até 24 horas, e depois continua ao vivo. Se não for possível um reenvio limpo, ele envia resync_required e você reconstrói a partir de um snapshot REST.

Quais clientes WebSocket posso usar?

Qualquer cliente que suporte a compressão permessage-deflate, que é obrigatória. ws do Node.js, WebSocket do navegador e websockets do Python fazem isso por padrão. websocket-client do Python e textalk/websocket do PHP não suportam e são recusados com HTTP 426. Em Go, ative EnableCompression no gorilla/websocket.

O feed inclui placares ao vivo e o relógio da partida?

Sim. Adicione channels=odds,scores,status à URL de conexão para receber mudanças de placar, mudanças de status e um snapshot do relógio da partida a cada 30 segundos, aproximadamente, junto com as odds. GET /v3/events/live retorna os mesmos placares e relógio via REST.

Como obtenho acesso ao WebSocket?

Escolha um plano pago e adicione o streaming via WebSocket. Ele custa o valor do plano de novo e transmite todas as casas de apostas selecionadas na sua conta, com duas conexões por API key. A API REST, incluindo odds ao vivo e /v3/odds/updated, faz parte de todos os planos.

Receba odds ao vivo hoje

Escolha um plano, adicione o streaming via WebSocket e abra uma única conexão para receber odds ao vivo das 450+ casas de apostas do feed.

Cancele quando quiser · O mesmo JSON via REST e WebSocket