API Gateway v1.2  ·  https://qapi.otunac.com/api

Base
de Questões de Concurso Público.

Simples, rápido e confiável.

exemplo.py
# pip install requests
import requests
 
BASE = "https://qapi.otunac.com/api"
KEY  = "qb_SuaChaveAqui"
H    = {"Q-Api-Key": KEY}
 
# buscar questões
r = requests.get(
    f"{BASE}/questions",
    params={"banca":"FGV", "ano":2024},
    headers=H
)
print(r.json()["total"])
 
$ python exemplo.py
100% Read-only
9 Endpoints
R$1 / 1.000 req
JWT + API Key
recursos

Tudo que você precisa para integrar em minutos

🔑

API Key única

Cada conta recebe uma chave prefixada qb_ gerada com 40 caracteres aleatórios seguros.

📊

Dashboard em tempo real

Gráfico de barras com consumo diário dos últimos 30 dias, custo mensal e histórico de pagamentos.

🔒

Somente leitura

O gateway bloqueia PUT, POST e DELETE. Apenas GET é permitido, protegendo integralmente a base de dados.

Token cacheado

O acesso à API privada usa token com cache de 23h — zero overhead de autenticação por requisição.

🛡️

CPF único por conta

Cadastro exige CPF válido e único, prevenindo criação de múltiplas contas por um mesmo usuário.

💳

Billing transparente

Pagamento mensal via PIX com QR Code no último dia do mês. Histórico de pagamentos disponível na dashboard.

documentação

Referência completa da API

Base URL: https://qapi.otunac.com/api  ·  Header obrigatório: Q-Api-Key: qb_SuaChave

Autenticação

Todos os endpoints de consulta requerem uma API Key enviada no header HTTP Q-Api-Key. Você obtém sua chave ao criar uma conta — ela fica disponível no seu dashboard.

Header obrigatório em todas as requisições
Q-Api-Key: qb_SuaChaveAqui

A chave é prefixada com qb_ seguido de 40 caracteres aleatórios. Mantenha-a em segredo — nunca exponha em código público ou repositórios. Se necessário, redefina-a pelo suporte.

Paginação

Os endpoints que retornam listas suportam paginação via query parameters. Todos seguem o mesmo padrão de resposta com metadados de paginação.

Parâmetros de paginação comuns
ParâmetroTipoPadrãoDescrição
pageinteger1Número da página (começa em 1)
sizeinteger10Itens por página. Em /questions, máximo de 100
Estrutura de resposta paginada
{
  "page":  1,      // página atual
  "size":  10,     // itens nesta página
  "pages": 63,     // total de páginas
  "total": 624,    // total de itens encontrados
  "questoes": [/* array de itens */]
}

Para percorrer todos os resultados, itere de page=1 até page=pages. Cada página consome 1 requisição no seu billing.

Questões

Endpoint principal para consulta de questões com filtros opcionais e paginação. Limite máximo de 100 itens por página. Combine múltiplos filtros para refinar os resultados — todos os filtros são cumulativos (AND).

