Python · API do SUAPGitHub  /  PyPI
Suapy, biblioteca Python para a API do SUAP

Seus dados acadêmicos,
em Python ou no terminal.

Consulte notas, faltas, avaliações e horários. Use os métodos em português ou exporte os registros para trabalhar com eles em uma planilha.

O cliente usa o SUAP do IFRN por padrão. Outras instituições podem ter APIs e permissões diferentes. Este é um projeto independente.

Esta página descreve a 1.4.1. Enquanto ela não estiver no PyPI, instale o código do repositório para usar os novos comandos.

Instalação

Use Python 3.10 ou superior. Em um ambiente virtual:

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade suapy

No Windows, ative com .venv\Scripts\activate. Para conversão em DataFrame, instale python -m pip install "suapy[pandas]". CSV e JSON não precisam de Pandas.

Versão do repositório

git clone https://github.com/kellyson71/suapy.git
cd suapy
python -m pip install -e ".[dev,pandas]"

Pelo terminal

Execute suapy para abrir o menu interativo. Para uma consulta direta, use um dos comandos abaixo. Quando necessário, o terminal solicita matrícula e senha.

suapy periodos
suapy boletim --ano 2026 --periodo 2
suapy turmas --ano 2026 --periodo 2
suapy avaliacoes
suapy mensagens --status nao_lidas
suapy progresso

Escolha ano e período a partir de suapy periodos; os valores do exemplo não garantem que existam registros na sua conta. Use suapy --help ou suapy boletim --help para ver as opções.

OpçãoUso
--formato tabela|json|csvFormato da consulta; o padrão é tabela.
--saida arquivoCria um arquivo JSON ou CSV; não sobrescreve arquivos existentes.
--sem-sessaoNão acessa o token salvo no computador.
--url-base URLSeleciona outra instituição, inclusive uma URL com prefixo como /suap.

Em Python

Autentique e selecione o período mais recente informado pela API:

from getpass import getpass
from suapy import Suap, SuapError

try:
    with Suap(timeout=(5, 30)) as suap:
        suap.login(input("Matrícula: "), getpass("Senha: "))
        periodos = list(suap.iterar_resultados(
            suap.ensino.obter_periodos_letivos()
        ))
        if periodos:
            atual = max(periodos, key=lambda p: (
                int(p["ano_letivo"]), int(p["periodo_letivo"])
            ))
            boletim = suap.ensino.obter_boletim(
                atual["ano_letivo"], atual["periodo_letivo"]
            )
            for disciplina in suap.iterar_resultados(boletim):
                print(disciplina.get("disciplina"),
                      disciplina.get("numero_faltas"))
except SuapError as erro:
    print(f"Consulta indisponível: {erro}")

O bloco with libera conexões HTTP. Se não usá-lo, chame suap.fechar(). A biblioteca mantém credenciais somente em memória.

Exportar dados

As consultas de listagem incluem todas as páginas. Avisos e prompts usam stderr; JSON e CSV usam stdout ou o arquivo escolhido.

suapy boletim --ano 2026 --periodo 2 --formato csv --saida boletim.csv
suapy avaliacoes --formato json > avaliacoes.json
suapy mensagens --status todas --formato json --saida mensagens.json

Arquivos de --saida são criados com acesso restrito em POSIX. Uma redireção com > usa as permissões do shell e pode sobrescrever arquivos.

JSON preserva objetos e listas. No CSV, as colunas reúnem as chaves dos registros, valores aninhados viram JSON e campos ausentes ficam vazios. Textos que poderiam ser interpretados como fórmulas recebem um apóstrofo inicial.

Com Pandas

import pandas as pd
from suapy import para_dataframe

# Com suap autenticado e ano/periodo selecionados:
resposta = suap.ensino.obter_boletim(ano, periodo)
df = para_dataframe(list(suap.iterar_resultados(resposta)))
if "media_final_disciplina" in df.columns:
    notas = pd.to_numeric(df["media_final_disciplina"], errors="coerce")
    if notas.notna().any():
        print(notas.mean())

Essa é uma média simples das notas disponíveis, não necessariamente o índice acadêmico oficial.

Login e sessão

O CLI do IFRN salva um refresh token em ~/.suapy/session.json. A senha não é gravada. O token é uma credencial em texto simples; em POSIX, a pasta usa permissão 700 e o arquivo 600.

suapy --sem-sessao
suapy boletim --ano 2026 --periodo 2 --sem-sessao
suapy --logout

--sem-sessao ignora a sessão existente e não a modifica, mesmo ao sair. --logout remove o arquivo local; não revoga o token no servidor. As duas opções não podem ser combinadas.

Uma --url-base alternativa não lê nem grava a sessão do IFRN. Você autentica naquela instituição durante a execução.

O cliente renova o acesso após um HTTP 401 e repete a chamada uma vez. Falhas de conexão não provocam novas tentativas automáticas.

