{
  "openapi": "3.1.0",
  "info": {
    "title": "Logs da Urna 2026",
    "version": "1.0.0",
    "description": "Métricas extraídas dos logs das urnas eletrônicas do 1º turno das Eleições Gerais 2026 (arquivos de urna publicados pelo TSE). Sem autenticação, CORS aberto. Respostas com cache de 30 a 600 segundos.",
    "contact": { "name": "João Raul", "url": "https://joaoraul.dev", "email": "me@joaoraul.dev" }
  },
  "servers": [{ "url": "https://logseleicoes.joaoraul.dev" }],
  "paths": {
    "/api/stats": {
      "get": {
        "operationId": "resumo",
        "summary": "Resumo nacional, por UF, progresso de publicação e rankings",
        "responses": {
          "200": { "description": "Resumo", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Resumo" } } } },
          "503": { "description": "Ainda processando os primeiros arquivos" }
        }
      }
    },
    "/resumo.md": {
      "get": {
        "operationId": "resumoMarkdown",
        "summary": "O mesmo resumo em markdown, pronto pra leitura",
        "responses": { "200": { "description": "Markdown", "content": { "text/markdown": {} } } }
      }
    },
    "/api/secoes": {
      "get": {
        "operationId": "listarSecoes",
        "summary": "Lista seções já lidas, com filtros e ordenação (50 por página)",
        "parameters": [
          { "name": "uf", "in": "query", "schema": { "type": "string", "pattern": "^[a-z]{2}$" }, "description": "Sigla da UF em minúsculas", "example": "rs" },
          { "name": "mu", "in": "query", "schema": { "type": "string", "pattern": "^\\d{5}$" }, "description": "Código TSE do município (veja /api/municipios)" },
          { "name": "zn", "in": "query", "schema": { "type": "string", "pattern": "^\\d{4}$" }, "description": "Zona eleitoral" },
          { "name": "q", "in": "query", "schema": { "type": "string", "maxLength": 40 }, "description": "Parte do nome do município; acentos são ignorados" },
          { "name": "f", "in": "query", "schema": { "type": "array", "items": { "type": "string", "enum": ["reinicio", "bateria", "troca", "alertas"] } }, "style": "form", "explode": true, "description": "reinicio: urna reiniciou com a votação aberta; bateria: 60 s ou mais na bateria com a votação aberta; troca: mais de uma urna no dia; alertas: 10 ou mais linhas ALERTA" },
          { "name": "ord", "in": "query", "schema": { "type": "string", "enum": ["local", "med", "tecla", "votos", "reinicios", "encerramento", "publicacao"], "default": "local" } },
          { "name": "dir", "in": "query", "schema": { "type": "string", "enum": ["asc", "desc"] } },
          { "name": "pagina", "in": "query", "schema": { "type": "integer", "minimum": 0, "maximum": 200, "default": 0 } }
        ],
        "responses": {
          "200": {
            "description": "Página de seções",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "pagina": { "type": "integer" }, "porPagina": { "type": "integer" }, "temMais": { "type": "boolean" },
                "itens": { "type": "array", "items": { "$ref": "#/components/schemas/Secao" } }
              }
            } } }
          },
          "400": { "$ref": "#/components/responses/Erro" }
        }
      }
    },
    "/api/municipios": {
      "get": {
        "operationId": "listarMunicipios",
        "summary": "Municípios de uma UF que já têm seções lidas",
        "parameters": [{ "name": "uf", "in": "query", "required": true, "schema": { "type": "string" }, "example": "rs" }],
        "responses": {
          "200": { "description": "Municípios", "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "uf": { "type": "string" },
              "municipios": { "type": "array", "items": { "type": "object", "properties": {
                "mu": { "type": "string" }, "nm": { "type": "string" }, "secoes": { "type": "integer" }, "votos": { "type": "integer" } } } }
            }
          } } } },
          "400": { "$ref": "#/components/responses/Erro" }
        }
      }
    },
    "/api/secao": {
      "get": {
        "operationId": "obterSecao",
        "summary": "Métricas de uma seção",
        "parameters": [{ "$ref": "#/components/parameters/Chave" }],
        "responses": {
          "200": { "description": "Seção", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Secao" } } } },
          "404": { "$ref": "#/components/responses/Erro" }
        }
      }
    },
    "/api/log": {
      "get": {
        "operationId": "lerLog",
        "summary": "Log completo da urna (logd.dat) de uma seção",
        "description": "Uma linha por evento, campos separados por tab: data e hora (dd/mm/aaaa hh:mm:ss), nível (INFO, ALERTA, ERRO), id da urna, módulo (VOTA, GAP, LOGD, SCUE…), mensagem, hash da linha. Inclui dias de preparação antes da eleição.",
        "parameters": [{ "$ref": "#/components/parameters/Chave" }],
        "responses": {
          "200": { "description": "Log em texto", "headers": { "x-origem": { "schema": { "type": "string" }, "description": "URL do arquivo .jez no TSE" }, "x-hash": { "schema": { "type": "string" } } }, "content": { "text/plain": {} } },
          "404": { "$ref": "#/components/responses/Erro" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Chave": { "name": "k", "in": "query", "required": true, "schema": { "type": "string", "pattern": "^[a-z]{2}-\\d{5}-\\d{4}-\\d{4}$" }, "example": "rs-85294-0155-0001", "description": "uf-município-zona-seção" }
    },
    "responses": {
      "Erro": { "description": "Erro", "content": { "application/json": { "schema": { "type": "object", "properties": { "erro": { "type": "string" } } } } } }
    },
    "schemas": {
      "Secao": {
        "type": "object",
        "properties": {
          "k": { "type": "string", "description": "Chave da seção" },
          "uf": { "type": "string" }, "mu": { "type": "string" }, "nm": { "type": "string", "description": "Município" },
          "zn": { "type": "string" }, "se": { "type": "string" },
          "votos": { "type": "integer", "description": "Votos computados no log" },
          "med": { "type": ["integer", "null"], "description": "Mediana do tempo de voto em segundos" },
          "p90": { "type": ["integer", "null"] },
          "bio": { "type": "integer", "description": "Eleitores habilitados por biometria" },
          "manual": { "type": "integer", "description": "Eleitores habilitados pelo mesário sem biometria" },
          "tecla": { "type": "integer", "description": "Tecla indevida pressionada" },
          "tpv": { "type": "number", "description": "Teclas indevidas por voto" },
          "corrige": { "type": "integer", "description": "Eleitor corrigiu na tela de confirmação" },
          "justif": { "type": "integer", "description": "Justificativas recebidas" },
          "alerta": { "type": "integer" }, "erro": { "type": "integer" },
          "reinicios": { "type": "integer", "description": "Reinícios com a votação aberta" },
          "urnas": { "type": "integer", "description": "Urnas distintas no log do dia" },
          "bateria": { "type": "integer", "description": "Segundos na bateria com a votação aberta (60 ou mais costuma ser falta de luz)" },
          "zeresima": { "type": ["string", "null"] }, "abertura": { "type": ["string", "null"] },
          "encerramento": { "type": ["string", "null"] }, "pub": { "type": "string", "description": "Quando o TSE recebeu os arquivos" }
        }
      },
      "Resumo": {
        "type": "object",
        "properties": {
          "atualizado": { "type": "string", "format": "date-time" },
          "progresso": { "type": "object", "description": "publicadas: seções com arquivo no TSE; total: seções; processadas: lidas aqui; porUf" },
          "br": { "type": "object", "description": "Agregado nacional: secoes, votos, med, p90, bioPct, teclaPorVoto, tecla, corrige, justif, secoesComReinicio, secoesComTroca, secoesComBateria, porHora, faixas (histograma de 5 s), encerramentos" },
          "uf": { "type": "object", "additionalProperties": { "type": "object" } },
          "rankings": { "type": "object", "description": "lentas, rapidas, tecla, reinicios" }
        }
      }
    }
  }
}