GET /api/questoes Q-Api-Key canônico
Parâmetros de query
ParâmetroTipoReq.Descrição
pageintegerPágina (padrão: 1)
sizeintegerItens por página — máximo 100 (padrão: 10)
bancastringBanca organizadora. Use /api/bancas para listar valores válidos
orgaostringÓrgão da prova. Use /api/orgaos para listar valores válidos
cargostringCargo da prova. Use /api/cargos para listar valores válidos
materiastringDisciplina/matéria. Use /api/materias para listar valores válidos
assuntostringAssunto específico da matéria. Use /api/assuntos para listar
anointegerAno de realização da prova (ex: 2024)
Exemplo de request
GET https://qapi.otunac.com/api/questoes?page=1&size=10&banca=FGV&ano=2024
Q-Api-Key: qb_SuaChaveAqui
Response 200
{
  "page":  1,
  "size":  10,
  "pages": 63,
  "total": 624,
  "questoes": [
    {
      "_id":      "69a8224af6d9445ec04dad9c",
      "orgao":    "TJ/SE",
      "banca":    "FGV",
      "ano":      2023,
      "cargo":    "Analista Judiciário - Análise de Sistemas",
      "materia":  "Conhecimento Específico",
      "assunto":  "Arquitetura de Computadores",
      "enunciado":"Em sistemas operacionais, a métrica que mede...",
      "opcaoA":   "throughput;",
      "opcaoB":   "tempo de espera;",
      "opcaoC":   "tempo de turnaround;",
      "opcaoD":   "tempo de processador;",
      "opcaoE":   "utilização do processador.",
      "gabarito": "A",
      "comentario":"Throughput é o número de processos...",
      "texto":    "QTXT566467"  // código p/ buscar o texto em /api/texts/:codigo
    }
  ]
}
Exemplos de código
## cURL
curl -X GET \
  "https://qapi.otunac.com/api/questoes?banca=FGV&materia=Direito+Administrativo&page=1&size=20" \
  -H "Q-Api-Key: qb_SuaChaveAqui"

## Python
import requests

r = requests.get(
    "https://qapi.otunac.com/api/questoes",
    params={"banca": "FGV", "materia": "Direito Administrativo", "page": 1, "size": 20},
    headers={"Q-Api-Key": "qb_SuaChaveAqui"}
)
data = r.json()
print(f"Total: {data['total']} questões, {data['pages']} páginas")

## JavaScript
const params = new URLSearchParams({ banca: "FGV", materia: "Direito Administrativo", page: 1, size: 20 });
const r = await fetch(`https://qapi.otunac.com/api/questoes?${params}`, {
  headers: { "Q-Api-Key": "qb_SuaChaveAqui" }
});
const data = await r.json();
Alias de compatibilidade (mantido): /api/questions
Textos

Recupera o texto completo referenciado pelo campo texto de uma questão. Questões que não possuem texto base retornam esse campo como string vazia — verifique antes de fazer a chamada.

GET /api/textos/:codigo Q-Api-Key canônico
Parâmetro de path
ParâmetroTipoReq.Descrição
codigostring✓ SimCódigo do texto — valor do campo texto retornado em /questoes
Exemplo de request
GET https://qapi.otunac.com/api/textos/QTXT566467
Q-Api-Key: qb_SuaChaveAqui
Response 200
{
  "_id":       "69b0cfaa20dadd7d66bfcec9",
  "codigo":    "QTXT566467",
  "titulo":    "A reinvenção da vírgula",
  "texto":     "No começo de 1902, Machado de Assis...",
  "fonte":     "Machado de Assis",
  "createdAt": "2026-03-11T02:12:58.079Z"
}
Padrão de uso recomendado
## Python — buscar questão e carregar seu texto base
import requests

BASE    = "https://qapi.otunac.com/api"
headers = {"Q-Api-Key": "qb_SuaChaveAqui"}

questoes = requests.get(f"{BASE}/questoes", params={"banca": "FGV"}, headers=headers).json()

for q in questoes["questoes"]:
    if q["texto"]:  # campo não vazio → tem texto base
        txt = requests.get(f"{BASE}/textos/{q['texto']}", headers=headers).json()
        print(txt["titulo"], txt["texto"][:200])
Alias de compatibilidade (mantido): /api/texts/:codigo
Provas

Lista e consulta provas cadastradas no sistema — cada prova agrupa as questões de um exame identificado por banca, órgão, cargo e ano. O campo linkProva aponta para o PDF do exame e linkGabarito para o gabarito oficial, quando disponíveis.

