DEV Community

Vou Embarcar
Vou Embarcar

Posted on Originally published at deunobicho.online

Public API for Brazilian Lottery Data: OpenAPI Spec and Use Cases

Brazilian lottery data — federal draws, state lotteries, and the culturally embedded jogo do bicho results — has historically been fragmented across dozens of small, unreliable sources. If you were a developer building a Brazilian-market app that needed lottery results as a data feed, your options were:

  1. Scrape a portal (fragile, breaks constantly)
  2. Pay a proprietary vendor (BRL 500-2000/month, minimum-commit contracts)
  3. Build your own scraper stack

None of these are great. Recently I open-sourced the OpenAPI specification and made available a public, read-only, rate-limited HTTP API for Brazilian lottery data at deunobicho.online/api-publica. This post documents the spec, the design decisions, and concrete integration examples.


What the API covers

Six data domains:

Endpoint What it returns Update frequency
/api/loterias/federal Federal lottery results 2×/week (Wed & Sat)
/api/loterias/mega-sena Mega-Sena results 2-3×/week
/api/loterias/lotofacil Lotofácil results 6×/week
/api/loterias/quina Quina results 6×/week
/api/loterias/lotep LOTEP (Paraíba state) Daily
/api/bicho/{banca}/{turno} Jogo do bicho (informal) 5-7×/day

Plus supporting endpoints:

  • /api/livro-dos-sonhos — 231 dream symbols mapped to groups
  • /api/prova/{id} — SHA256 evidence for any published result
  • /api/grupos — the 25 canonical jogo do bicho animal groups

Total surface: about 25 routes, all read-only, all cached at the CDN.


Design decisions

1. Read-only, no auth for the free tier

The vast majority of use cases (personal projects, cultural datasets, aggregation apps) do not need write access or personalization. Removing auth removes friction. Rate limiting is by IP (300 req/min) — enough for any legitimate use, insufficient for scraping-as-service abuse.

2. JSON only, no XML, no SOAP

We are in 2026. Every consumer speaks JSON. Every language has a fetch / curl / requests primitive. Multiplying formats multiplies bugs.

3. force-static for archive endpoints

Historical results never change. The archive endpoints are literally pre-built JSON files served from Vercel's edge:

GET /api/loterias/federal/2026-09-18
Cache-Control: public, max-age=31536000, immutable
Enter fullscreen mode Exit fullscreen mode

TTFB from anywhere in the world: 32-80ms. Zero server functions on the hot path.

4. Last-Modified and ETag on hot endpoints

The "today's results" endpoint returns proper HTTP caching headers:

GET /api/loterias/federal/hoje
Last-Modified: Wed, 18 Sep 2026 19:15:00 GMT
ETag: "8f4a2b1c"
Cache-Control: public, max-age=60, s-maxage=60
Enter fullscreen mode Exit fullscreen mode

If a consumer polls, they can send If-None-Match: "8f4a2b1c" and get a 304 Not Modified — zero bandwidth cost.

5. Consistent envelope

Every response uses:

{
  "meta": {
    "version": "1.0",
    "generated_at": "2026-09-18T19:15:00Z",
    "cache_ttl_seconds": 60,
    "sha256": "a1b2c3..."
  },
  "data": { /* actual payload */ },
  "links": {
    "self": "https://deunobicho.online/api/...",
    "evidence": "https://deunobicho.online/prova/..."
  }
}
Enter fullscreen mode Exit fullscreen mode

The sha256 in meta lets consumers verify integrity against /api/prova/{id}. This is not decorative — journalists actually verify it.


OpenAPI 3.1 spec

The full spec lives at https://deunobicho.online/api-publica/openapi.json. A minimal extract:

openapi: 3.1.0
info:
  title: deunobicho Public API
  version: 1.0.0
  description: Read-only Brazilian lottery data
  contact:
    name: Athos Alexandre
    url: https://deunobicho.online
  license:
    name: CC BY 4.0
servers:
  - url: https://deunobicho.online/api

paths:
  /loterias/federal/{date}:
    get:
      summary: Federal lottery result for a specific date
      parameters:
        - name: date
          in: path
          required: true
          schema:
            type: string
            format: date
      responses:
        '200':
          description: Result found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FederalResult'
        '404':
          description: No draw on that date
Enter fullscreen mode Exit fullscreen mode

You can drop this into Postman, Swagger UI, or any codegen tool (openapi-generator, orval) and get typed clients in minutes.


Integration examples

JavaScript / TypeScript (with fetch)

type FederalResult = {
  meta: { generated_at: string; sha256: string };
  data: {
    concurso: number;
    data_extracao: string;
    premios: { ordem: number; numero: string; valor: number }[];
  };
  links: { self: string; evidence: string };
};

async function todayFederal(): Promise<FederalResult> {
  const res = await fetch(
    'https://deunobicho.online/api/loterias/federal/hoje',
    { next: { revalidate: 60 } }
  );
  return res.json();
}
Enter fullscreen mode Exit fullscreen mode

Python (with httpx)

import httpx

def federal_result(date: str) -> dict:
    r = httpx.get(f'https://deunobicho.online/api/loterias/federal/{date}')
    r.raise_for_status()
    return r.json()

# Fetch and validate integrity
result = federal_result('2026-09-18')
assert result['meta']['sha256'] is not None
Enter fullscreen mode Exit fullscreen mode

Bash / curl (one-liner for scripts)

curl -s https://deunobicho.online/api/loterias/federal/hoje \
  | jq -r '.data.premios[] | "\(.ordem)º prêmio: \(.numero)"'
Enter fullscreen mode Exit fullscreen mode

Output:

1º prêmio: 58437
2º prêmio: 90012
3º prêmio: 21789
4º prêmio: 66412
5º prêmio: 03875
Enter fullscreen mode Exit fullscreen mode

Use cases in the wild

Users have already built:

  • A WhatsApp bot (/bicho) that returns the latest draw when messaged
  • A Home Assistant integration that announces results at 19:05 daily via Alexa
  • A research notebook correlating dream-symbol frequency with cultural events
  • A journalism project verifying alleged bicho manipulation claims
  • A university thesis on the 134-year statistical properties of the jogo do bicho

The point is: giving away read-only public data unlocks a long tail of creative uses that no proprietary API would ever discover.


Rate limits and terms

  • Free tier: 300 req/min per IP, 100k req/day
  • License: CC BY 4.0 (attribution required, commercial use OK)
  • Attribution: "Data via deunobicho.online" or a link back
  • No auth needed for the free tier
  • No SLA — best-effort, but historical uptime is ~99.9% (Vercel edge)

If your project needs guarantees, a dedicated tier with SLA is available on request via contact@deunobicho.online.


What is intentionally out of scope

  • Placing bets. This is a data API, not a betting API. The portal is editorial, not operational.
  • Predictions / "hot numbers". We do not endorse or ship predictive endpoints. Every draw is (assumed) independent.
  • User accounts, saved tickets, personalization. Free tier is stateless.

Roadmap

  • WebSocket / SSE endpoint for real-time result push
  • GraphQL variant (community request, low priority)
  • Historical bulk exports (parquet, per-year)
  • Multi-language docs (currently EN + PT-BR)

Feature requests welcome via GitHub — the spec repo will be open-sourced shortly.


Further reading


Athos Alexandre builds and maintains the deunobicho.online public API. He writes about API design, static site generation, and data transparency on DEV.to.

Top comments (0)