Correspondência de Eventos
O Problema
Cada sportsbook utiliza seus próprios IDs internos de eventos. O mesmo jogo Lakers vs Celtics pode ser o evento 33483200 na DraftKings, nba-bos-lal-20260208 na FanDuel e 556677889 na Pinnacle. Sem um identificador unificado, construir ferramentas de comparação entre sportsbooks exige implementar sua própria lógica de correspondência de eventos.
Como a SharpAPI Resolve Isso
A SharpAPI gera um ID canônico de evento para cada evento. Esse ID é determinístico — o mesmo evento do mundo real sempre recebe o mesmo id, independentemente de qual sportsbook ele venha.
Formato: {league}_{teamA}_{teamB}_{YYYY-MM-DD}_b{N}O _b{N} final é um bucket de horário de início de 6 horas — veja Sufixo de bucket de horário de início abaixo.
Exemplo: Um jogo Celtics vs Lakers em 8 de fevereiro de 2026 produz o mesmo ID em todos os sportsbooks:
| Sportsbook | ID Nativo do Evento | id da SharpAPI |
|---|---|---|
| DraftKings | 33483200 | nba_celtics_lakers_2026-02-08_b3 |
| FanDuel | nba-bos-lal-20260208 | nba_celtics_lakers_2026-02-08_b3 |
| Pinnacle | 556677889 | nba_celtics_lakers_2026-02-08_b3 |
| BetMGM | ms_44556 | nba_celtics_lakers_2026-02-08_b3 |
Dois Tipos de IDs de Eventos
Todo evento na API possui dois campos de ID:
| Campo | Escopo | Finalidade |
|---|---|---|
id | Entre sportsbooks (canônico) | Use como chave primária para corresponder eventos entre sportsbooks |
external_ids | Por sportsbook | Mapa do ID nativo de cada sportsbook, útil para deep links |
{
"id": "nba_celtics_lakers_2026-02-08_b3",
"external_ids": {
"draftkings": "33483200",
"fanduel": "nba-bos-lal-20260208",
"pinnacle": "556677889",
"betmgm": "ms_44556"
}
}Como os IDs Canônicos São Gerados
O ID canônico é construído a partir de quatro componentes:
- Código da liga — esporte mapeado para liga (ex.:
basketball→nba) - Nomes dos times — normalizados e ordenados alfabeticamente
- Data — data de início do evento no formato
YYYY-MM-DD - Bucket de horário de início — sufixo
_b{N}ondeNestá em0..3
Normalização de Nomes de Times
Os nomes dos times são normalizados para lidar com variações entre sportsbooks:
"Los Angeles Lakers"→lakers"LA Lakers"→lakers"LAL"→lakers
A normalização remove prefixos (“The”, “Los”, “Las”), sufixos (“FC”, “United”, “City”), pontuação e acentos. Os times são então ordenados alfabeticamente para que o ID seja idêntico, independentemente da ordem casa/visitante.
Sufixo de bucket de horário de início (_b{N})
O sufixo _b{N} é um bucket de horário de início de 6 horas. N está em 0..3:
| Bucket | Faixa de horário |
|---|---|
_b0 | 00:00–05:59 |
_b1 | 06:00–11:59 |
_b2 | 12:00–17:59 |
_b3 | 18:00–23:59 |
Para esportes de ligas dos EUA (NBA, NFL, NHL, MLB, NCAAB, NCAAF, WNBA, NCAAW), o bucket é ancorado no horário do Leste dos EUA (ET), de modo que um jogo que começa às 19h30 ET cai em _b3, independentemente de como os sportsbooks registram seus offsets UTC. Para todos os outros esportes (futebol, tênis, críquete etc.), o bucket é ancorado em UTC.
Por que isso existe. Mesmo confronto, mesma data de calendário, mas jogos reais diferentes são possíveis:
- Um doubleheader (jogo duplo) da MLB com dois jogos no mesmo dia.
- Um jogo da MLB na noite dos EUA cujo carimbo UTC cai no dia de calendário seguinte, mais uma revanche real no dia seguinte cujo carimbo UTC cai na mesma data.
Sem o bucket, os dois jogos colidiriam em um único ID e as odds seriam misturadas. Com ele, os dois jogos caem em sufixos _bN diferentes e permanecem separados.
O que isso significa para a correspondência entre sportsbooks. Dentro de um mesmo jogo, todo sportsbook que reporta um horário de início dentro da mesma janela de 6 horas converge para o mesmo _b{N}. Ao cruzar o limite de um bucket — por exemplo, um sportsbook registra o início de um jogo de futebol às 17:55 UTC (_b2) e outro às 18:10 UTC (_b3) — os sportsbooks podem se fragmentar em dois IDs canônicos. Essa é uma limitação conhecida. Se você observar isso, abra um ticket com os detalhes do evento.
Sufixo de doubleheader (_g{N})
Quando um sportsbook reporta os dois jogos de um doubleheader do mesmo dia em uma única atualização, os dois jogos são desambiguados com um sufixo _g{N} colocado depois do bucket — ex.: mlb_athletics_mariners_2026-05-02_b0 e mlb_athletics_mariners_2026-05-02_b0_g1. Sportsbooks que veem apenas um dos dois jogos emitem o ID com bucket sem sufixo adicional. A divergência residual entre sportsbooks para doubleheaders é, portanto: mesma base _b{N}, com um lado carregando o sufixo _g{N} e o outro não.
Agrupando um confronto entre vários IDs
Para consolidar as linhas que pertencem a um único jogo físico, mas acabaram em IDs canônicos diferentes, escolha o nível que corresponde à sua tolerância a mesclagens:
-
Consolidação do mesmo jogo (recomendado). Remova o sufixo
_g{N}final e compare o restante, mantendo o bucket_b{N}intacto:key = event_id sem o sufixo _g{N} final # ..._b0_g1 → ..._b0 agrupe os eventos cujo key resultante seja idênticoIsso reúne a divergência do sufixo de doubleheader descrita acima sem mesclar jogos distintos. Espelha o predicado same-event do lado do servidor.
-
Agrupamento amplo por confronto (exibição). Para reunir todos os preços de um confronto em uma data, independentemente do bucket — ex.: para renderizar um card por jogo em uma UI e absorver a fragmentação nos limites de bucket descrita acima — remova tanto o sufixo
_g{N}quanto o_b{N}e agrupe por{league}_{teamA}_{teamB}_{date}, tolerando ±1 dia para inícios que cruzam a meia-noite UTC:key = "{league}_{teamA}_{teamB}_{date}" # os times já estão em ordem alfabética; _b{N}/_g{N} removidos agrupe os keys que compartilham liga + times e cujas datas diferem em no máximo 1 diaContrapartida: como isso descarta o bucket, um doubleheader genuíno do mesmo dia colapsa em um único grupo. Use o nível 1 quando os dois jogos precisarem permanecer separados.
Usando IDs Canônicos em Sua Aplicação
Como Chave Primária
Use o campo id como chave primária do seu banco de dados ao armazenar eventos:
// Fetch events from the API
const { data: events } = await fetch(
'https://api.sharpapi.io/api/v1/events?league=nba',
{ headers: { 'X-API-Key': API_KEY } }
).then(r => r.json());
// Store using canonical ID as primary key
for (const event of events) {
await db.events.upsert({
id: event.id, // "nba_celtics_lakers_2026-02-08_b3"
home_team: event.home_team,
away_team: event.away_team,
start_time: event.start_time,
external_ids: event.external_ids
});
}Comparação de Odds Entre Sportsbooks
O ID canônico permite comparar odds para o mesmo evento em todos os sportsbooks:
// Get odds filtered to a specific event
const { data } = await fetch(
'https://api.sharpapi.io/api/v1/events/nba_celtics_lakers_2026-02-08_b3/odds',
{ headers: { 'X-API-Key': API_KEY } }
).then(r => r.json());
// All odds in the response are for the same canonical event
// Group by sportsbook to compare
const byBook = {};
for (const odds of data.odds) {
byBook[odds.sportsbook] = byBook[odds.sportsbook] || [];
byBook[odds.sportsbook].push(odds);
}Deep Linking para Sportsbooks
Use external_ids para direcionar usuários de volta para a página do evento de um sportsbook específico:
const event = await getEvent('nba_celtics_lakers_2026-02-08_b3');
// Build a sportsbook-specific link
const dkEventId = event.external_ids['draftkings'];
// → "33483200"Como Isso Alimenta a Detecção de EV e Arbitragem
Os mecanismos de detecção de oportunidades da SharpAPI dependem internamente dos IDs canônicos de eventos:
- Cálculo de EV encontra as odds de referência sharp (Pinnacle) para o mesmo
eventIde as compara com as odds dos soft books - Detecção de arbitragem agrupa todas as odds por
eventId+ tipo de mercado para encontrar discrepâncias de preços entre sportsbooks - Detecção de middles encontra linhas sobrepostas entre sportsbooks para o mesmo
eventId
Esse é o mesmo sistema de correspondência exposto a você através da API — quando você vê uma oportunidade de arbitragem com pernas de diferentes sportsbooks, é o ID canônico do evento que ligou essas odds.
Propriedades Principais
| Propriedade | Detalhe |
|---|---|
| Determinístico | As mesmas entradas sempre produzem o mesmo ID — sem UUIDs aleatórios |
| Estável | O ID não muda depois de gerado |
| Legível por humanos | nba_celtics_lakers_2026-02-08_b3 é significativo à primeira vista |
| Ordenável | Os IDs são ordenados naturalmente por liga, time e data |