QQuestions API

Documentação

A Questions API é uma API REST pública e colaborativa com questões escolares de múltipla escolha. Toda questão tem exatamente 5 alternativas — 1 correta e 4 incorretas. Leitura não exige autenticação. Qualquer pessoa pode enviar uma nova questão pelo endpoint público — entra como pending e aparece na listagem pública após ser aprovada por um moderador.

Matérias suportadas

Matemática, Português, História, Geografia, Biologia, Física, Química e Inglês — cada uma com seus assuntos.

Hierarquia

Subject (matéria) → Topic (assunto) → Question (questão). Filtre por qualquer nível.

GET/questions

Retorna uma lista paginada de questões aprovadas. Suporta filtros por matéria, assunto e dificuldade. Todos os parâmetros são opcionais.

Parâmetros

ParâmetroTipoObrigatórioDescrição
subjectstringNãoFiltra por matéria (slug ou nome, case-insensitive).
topicstringNãoFiltra por assunto (slug ou nome, case-insensitive).
difficultystringNãoeasy, medium ou hard.
limitnumberNãoQuantidade de questões por página.
pagenumberNãoPágina desejada (padrão: 1). Requer limit.
encodestringNãoUse encode=base64 para codificar todos os valores em base64.

Modelo de dados — Question

CampoTipoDescrição
idUUIDIdentificador único
titlestringEnunciado da questão
correctAnswerstringResposta correta
incorrectAnswersstring[]As 4 respostas incorretas (total de 5 alternativas com a correta)
difficultyenumeasy | medium | hard
statusenumapproved | pending | rejected
topicIdUUIDChave estrangeira do assunto
topicobjectAssunto + matéria aninhados (name, slug, subject)
submitterNamestring?Nome de quem enviou (null se anônimo)
submitterEmailstring?Email de quem enviou
createdAtISO 8601Data de criação
updatedAtISO 8601Data da última atualização

Resposta

JSON paginado. Os campos limit e pages aparecem apenas quando limit é passado.

GET /questions
{
  "total": 92,
  "page": 1,
  "limit": 10,
  "pages": 10,
  "data": [
    {
      "id": "3f2a1b4c-9d8e-4f3a-b2c1-0a1b2c3d4e5f",
      "title": "Qual é a capital do Brasil?",
      "correctAnswer": "Brasília",
      "incorrectAnswers": ["Rio de Janeiro", "São Paulo", "Salvador", "Belo Horizonte"],
      "difficulty": "easy",
      "status": "approved",
      "topicId": "8e1d3f7a-4b2c-4f1e-9a3d-7c6b5a4e3f2d",
      "topic": {
        "id": "8e1d3f7a-4b2c-4f1e-9a3d-7c6b5a4e3f2d",
        "name": "Geografia do Brasil",
        "slug": "geografia-do-brasil",
        "subject": {
          "id": "c4a0e9b6-7d2e-4b3a-8c1f-2e5d6c7b8a9f",
          "name": "Geografia",
          "slug": "geografia",
          "color": "#10b981",
          "icon": "globe"
        }
      },
      "createdAt": "2026-04-19T00:00:00.000Z",
      "updatedAt": "2026-04-19T00:00:00.000Z"
    }
  ]
}

Matérias e assuntos

Consulte a estrutura completa de matérias com seus assuntos:

GET/subjects
GET /subjects
[
  {
    "id": "c4a0e9b6-7d2e-4b3a-8c1f-2e5d6c7b8a9f",
    "name": "Matemática",
    "slug": "matematica",
    "color": "#3b82f6",
    "icon": "calculator",
    "_count": { "topics": 3 },
    "topics": [
      {
        "id": "...",
        "name": "Álgebra",
        "slug": "algebra",
        "_count": { "questions": 4 }
      }
    ]
  }
]

Contribuir (POST /questions)

Endpoint público. Qualquer pessoa pode enviar. A questão é criada comstatus: "pending"e fica aguardando revisão de um moderador antes de aparecer no GET /questions. Você pode vincular a questão a um assunto existente (topicId) ou pedir a criação de um novo passando subjectId + topicName — nesse caso, o assunto entra como pending e vira aprovado junto da questão.

POST/questions
ParâmetroTipoObrigatórioDescrição
titlestringSimEnunciado da questão.
correctAnswerstringSimResposta correta.
incorrectAnswersstring[]SimArray com exatamente 4 respostas incorretas, distintas entre si e diferentes da correta.
difficultyenumSimeasy, medium ou hard.
topicIdUUIDNãoID de um assunto existente. Obrigatório se não enviar subjectId + topicName.
subjectIdUUIDNãoID da matéria. Use junto com topicName para criar um novo assunto.
topicNamestringNãoNome de um assunto novo (ou existente pelo nome). Se não houver um assunto com este slug na matéria, ele é criado com status pending e aprovado junto com a questão.
submitterNamestringNãoNome de quem enviou (opcional).
submitterEmailstringNãoEmail de quem enviou (opcional).
201 Created
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "Qual é o maior planeta do Sistema Solar?",
  "correctAnswer": "Júpiter",
  "incorrectAnswers": ["Saturno", "Terra", "Netuno", "Urano"],
  "difficulty": "easy",
  "status": "pending",
  "topicId": "8e1d3f7a-4b2c-4f1e-9a3d-7c6b5a4e3f2d",
  "submitterName": "Maria",
  "submitterEmail": "maria@exemplo.com",
  "topic": {
    "id": "...",
    "name": "...",
    "subject": { "name": "Ciências", "slug": "ciencias" }
  }
}
Limite: 5 submissões por minuto por IP. Exceder retorna 429.

Erros

400Parâmetros inválidos
json
{ "error": "Dificuldade inválida. Use: easy, medium, hard" }
429Rate limit excedido
json
{ "error": "Muitas requisições. Tente novamente em 30 segundos." }
Filtro sem resultados — não gera erro. Retorna { "total": 0, "page": 1, "data": [] }.

Rate Limit

EndpointJanelaLimite
GET /questions30 segundos12 req
POST /questions60 segundos5 req

Headers RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset são incluídos em todas as respostas.