GET /api/provas Q-Api-Key
Query parameters
ParâmetroTipoReq.Descrição
pageintegerPágina (padrão: 1)
sizeintegerItens por página, máx. 100 (padrão: 10)
bancastringFiltrar por banca organizadora
orgaostringFiltrar por órgão
cargostringFiltrar por cargo
anointegerFiltrar por ano do exame
Exemplo de request
GET https://qapi.otunac.com/api/provas?banca=CEBRASPE&ano=2024&page=1&size=10
Q-Api-Key: qb_SuaChaveAqui
Response 200
{
  "provas": [
    {
      "_id":          "6a164c795e06528a230ff9d4",
      "orgao":         "Polícia Federal",
      "banca":         "CEBRASPE",
      "cargo":         "Delegado Federal",
      "ano":           2024,
      "linkProva":     "https://cdn.exemplo.com/prova.pdf",
      "linkGabarito":  "https://cdn.exemplo.com/gabarito.pdf",
      "createdAt":     "2025-05-30T14:00:00.000Z"
    }
  ],
  "total": 12,
  "page":  1,
  "size":  10,
  "pages": 2
}
GET /api/provas/:id Q-Api-Key
Parâmetro de path
ParâmetroTipoReq.Descrição
idstring✓ SimID da prova (ObjectId MongoDB)
Exemplo de request
GET https://qapi.otunac.com/api/provas/6a164c795e06528a230ff9d4
Q-Api-Key: qb_SuaChaveAqui
Response 200
{
  "_id":          "6a164c795e06528a230ff9d4",
  "orgao":         "Polícia Federal",
  "banca":         "CEBRASPE",
  "cargo":         "Delegado Federal",
  "ano":           2024,
  "linkProva":     "https://cdn.exemplo.com/prova.pdf",
  "linkGabarito":  "https://cdn.exemplo.com/gabarito.pdf",
  "uploadProva":   { "filename": "pf_2024.pdf", "size": 2048576, "uploadedAt": "2025-05-30T14:00:00.000Z" },
  "uploadGabarito": { "filename": "gabarito_pf_2024.pdf", "size": 512000, "uploadedAt": "2025-05-30T15:00:00.000Z" },
  "createdAt":     "2025-05-30T14:00:00.000Z"
}
Retorna 404 quando o ID não existe. Os campos linkProva e linkGabarito são null quando o PDF ainda não foi enviado.
Catálogos de filtros

Use esses endpoints para descobrir os valores válidos dos filtros de /api/questions. Todos suportam paginação e busca por texto. O parâmetro search realiza busca parcial case-insensitive.

Parâmetros comuns a todos os catálogos:   page (integer, padrão: 1)  ·  size (integer, padrão: 10)  ·  search (string — busca parcial no nome)
GET /api/bancas Q-Api-Key

Lista as bancas organizadoras. Use search para filtrar por nome.

GET https://qapi.otunac.com/api/bancas?page=1&size=10&search=fgv
Q-Api-Key: qb_SuaChaveAqui
{
  "bancas": ["FGV"],
  "total": 1, "page": 1, "pages": 1
}
GET /api/orgaos Q-Api-Key

Lista os órgãos. Use search para busca parcial.

GET https://qapi.otunac.com/api/orgaos?page=1&size=5&search=ces
Q-Api-Key: qb_SuaChaveAqui
{
  "orgaos": ["CESPE", "CESGRANRIO"],
  "total": 2, "page": 1, "pages": 1
}
GET /api/cargos Q-Api-Key

Lista os cargos disponíveis na base.

GET https://qapi.otunac.com/api/cargos?page=1&size=10&search=professor
Q-Api-Key: qb_SuaChaveAqui
{
  "cargos": ["Professor de Ensino Básico", "Professor Adjunto"],
  "total": 2, "page": 1, "pages": 1
}
GET /api/materias Q-Api-Key

Lista as matérias e disciplinas disponíveis.

GET https://qapi.otunac.com/api/materias?page=1&size=5&search=Direito
Q-Api-Key: qb_SuaChaveAqui
{
  "materias": ["Direito Administrativo", "Direito Constitucional", "Direito Civil"],
  "total": 3, "page": 1, "pages": 1
}
GET /api/assuntos Q-Api-Key

Lista os assuntos de uma matéria. materia é obrigatório.