URLs e paginação

Um prefixo na URL base é preservado nos endpoints do cliente:

suap = Suap(url_base="https://instituicao.example/suap")
# obter_boletim(2026, 2) consulta:
# https://instituicao.example/suap/api/ensino/meu-boletim/2026/2/

Listas e objetos continuam sendo usados como JSON. Páginas com results são dicionários com um atributo interno para a URL de origem; os campos do JSON não são alterados. Assim, um next como ?page=2 é resolvido contra a URL consultada.

Para páginas carregadas de outro lugar, informe a URL de origem se o link seguinte for relativo:

pagina = {"results": [], "next": "?page=2"}
registros = suap.iterar_resultados(
    pagina,
    url_origem="https://instituicao.example/suap/api/lista/"
)

Links absolutos e relativos à raiz seguem a semântica da URL retornada pelo servidor. Links externos e ciclos são rejeitados. O iterador é incremental, mas cada página é carregada em memória. A exportação do CLI reúne todos os registros antes de escrever.

Métodos da API

Todos os métodos dependem dos endpoints e das permissões da instituição.

MóduloMétodos
ensinoobter_dados_aluno(), obter_periodos_letivos(), obter_boletim(ano, periodo), obter_turmas_virtuais(ano, periodo), obter_turma_virtual(pk), obter_proximas_avaliacoes(), obter_mensagens_aluno(status), obter_requisitos_conclusao(), obter_eventos(), obter_horario_aulas(), obter_diarios(ano=None, periodo=None).
usuarioobter_meus_dados_resumidos(), obter_meus_dados(), obter_historico_funcional(), obter_contracheques(), obter_contracheque_detalhado(ano, mes).
infraestruturaobter_campi(), obter_setores().
pesquisa_extensaoobter_projetos_pesquisa(), obter_projetos_extensao().

Para notas e faltas de alunos, use boletim. Diários podem exigir perfil de professor. Métodos funcionais podem exigir vínculo de servidor.

Interpretar horários

from suapy import parse_horario
print(parse_horario("2V34 / 4V56"))

O retorno contém dia_semana, dia_num, turno e horarios. O número 2 representa segunda-feira; V representa tarde. Os números 3 e 4 representam tempos de aula, não horas do relógio.

Erros e validação

ExceçãoQuando ocorre
ValueErrorURL base inválida; ano que não tem quatro dígitos; período não positivo; argumentos parciais de diários; status de mensagem desconhecido.
SuapAuthErrorTokens inválidos ou respostas HTTP 401/403.
SuapApiErrorOutros erros HTTP, JSON inválido ou paginação incompatível.
SuapErrorClasse base e erros de conexão/timeout.

A validação de ano/período se aplica a boletim, turmas e diários. Aceita inteiros e strings decimais; rejeita booleanos. Não limita o período a dois semestres: consulte os períodos disponíveis na instituição.

No CLI, erro de argumentos retorna código 2, erro de execução retorna 1 e interrupção retorna 130. Consultas concluídas retornam 0.

Testes

Os testes padrão simulam a API e não acessam uma conta:

python -m pip install -e ".[dev,pandas]"
python -m pytest -q

Uma conta real de teste

Em Bash, forneça as credenciais sem gravar a senha no histórico:

read -r -p "Matrícula de teste: " SUAP_TEST_USERNAME
read -r -s -p "Senha de teste: " SUAP_TEST_PASSWORD
export SUAP_TEST_USERNAME SUAP_TEST_PASSWORD
python scripts/test_live.py
unset SUAP_TEST_USERNAME SUAP_TEST_PASSWORD

Para outra instituição, defina também SUAP_TEST_URL. O teste autentica, renova o token e consulta dados do aluno, períodos, boletim, turmas e avaliações. Não imprime respostas nem salva tokens. Uma lista vazia não permite validar os campos dos registros.

Sem credenciais ou sem períodos, o teste retorna 2 (pendente/incompleto). Erros retornam 1. Isso não substitui testes com os diferentes perfis e permissões usados pela instituição.

Publicação e diagnóstico

O publicador deve ser do tipo GitHub no PyPI: proprietário kellyson71, repositório suapy, workflow release.yml, environment pypi.

Para testar somente a autenticação, abra Actions → Publish to PyPI → Run workflow, ou use:

gh workflow run release.yml --ref main

A execução manual troca a identidade do GitHub por uma credencial temporária do PyPI e a descarta. Não constrói, envia ou republica pacotes. Um erro invalid-publisher pede revisão do provedor e dos quatro campos do cadastro.

A publicação real ocorre ao publicar uma release com tag correspondente à versão em pyproject.toml. Ela passa pelos testes e pela validação dos pacotes. Uma versão já publicada não pode ser sobrescrita.

Consulte a documentação do PyPI e o guia de contribuição.