Simples, rápido e confiável.
O QAPI MCP Server expõe toda a base de questões via Model Context Protocol (MCP) — o mesmo padrão aberto usado por Claude, ChatGPT e outros agentes de IA para chamar ferramentas externas. Em vez de você integrar cada endpoint REST manualmente no seu agente, conecte-o uma vez ao MCP e todas as ferramentas — questões, provas, concursos, flashcards, simulados, comentários — ficam disponíveis automaticamente para o modelo decidir quando e como chamar.
https://qapi.otunac.com/mcpQ-Api-KeyCada conta recebe uma chave prefixada qb_ gerada com 40 caracteres aleatórios seguros.
Gráfico de barras com consumo diário dos últimos 30 dias, custo mensal e histórico de pagamentos.
A maior parte da API é somente leitura. Comentários e chamados de suporte também podem ser criados, editados e removidos diretamente pela API.
Cada questão já chega com o gabarito e o comentario (justificativa da resposta) na mesma requisição — sem custo extra e sem endpoint separado.
Cadastro exige CPF válido e único, prevenindo criação de múltiplas contas por um mesmo usuário.
Pague via PIX antes de usar e recarregue cotas a qualquer momento — sem fatura mensal. O crédito não expira: o saldo fica na conta até ser usado.
Base URL: https://qapi.otunac.com/api · Header obrigatório: Q-Api-Key: qb_SuaChave
O QAPI MCP Server é uma segunda forma de acessar exatamente os mesmos dados da API REST abaixo — desenhada para ser consumida por agentes de IA (Claude, ChatGPT, e qualquer cliente compatível com Model Context Protocol) em vez de código escrito à mão. Onde a API REST exige que você implemente cada chamada HTTP individualmente, o MCP expõe um catálogo de 26 ferramentas que o próprio modelo descobre e decide quando invocar — você conecta uma vez, o agente aprende o resto.
POST https://qapi.otunac.com/mcp Q-Api-Key: qb_SuaChaveAqui Content-Type: application/json
| MCP | API REST | |
|---|---|---|
| Consumidor típico | Agente de IA (LLM decide o que chamar) | Código escrito por você |
| Descoberta | Automática — tools/list | Manual — esta página |
| Autenticação | Header Q-Api-Key (mesma chave) | Header Q-Api-Key |
| Custo por chamada | 2 cotas | 1 cota |
| Dados retornados | Idênticos | Idênticos |
O MCP usa o transporte streamable HTTP (JSON-RPC 2.0 sobre um
único endpoint POST /mcp) —
sem estado de sessão entre chamadas: cada requisição é independente, autenticada pelo próprio header
Q-Api-Key.
Ao conectar, o agente lista as ferramentas disponíveis (tools/list)
junto com nome, descrição e parâmetros de cada uma — sem precisar de chave, igual à documentação
pública desta página. Só a execução de uma ferramenta exige autenticação.
Cada chamada de ferramenta (tools/call)
carrega o header Q-Api-Key.
O servidor valida a chave (ativa, não suspensa) e o saldo de cotas exatamente como a API REST — e só
então repassa a chamada para a base de questões.
Em caso de sucesso, a ferramenta devolve o mesmo JSON que o endpoint REST equivalente retornaria.
Em caso de erro (chave ausente/inválida, sem saldo, recurso não encontrado), a ferramenta devolve um
resultado de erro (isError: true)
com uma mensagem legível — o agente lê o motivo e pode agir (avisar o usuário, sugerir recarregar
cotas etc.), em vez de travar. Ver Erros no MCP.
A configuração varia por cliente, mas todos pedem a mesma URL e o mesmo header. Exemplos:
claude mcp add --transport http qapi https://qapi.otunac.com/mcp \
--header "Q-Api-Key: qb_SuaChaveAqui"
Ao conectar o QAPI como servidor MCP no Claude Web, informe a chave no header
x-api-key — o Claude Web
não aceita o header Q-Api-Key.
Use a mesma chave e a mesma URL:
URL: https://qapi.otunac.com/mcp
Header: x-api-key: qb_SuaChaveAqui
{
"mcpServers": {
"qapi": {
"type": "http",
"url": "https://qapi.otunac.com/mcp",
"headers": {
"Q-Api-Key": "qb_SuaChaveAqui"
}
}
}
}
Sua chave está disponível em /dashboard (se estiver logado, também aparece pronta pra copiar nos exemplos de código de lá).
Uma ferramenta MCP para cada endpoint hoje protegido por Q-Api-Key
na API REST — mesmos filtros, mesmos limites de paginação (máx. 10 itens/página), mesmos dados.
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_questoes | GET /api/questoes | Consulta questões com filtros (qCode, banca, órgão, cargo, matéria, assunto, enunciado, ano) e paginação |
| get_texto | GET /api/textos/:codigo | Texto/base de referência associado a uma questão |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_bancas | GET /api/bancas | Lista bancas organizadoras |
| get_orgaos | GET /api/orgaos | Lista órgãos públicos |
| get_cargos | GET /api/cargos | Lista cargos |
| get_materias | GET /api/materias | Lista matérias |
| get_assuntos | GET /api/assuntos | Lista assuntos de uma matéria (parâmetro materia obrigatório) |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_provas | GET /api/provas | Lista provas com filtros e paginação — 200 cotas por chamada (tarifa diferenciada) |
| get_prova_por_id | GET /api/provas/:id | Prova pelo ID, incluindo links de PDF quando disponíveis — 200 cotas por chamada (tarifa diferenciada) |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_concursos | GET /api/concursos | Lista concursos públicos com filtros (órgão, banca, status, ano, cargo, região, estado) e paginação |
| get_concurso_por_id | GET /api/concursos/:id | Concurso pelo ID |
| get_status_concurso | GET /api/concursos/status | Valores fixos aceitos pelo campo status |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_disciplinas | GET /api/disciplinas | Disciplinas de edital (filtros: concurso, cargo, matéria) |
| get_disciplina_por_id | GET /api/disciplinas/:id | Disciplina de edital pelo ID |
| get_conteudos | GET /api/conteudos | Lista plana do conteúdo programático de uma disciplina |
| get_conteudos_arvore | GET /api/conteudos/arvore | Árvore completa (aninhada) do conteúdo programático |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_flashcards | GET /api/flashcards | Lista flashcards com filtros e paginação |
| get_flashcard_por_id | GET /api/flashcards/:id | Flashcard pelo ID |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| get_apostilas | GET /api/apostilas | Catálogo de apostilas/e-books com filtros e paginação |
| get_apostila_por_id | GET /api/apostilas/:id | Apostila pelo ID |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| gerar_simulado | GET /api/simulados | Monta um simulado sob demanda a partir de filtros — não persiste nada |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| listar_comentarios | GET /api/comentarios | Lista comentários, opcionalmente filtrados por questão |
| criar_comentario | POST /api/comentarios | Cria um comentário sobre uma questão |
| atualizar_comentario | PUT /api/comentarios/:id | Atualiza texto e/ou autor de um comentário |
| remover_comentario | DELETE /api/comentarios/:id | Remove um comentário |
| Ferramenta | Equivalente REST | Descrição |
|---|---|---|
| abrir_chamado_suporte | POST /api/suporte | Abre um chamado de suporte (bug, questão incorreta, falha de serviço) |
Cada chamada de ferramenta via MCP debita 2 cotas do seu saldo — o dobro de uma requisição equivalente na API REST (1 cota). O saldo é o mesmo das duas formas de acesso: cotas compradas em /payments valem tanto para REST quanto para MCP, sem plano separado.
Agentes de IA — sobretudo fluxos multi-agente/paralelos, que exploram a base de forma automatizada — tendem a multiplicar o número de requisições em relação a um cliente programático tradicional. O custo em dobro contém abuso sem proibir o uso legítimo.
Se o saldo for insuficiente para o custo em dobro (ex: 1 cota restante, que bastaria para uma requisição REST mas não para uma chamada MCP), a ferramenta recusa a chamada com uma mensagem de erro explicando o motivo — nenhuma cota é debitada nesse caso, sem consumo parcial.
Diferente da API REST (que usa códigos de status HTTP), erros de uma ferramenta MCP chegam como um
resultado com isError: true
e uma mensagem de texto — o formato que os agentes de IA esperam para decidir o que fazer a seguir.
| Situação | Mensagem (resumo) |
|---|---|
| Sem header Q-Api-Key | "Header 'Q-Api-Key' é obrigatório..." |
| Chave inválida | "API Key inválida." |
| Chave suspensa | "Sua chave de API foi suspensa por falta de pagamento..." |
| Conta desativada | "Conta desativada. Entre em contato com o suporte." |
| Saldo insuficiente p/ custo em dobro | "Você não possui créditos (cotas) suficientes para usar o QAPI via MCP..." |
| Recurso não encontrado (ex: ID inexistente) | "Prova não encontrada.", "Concurso não encontrado.", etc. |
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.
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.
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âmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| page | integer | 1 | Número da página (começa em 1) |
| size | integer | 10 | Itens por página. Máximo de 10 em todos os endpoints de listagem (questões, provas, concursos, flashcards, apostilas, bancas, órgãos, cargos, matérias e assuntos). Valores maiores são reduzidos para 10 automaticamente |
{
"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.
Endpoint principal para consulta de questões com filtros opcionais e paginação. Limite máximo de 10 itens por página. Combine múltiplos filtros para refinar os resultados — todos os filtros são cumulativos (AND).
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| page | integer | — | Página (padrão: 1) |
| size | integer | — | Itens por página — máximo 10 (padrão: 10) |
| qCode | string | — | Código único da questão (Q-XXXXXXX). Localiza uma questão específica; combina com os demais filtros. Aceita também sem o prefixo e em minúsculas. Código inexistente ou malformado retorna lista vazia |
| banca | string | — | Banca organizadora — casa pelo nome completo ou pela sigla (ex: "FGV" e "Fundação Getulio Vargas" retornam o mesmo conjunto). Use /api/bancas para listar valores válidos |
| orgao | string | — | Órgão da prova — mesma busca por nome completo ou sigla. Use /api/orgaos para listar valores válidos |
| cargo | string | — | Cargo da prova. Use /api/cargos para listar valores válidos |
| materia | string | — | Disciplina/matéria. Use /api/materias para listar valores válidos |
| assunto | string | — | Assunto específico da matéria. Use /api/assuntos para listar |
| enunciado | string | — | Busca textual livre (contains, case-insensitive) no enunciado da questão |
| ano | integer | — | Ano de realização da prova (ex: 2024) |
GET https://qapi.otunac.com/api/questoes?page=1&size=10&banca=FGV&ano=2024 Q-Api-Key: qb_SuaChaveAqui
{
"page": 1,
"size": 10,
"pages": 63,
"total": 624,
"questoes": [
{
"_id": "69a8224af6d9445ec04dad9c",
"qCode": "Q-7KD4M2P", // identificador único e estável da questão
"orgao": "TJ/SE",
"banca": "FGV",
"siglaBanca":"FGV",
"siglaOrgao":"TJ/SE",
"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
}
]
}
siglaBanca/siglaOrgao
são a sigla resolvida a partir do catálogo (pode vir null quando a instituição não tem sigla cadastrada). A base tem questões salvas ora com o nome completo em banca/orgao, ora com a sigla — o filtro já casa os dois formatos automaticamente, então normalmente você não precisa olhar esses campos pra filtrar.
qCode — identificador único da questão. Toda questão tem um código externo no formato Q-XXXXXXX (a letra Q, um hífen e 7 caracteres alfanuméricos maiúsculos, sem 0, O, 1 e I). Ele é estável — nunca muda depois de criado — e único na base. Use-o como chave da questão na sua aplicação, no lugar do _id interno do banco: GET /api/questoes?qCode=Q-7KD4M2P. O mesmo filtro existe na ferramenta MCP get_questoes.
Markdown em enunciado e nas alternativas (opcaoA–opcaoE). As bancas destacam o termo cobrado dentro do próprio enunciado e da alternativa, e entregar texto puro apagava parte desse destaque. Por isso esses campos agora podem conter Markdown (negrito, itálico, sublinhado, listas...). Se você renderizava esses campos como texto simples, as marcações vão aparecer cruas na tela (ex.: **termo**). Ajuste sua aplicação para renderizar Markdown — qualquer biblioteca (marked, markdown-it, react-markdown, python-markdown) resolve; sanitize o HTML resultante antes de exibir.
## cURL curl -X GET \ "https://qapi.otunac.com/api/questoes?banca=FGV&materia=Direito+Administrativo&page=1&size=10" \ -H "Q-Api-Key: qb_SuaChaveAqui" ## cURL — busca por enunciado curl -X GET \ "https://qapi.otunac.com/api/questoes?enunciado=direitos+fundamentais&size=10" \ -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": 10}, 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: 10 }); const r = await fetch(`https://qapi.otunac.com/api/questoes?${params}`, { headers: { "Q-Api-Key": "qb_SuaChaveAqui" } }); const data = await r.json();
/api/questions
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.
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| codigo | string | Sim | Código do texto — valor do campo texto retornado em /questoes |
GET https://qapi.otunac.com/api/textos/QTXT566467 Q-Api-Key: qb_SuaChaveAqui
{
"_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"
}
## 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])
/api/texts/:codigo
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.
Tarifa diferenciada (desde 11/10/2026): R$ 1,00 por requisição (100 cotas), contra 1 cota nas demais rotas. Os PDFs ficam em armazenamento em nuvem mantido por nós, com acesso permanente ao arquivo original — o que gera custo de storage e transferência além do servidor e do banco. Cada requisição retorna até 10 provas, ou seja, ≈ R$ 0,10 por prova. Vale para GET /api/provas e GET /api/provas/:id; via MCP o custo é o dobro (200 cotas). Só é cobrado quando a resposta é 200. Com saldo positivo, mas abaixo de 100 cotas, a rota responde 402 sem consumir nada.
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| page | integer | — | Página (padrão: 1) |
| size | integer | — | Itens por página, máx. 10 (padrão: 10) |
| banca | string | — | Filtrar por banca organizadora |
| orgao | string | — | Filtrar por órgão |
| cargo | string | — | Filtrar por cargo |
| ano | integer | — | Filtrar por ano do exame |
GET https://qapi.otunac.com/api/provas?banca=CEBRASPE&ano=2024&page=1&size=10 Q-Api-Key: qb_SuaChaveAqui
{
"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
}
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| id | string | Sim | ID da prova (ObjectId MongoDB) |
GET https://qapi.otunac.com/api/provas/6a164c795e06528a230ff9d4 Q-Api-Key: qb_SuaChaveAqui
{
"_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"
}
404 quando o ID não existe.
Os campos linkProva e linkGabarito são null quando o PDF ainda não foi enviado.
Concursos públicos em andamento no Brasil, cadastrados pela equipe do QBase. Todos os campos além de orgao, descricao, status e ano são opcionais e salvos como texto livre, sem parsing de data/valor.
orgao e banca são objetos, não strings — cada um traz _id, nome, logo (URL da imagem, para exibir o concurso na sua interface) e website do órgão/banca, quando cadastrados no catálogo do QBase. Sem correspondência no catálogo, você recebe apenas { "nome": "..." }. banca é null quando ainda não definida. Os filtros de query orgao/banca continuam sendo pelo nome (string).
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| page | integer | — | Página (padrão: 1) |
| size | integer | — | Itens por página, máx. 10 (padrão: 10) |
| orgao | string | — | Filtrar por órgão |
| banca | string | — | Filtrar por banca organizadora |
| status | string | — | Filtrar por status (ver /concursos/status abaixo) |
| ano | integer | — | Filtrar por ano do concurso |
| cargo | string | — | Filtrar concursos que ofereçam este cargo |
| regiao | string | — | Filtrar por região: norte, nordeste, centro-oeste, sudeste, sul ou nacional |
| estado | string | — | Filtrar por estado — nome (Paraíba) ou sigla (PB); sem distinção de acento/caixa |
| siglaEstado | string | — | Filtrar pela UF (PB, SP...). Região/estado inexistentes retornam 400 |
| search | string | — | Busca parcial em órgão e descrição |
GET https://qapi.otunac.com/api/concursos?status=editais+publicados&ano=2026&page=1&size=10 Q-Api-Key: qb_SuaChaveAqui
{
"concursos": [
{
"_id": "6a582f98b7e102f6a66d0e16",
"orgao": { "_id": "659a1b2c...", "nome": "DATAPREV", "logo": "https://cdn.../logo_dataprev.png", "website": "https://www.dataprev.gov.br" },
"banca": { "_id": "65b2c3d4...", "nome": "FGV Conhecimento", "logo": "https://cdn.../logo_fgv.png", "website": "https://conhecimento.fgv.br" },
"descricao": "Informações sobre o concurso público...",
"status": "editais publicados",
"vagas": 212,
"cargos": ["Engenharia", "Advocacia"],
"requisitos": "Nível superior",
"remuneracao": "até R$ 10.685,44",
"taxaInscricao": "110,00",
"website": "https://conhecimento.fgv.br/concursos/dataprev26",
"inicioInscricao": "6 de julho de 2026 às 16h",
"fimInscricao": "6 de agosto de 2026 às 16h",
"dataProva": "11 de outubro de 2026",
"horaProva": null,
"validade": "2 anos (podendo ser prorrogado)",
"ano": 2026,
"regiao": "nordeste",
"estado": "Paraíba",
"siglaEstado": "PB",
"createdAt": "2026-07-16T01:10:48.150Z"
}
],
"total": 2,
"page": 1,
"size": 10,
"pages": 1
}
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| id | string | Sim | ID do concurso (ObjectId MongoDB) |
GET https://qapi.otunac.com/api/concursos/6a582f98b7e102f6a66d0e16 Q-Api-Key: qb_SuaChaveAqui
404 quando o ID não existe.
Retorna a lista fixa de valores aceitos pelo campo status, na ordem do fluxo de um concurso — útil para popular um filtro na sua aplicação.
{
"status": [
"solicitado", "autorizado", "banca em definição",
"banca contratada", "comissão formada", "previsto",
"anunciado", "editais publicados"
]
}
Gera um simulado sob demanda a partir dos filtros informados — nada é salvo no banco. Repita a mesma chamada e receba uma seleção e ordem diferentes a cada vez: com mais questões disponíveis que size, um subconjunto aleatório é sorteado a cada chamada; com poucas (ou nenhuma), você recebe o que existir, sempre embaralhado.
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| banca | string | — | Banca organizadora |
| orgao | string | — | Órgão da prova |
| cargo | string | — | Cargo da prova |
| materia | string | — | Disciplina/matéria |
| assunto | string | — | Assunto específico da matéria |
| ano | integer | — | Ano de realização da prova |
| size | integer | — | Quantidade de questões — máximo 10 (padrão: 10) |
GET https://qapi.otunac.com/api/simulados?banca=FGV&materia=Direito+Constitucional&size=10 Q-Api-Key: qb_SuaChaveAqui
{
"questoes": [ /* array de questões, na ordem sorteada */ ],
"total": 137, // total de questões que batem com o filtro
"size": 10 // quantidade efetivamente retornada
}
Todos os filtros são opcionais e combináveis — chame sem nenhum para sortear questões de toda a base.
Use esses endpoints para descobrir os valores válidos dos filtros de /api/questions. Todos suportam paginação e busca por texto — em bancas/órgãos, o parâmetro search casa tanto pelo nome quanto pela sigla da instituição.
Lista as bancas organizadoras. Use search para filtrar por nome ou sigla — ex: "fgv" encontra "Fundação Getulio Vargas" mesmo que você não digite o nome completo.
GET https://qapi.otunac.com/api/bancas?page=1&size=10&search=fgv Q-Api-Key: qb_SuaChaveAqui
{
"bancas": [
{
"_id": "6a2cfe8e4d53df4eac8fe0b4",
"nome": "Fundação Getulio Vargas",
"sigla": "FGV",
"logo": "https://.../logo_fgv.png",
"website": null
}
],
"total": 1, "page": 1, "pages": 1
}
sigla/logo/website vêm null quando não cadastrados no catálogo.
Lista os órgãos. Use search para busca parcial por nome ou sigla.
GET https://qapi.otunac.com/api/orgaos?page=1&size=5&search=ces Q-Api-Key: qb_SuaChaveAqui
{
"orgaos": [
{
"_id": "659f...",
"nome": "Centro de Seleção e de Promoção de Eventos",
"sigla": "CESPE",
"logo": null,
"website": null
}
],
"total": 1, "page": 1, "pages": 1
}
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
}
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
}
Lista os assuntos de uma matéria. materia é obrigatório.
| Parâmetro | Tipo | Req. | Descrição |
|---|---|---|---|
| materia | string | Sim | Nome exato da matéria (obter via /api/materias) |
| page | integer | — | Página |
| size | integer | — | Itens por página |
| search | string | — | Busca 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
}
Comente em qualquer questão — para tirar dúvidas, discutir a resolução ou reportar um gabarito incorreto. Os comentários são compartilhados: qualquer chamada à API vê a mesma conversa em uma questão.
| Campo | Tipo | Req. | Descrição |
|---|---|---|---|
| questao | string | ID da questão comentada | |
| usuario | string | Nome de quem está comentando | |
| comentario | string | Texto do comentário |
POST https://qapi.otunac.com/api/comentarios Q-Api-Key: qb_SuaChaveAqui Content-Type: application/json { "questao": "69a8224af6d9445ec04dad9c", "usuario": "Maria Souza", "comentario": "O gabarito está incorreto, a alternativa correta é a B." }
{
"_id": "6a539f2c790ad5b7852c63ad",
"questao": "69a8224af6d9445ec04dad9c",
"usuario": "Maria Souza",
"comentario": "O gabarito está incorreto, a alternativa correta é a B.",
"createdAt": "2026-07-12T14:05:32.740Z",
"updatedAt": "2026-07-12T14:05:32.740Z"
}
Lista os comentários de uma questão, em ordem cronológica. Lista vazia se a questão ainda não tiver comentários.
GET https://qapi.otunac.com/api/comentarios?questao=69a8224af6d9445ec04dad9c Q-Api-Key: qb_SuaChaveAqui
{
"comentarios": [
{ "_id": "...", "usuario": "Maria Souza", "comentario": "O gabarito está incorreto...", "createdAt": "..." }
]
}
Atualiza usuario e/ou comentario. Retorna 404 se o ID não existir.
PUT https://qapi.otunac.com/api/comentarios/6a539f2c790ad5b7852c63ad Q-Api-Key: qb_SuaChaveAqui Content-Type: application/json { "comentario": "Editado: na verdade o gabarito está certo." }
Remove um comentário. Retorna 204 sem corpo. 404 se o ID não existir.
DELETE https://qapi.otunac.com/api/comentarios/6a539f2c790ad5b7852c63ad Q-Api-Key: qb_SuaChaveAqui
Abra um chamado diretamente pela API — bug na API, questão incorreta, falha de serviço, ou qualquer outro problema.
| Campo | Tipo | Req. | Descrição |
|---|---|---|---|
| incidente | string | Título curto do problema | |
| descricao | string | Detalhes do problema | |
| nomeDoCliente | string | Nome de quem está reportando | |
| string | E-mail para retorno |
POST https://qapi.otunac.com/api/suporte Q-Api-Key: qb_SuaChaveAqui Content-Type: application/json { "incidente": "Falha no endpoint /api/questoes", "descricao": "Recebendo 500 ao filtrar por banca=FGV.", "nomeDoCliente": "João Silva", "email": "[email protected]" }
{
"_id": "6a539f3f790ad5b7852c63b8",
"incidente": "Falha no endpoint /api/questoes",
"descricao": "Recebendo 500 ao filtrar por banca=FGV.",
"nomeDoCliente": "João Silva",
"email": "[email protected]",
"createdAt": "2026-07-12T14:05:51.772Z"
}
Apenas a abertura de chamados é exposta pela API pública — consulta, edição e remoção de chamados ficam restritas à equipe do QAPI.
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.
Cria uma nova conta e retorna a api_key gerada automaticamente — prefixada com qb_.
| Campo | Tipo | Req. | Descrição |
|---|---|---|---|
| name | string | Nome completo | |
| string | E-mail único (usado no login) | ||
| cpf | string | CPF brasileiro válido (formato: 123.456.789-09 ou apenas dígitos) | |
| password | string | Senha 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" }
{
"message": "Conta criada com sucesso.",
"api_key": "qb_abc123xyz..." // guarde esta chave!
}
Autentica com e-mail e senha. Retorna um JWT Bearer token e os dados da conta, incluindo a api_key.
| Campo | Tipo | Req. | Descrição |
|---|---|---|---|
| string | E-mail cadastrado | ||
| password | string | Senha da conta |
POST https://qapi.otunac.com/api/auth/login Content-Type: application/json { "email": "[email protected]", "password": "minhasenha123" }
{
"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.
A API retorna erros em formato JSON com um campo error descritivo. Use o HTTP status code para determinar o tipo de falha.
| Status | Significado | Causa comum |
|---|---|---|
| 200 | OK | Requisição processada com sucesso |
| 400 | Bad Request | Parâmetro inválido ou ausente (ex: materia ausente em /assuntos) |
| 401 | Unauthorized | Header Q-Api-Key ausente ou inválido |
| 402 | Payment Required | Sem cotas (créditos) em saldo — modelo pré-pago vigente desde 01/08/2026 |
| 403 | Forbidden | Chave de API suspensa |
| 404 | Not Found | Recurso não encontrado (ex: código de texto inexistente) |
| 422 | Unprocessable | Dado inválido no corpo (registro/login) |
| 500 | Server Error | Erro interno — tente novamente ou contate o suporte |
{
"error": "Chave de API inválida ou inexistente."
}
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 == 402: raise PermissionError("Sem créditos — insira cotas para continuar") elif r.status_code == 403: raise PermissionError("Chave suspensa — contate o suporte") else: r.raise_for_status()
Sem mensalidade, sem taxa de adesão. Desde 01/08/2026, o QAPI funciona por cotas pré-pagas: recarregue a partir de R$ 50,00 (múltiplos de R$ 50,00) e use enquanto houver saldo — sem cotas, a API não responde.