ParâmetroTipoReq.Descrição
materiastring✓ SimNome exato da matéria (obter via /api/materias)
pageintegerPágina
sizeintegerItens por página
searchstringBusca parcial no nome do assunto
GET https://qapi.otunac.com/api/assuntos?materia=Tecnologia+Java&page=1&size=5&search=hibernate
Q-Api-Key: qb_SuaChaveAqui
{
  "materia": "Tecnologia Java",
  "assuntos": ["Hibernate / JPA", "Hibernate Cache"],
  "total": 2, "page": 1, "pages": 1
}
Autenticação programática

Endpoints para criar conta e obter token via API. Útil para integrações automatizadas. O CPF brasileiro válido é obrigatório no cadastro — cada CPF pode ter apenas uma conta.

POST /api/auth/register

Cria uma nova conta e retorna a api_key gerada automaticamente — prefixada com qb_.

Request body
CampoTipoReq.Descrição
namestringNome completo
emailstringE-mail único (usado no login)
cpfstringCPF brasileiro válido (formato: 123.456.789-09 ou apenas dígitos)
passwordstringSenha com mínimo de 8 caracteres
POST https://qapi.otunac.com/api/auth/register
Content-Type: application/json

{
  "name":     "João Silva",
  "email":    "[email protected]",
  "cpf":      "123.456.789-09",
  "password": "minhasenha123"
}
Response 201
{
  "message": "Conta criada com sucesso.",
  "api_key": "qb_abc123xyz..."   // guarde esta chave!
}
POST /api/auth/login

Autentica com e-mail e senha. Retorna um JWT Bearer token e os dados da conta, incluindo a api_key.

Request body
CampoTipoReq.Descrição
emailstringE-mail cadastrado
passwordstringSenha da conta
POST https://qapi.otunac.com/api/auth/login
Content-Type: application/json

{
  "email":    "[email protected]",
  "password": "minhasenha123"
}
Response 200
{
  "token":          "eyJhbGci...",   // JWT — válido por 24h
  "api_key":        "qb_abc123xyz...",
  "api_key_active": true
}

O JWT retornado pode ser usado como Authorization: Bearer <token> em rotas autenticadas da web. Para acesso à API de questões, use sempre o Q-Api-Key header com sua api_key.

Tratamento de erros

A API retorna erros em formato JSON com um campo error descritivo. Use o HTTP status code para determinar o tipo de falha.

HTTP Status Codes
StatusSignificadoCausa comum
200OKRequisição processada com sucesso
400Bad RequestParâmetro inválido ou ausente (ex: materia ausente em /assuntos)
401UnauthorizedHeader Q-Api-Key ausente ou inválido
403ForbiddenChave de API suspensa por inadimplência
404Not FoundRecurso não encontrado (ex: código de texto inexistente)
422UnprocessableDado inválido no corpo (registro/login)
500Server ErrorErro interno — tente novamente ou contate o suporte
Estrutura de resposta de erro
{
  "error": "Chave de API inválida ou inexistente."
}
Exemplo de tratamento em Python
import requests

r = requests.get(
    "https://qapi.otunac.com/api/questions",
    headers={"Q-Api-Key": "qb_SuaChave"}
)

if r.status_code == 200:
    data = r.json()
elif r.status_code == 401:
    raise ValueError("API Key inválida")
elif r.status_code == 403:
    raise PermissionError("Chave suspensa — regularize o pagamento")
else:
    r.raise_for_status()
preços

Pague apenas pelo que usar

Sem mensalidade, sem taxa de adesão. A cobrança é calculada com base no total de requisições realizadas via sua API Key no mês. O pagamento é feito no último dia de cada mês via PIX.

R$1
a cada 1.000 requisições
  • Sem mensalidade ou taxa de adesão
  • Todos os endpoints contabilizados igualmente
  • Dashboard com custo do mês em tempo real
  • Histórico de pagamentos com confirmação
  • Chave suspensa automaticamente em caso de atraso
Criar conta grátis →