pnclFEED Chave gratuita

Notas de quickstart

Uma página de odds mínima com o servidor nativo do Node

Navegadores não podem chamar a API de odds sem mostrar a sua chave. Um servidor Node de trinta linhas busca o quadro, guarda em cache e serve uma tabela.

Você quer uma página web que mostre odds atuais, e o primeiro instinto é buscar a partir do navegador. Isso vaza a sua chave para todo visitante, então a página precisa ser montada no servidor. A menor versão desse servidor tem cerca de trinta linhas de Node, sem nada para instalar: busque o quadro, renderize uma tabela, guarde a resposta em cache por um minuto.

O formato disso

O navegador fala com o seu servidor; o seu servidor fala com a API. A chave fica no ambiente do servidor, enviada no cabeçalho x-portal-apikey, exatamente como o loop de polling do quickstart de Node faz, verificado em 2026-10-26. A página que volta ao visitante contém só preços.

O Node 18 em diante traz fetch e um servidor HTTP nativo, então tudo cabe num arquivo:

import http from "node:http";

const HOST = process.env.ODDS_BASE_URL;
const KEY = process.env.ODDS_API_KEY;
let cache = { at: 0, rows: [] };

async function board() {
  if (Date.now() - cache.at < 60_000) return cache.rows;
  const url = HOST + "/kit/v1/markets?event_type=prematch&sport_id=1";
  const r = await fetch(url, { headers: { "x-portal-apikey": KEY } });
  if (!r.ok) return cache.rows; // serve a última resposta boa
  const data = await r.json();
  cache = {
    at: Date.now(),
    rows: data.events.map((ev) => {
      const ml = (ev.periods?.num_0 || {}).money_line || {};
      return `<tr><td>${ev.home} v ${ev.away}</td>` +
        `<td>${ml.home ?? ""}</td><td>${ml.draw ?? ""}</td>` +
        `<td>${ml.away ?? ""}</td></tr>`;
    }),
  };
  return cache.rows;
}

http.createServer(async (req, res) => {
  const rows = await board();
  res.setHeader("content-type", "text/html; charset=utf-8");
  res.end(`<table>${rows.join("")}</table>`);
}).listen(8080);

Rode com as duas variáveis de ambiente exportadas, e a porta 8080 responde com uma tabela do quadro de pré-jogo de futebol.

O cache é a cota

Cada visualização de página que chegasse à API gastaria a sua permissão. Uma chamada por minuto é 1.440 chamadas por dia, e o orçamento diário da chave gratuita é bem menor que isso, como as notas do quickstart deixam claro, verificado em 2026-10-26. O cache de um minuto na frente do fetch é o que torna a página viável: cem visitantes num minuto custam uma chamada.

O mesmo cache funciona como modo de falha. Quando a API responde um erro, o servidor devolve o último quadro bom em vez de uma página em branco, e os timestamps nos seus logs dizem quão velho ele ficou.

O que a página nunca deve conter

O HTML que você serve é público por definição. Preços pertencem a ele. A chave, a URL base com quaisquer credenciais embutidas e o estado do seu cursor, não. Se um dia você der view-source na página e vir qualquer coisa além da tabela, a fronteira quebrou.

Isso também resolve a questão da atualização: a página recarrega, o servidor serve o cache, e o cronograma do poller continua sendo o único relógio que gasta cota.

Onde esse desenho para

Um processo, um esporte, uma tabela, um minuto de defasagem. Isso cobre uma página de status, um painel de casa, uma olhada rápida no celular. Quando a página precisa reagir em segundos em vez de minutos, o trabalho sobe para o upstream: faça polling mais rápido ou leia o stream de quedas no servidor, e deixe a página continuar exatamente assim de simples. O quickstart de Node é onde esse loop começa.

Um servidor de trinta linhas não é um produto. É a menor resposta honesta à pergunta que todo projeto web faz primeiro: como mostro esses preços sem mostrar a minha chave.