{"openapi":"3.1.0","info":{"title":"API TreinaWeb","version":"1.0.0","summary":"API de parceiros da TreinaWeb e superfícies públicas para agentes.","description":"A API de parceiros (`/api/empresa/v1`) atende empresas com contrato B2B: lista os alunos da conta, o andamento deles nos cursos e gera URLs de login direto. O token é entregue no fechamento do contrato — não existe auto-cadastro nem sandbox pública.\n\nToda resposta é JSON, inclusive os erros, no formato `{\"error\": {\"http_code\", \"code\", \"message\"}}`.\n\nO endpoint MCP (`/dashboard/mcp`) é a superfície para agentes autenticados por OAuth 2.1 com o escopo `mcp:use`, restrita a administradores da plataforma.\n\nOs arquivos públicos (`/llms.txt`, `/robots.txt`, `/sitemap.xml`) e a negociação de Markdown por `Accept: text/markdown` dispensam credencial. Detalhes em https://www.treinaweb.com.br/developers.","contact":{"name":"TreinaWeb","email":"atendimento@treinaweb.com.br","url":"https://www.treinaweb.com.br/contato"},"license":{"name":"Uso restrito a parceiros com contrato","url":"https://www.treinaweb.com.br/developers"}},"servers":[{"url":"https://www.treinaweb.com.br","description":"Host desta especificação"}],"tags":[{"name":"Alunos","description":"Alunos da empresa contratante e o andamento deles nos cursos."},{"name":"Autenticação","description":"Token de acesso e login direto do aluno."},{"name":"Agentes","description":"Arquivos públicos que descrevem o site para agentes de IA."},{"name":"MCP","description":"Servidor Model Context Protocol da plataforma."}],"security":[{"bearerAuth":[]}],"paths":{"/api/empresa/v1/alunos":{"get":{"operationId":"listarAlunos","tags":["Alunos"],"summary":"Lista os alunos da empresa","description":"Devolve todos os alunos vinculados à empresa dona do token, com data de cadastro, último acesso e links para os recursos relacionados de cada aluno.","responses":{"200":{"description":"Alunos da empresa.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Aluno"}}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/alunos/relatorio":{"get":{"operationId":"listarRelatorioDeAlunos","tags":["Alunos"],"summary":"Relatório de alunos com os cursos iniciados","description":"Mesma lista de alunos, com os cursos já iniciados e o progresso de cada um embutidos. Paginado em 500 alunos por página.","parameters":[{"name":"incluir_inativos","in":"query","required":false,"description":"Inclui também os alunos desativados da conta.","schema":{"type":"boolean","default":false}},{"name":"page","in":"query","required":false,"description":"Página do resultado.","schema":{"type":"integer","minimum":1,"default":1}}],"responses":{"200":{"description":"Alunos com os cursos iniciados.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatorioDeAlunos"}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/alunos/{aluno_uuid}/login/url":{"post":{"operationId":"gerarUrlDeLoginDoAluno","tags":["Autenticação"],"summary":"Gera uma URL de login direto para o aluno","description":"Devolve uma URL de uso único, válida por 10 minutos, que autentica o aluno e o leva ao painel. Para levar o aluno a uma página específica depois do login, passe `next`.","parameters":[{"name":"aluno_uuid","in":"path","required":true,"description":"UUID do aluno, como devolvido em `listarAlunos`.","schema":{"type":"string","format":"uuid"}},{"name":"next","in":"query","required":false,"description":"URL da plataforma para onde o aluno segue depois do login (por exemplo a `url_painel` de um curso).","schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"URL de login de uso único.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UrlDeLogin"}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"404":{"$ref":"#/components/responses/NaoEncontrado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/alunos/{aluno_uuid}/cursos":{"get":{"operationId":"listarCursosDoAluno","tags":["Alunos"],"summary":"Lista os cursos que o aluno acessa","description":"Cursos liberados para o aluno, com progresso de 0 a 100, vigência do acesso e o link `self` para o detalhamento de aulas.","parameters":[{"name":"aluno_uuid","in":"path","required":true,"description":"UUID do aluno, como devolvido em `listarAlunos`.","schema":{"type":"string","format":"uuid"}},{"name":"andamento_status","in":"query","required":false,"description":"Filtra por andamento: 1 iniciados, 2 concluídos, 3 não iniciados.","schema":{"type":"integer","enum":[1,2,3]}}],"responses":{"200":{"description":"Cursos do aluno.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Curso"}}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"404":{"$ref":"#/components/responses/NaoEncontrado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/alunos/{aluno_uuid}/cursos/{curso_uuid}":{"get":{"operationId":"obterCursoDoAluno","tags":["Alunos"],"summary":"Detalha um curso do aluno","description":"Curso com aulas e subaulas, incluindo o tempo que o aluno passou em cada uma e a data do último acesso. `data_ultimo_acesso` nula significa que o aluno ainda não abriu aquela subaula.","parameters":[{"name":"aluno_uuid","in":"path","required":true,"description":"UUID do aluno, como devolvido em `listarAlunos`.","schema":{"type":"string","format":"uuid"}},{"name":"curso_uuid","in":"path","required":true,"description":"UUID do curso, como devolvido em `listarCursosDoAluno`.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Curso detalhado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursoDetalhado"}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"404":{"$ref":"#/components/responses/NaoEncontrado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/token/refresh":{"post":{"operationId":"atualizarToken","tags":["Autenticação"],"summary":"Rotaciona o token do contrato","description":"Emite um token novo e invalida o atual na hora. Não há prazo de validade: rotacione quando a sua política pedir.","responses":{"200":{"description":"Token novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"429":{"$ref":"#/components/responses/LimiteExcedido"}}}},"/api/empresa/v1/login":{"get":{"operationId":"loginDoAlunoPorToken","tags":["Autenticação"],"summary":"Consome a URL de login direto","description":"Endpoint de navegador, não de integração: é o destino da URL devolvida por `gerarUrlDeLoginDoAluno`. Autentica o aluno e redireciona para o painel. Não exige o token do contrato.","security":[],"parameters":[{"name":"token","in":"query","required":true,"description":"JWT de uso único gerado por `gerarUrlDeLoginDoAluno`.","schema":{"type":"string"}}],"responses":{"302":{"description":"Aluno autenticado; redireciona para o painel."},"401":{"$ref":"#/components/responses/NaoAutenticado"}}}},"/dashboard/mcp":{"post":{"operationId":"chamarServidorMcp","tags":["MCP"],"summary":"Endpoint do servidor MCP","description":"Fala Model Context Protocol sobre HTTP streamable (JSON-RPC 2.0), não REST. Exige OAuth 2.1 com o escopo `mcp:use` e é restrito a administradores autorizados da plataforma. A resposta 401 traz `WWW-Authenticate` com o endereço dos metadados do recurso protegido.","security":[{"mcpOAuth":["mcp:use"]}],"requestBody":{"required":true,"description":"Envelope JSON-RPC 2.0 do protocolo MCP.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequisicaoJsonRpc"}}}},"responses":{"200":{"description":"Resposta JSON-RPC do protocolo MCP.","content":{"application/json":{"schema":{"type":"object"}},"text/event-stream":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/NaoAutenticado"},"403":{"$ref":"#/components/responses/Proibido"}}}},"/llms.txt":{"get":{"operationId":"obterIndiceParaAgentes","tags":["Agentes"],"summary":"Índice do site para agentes (llmstxt.org)","description":"Resumo do site, orientação de uso e links das páginas principais, categorias, cursos, formações e posts — todos já na versão Markdown.","security":[],"responses":{"200":{"description":"Índice em texto puro.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/openapi.json":{"get":{"operationId":"obterEspecificacaoOpenApi","tags":["Agentes"],"summary":"Esta especificação","description":"A própria especificação OpenAPI 3.1 do host, em JSON.","security":[],"responses":{"200":{"description":"Documento OpenAPI.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Token do contrato B2B, enviado como `Authorization: Bearer <token>`. Pode ser rotacionado em `/api/empresa/v1/token/refresh`; o token anterior deixa de valer na hora."},"mcpOAuth":{"type":"oauth2","description":"OAuth 2.1 com PKCE do servidor MCP. Os metadados ficam em `/.well-known/oauth-authorization-server` (RFC 8414) e `/.well-known/oauth-protected-resource` (RFC 9728); clientes se registram sozinhos em `/oauth/register` (RFC 7591).","flows":{"authorizationCode":{"authorizationUrl":"https://www.treinaweb.com.br/oauth/authorize","tokenUrl":"https://www.treinaweb.com.br/oauth/token","refreshUrl":"https://www.treinaweb.com.br/oauth/token","scopes":{"mcp:use":"Consultar relatórios e datasets somente leitura pelo servidor MCP."}}}}},"schemas":{"Error":{"type":"object","description":"Envelope de erro de toda a API.","required":["error"],"properties":{"error":{"type":"object","required":["http_code","code","message"],"properties":{"http_code":{"type":"integer","description":"Status HTTP repetido no corpo.","examples":[401]},"code":{"type":"string","description":"Código estável do erro, para tratamento programático.","examples":["unauthorized"]},"message":{"type":"string","description":"Mensagem legível do que aconteceu.","examples":["Unauthorized"]}}}}},"Link":{"type":"object","description":"Link de navegação para um recurso relacionado. Prefira seguir estas URLs a montá-las à mão.","required":["type","rel","uri"],"properties":{"type":{"type":"string","description":"Método HTTP do link.","examples":["GET"]},"rel":{"type":"string","description":"Nome da relação.","examples":["cursos"]},"uri":{"type":"string","format":"uri","description":"URL completa do recurso."}}},"Aluno":{"type":"object","description":"Aluno vinculado à empresa contratante.","required":["id","nome","email"],"properties":{"id":{"type":"string","format":"uuid","description":"UUID do aluno."},"nome":{"type":"string"},"email":{"type":"string","format":"email"},"foto_url":{"type":["string","null"],"format":"uri","description":"Foto de perfil, quando o aluno enviou uma."},"data_cadastro":{"type":["string","null"],"format":"date-time","description":"ISO 8601 com fuso."},"ultimo_acesso":{"type":["string","null"],"format":"date-time","description":"Último login do aluno; nulo se nunca acessou."},"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}}}},"RelatorioDeAlunos":{"type":"object","description":"Página do relatório de alunos, com os cursos iniciados embutidos.","properties":{"data":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/Aluno"},{"type":"object","properties":{"cursos":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Curso"}}}}}}]}},"meta":{"$ref":"#/components/schemas/MetaDePaginacao"}}},"MetaDePaginacao":{"type":"object","properties":{"pagination":{"type":"object","properties":{"total":{"type":"integer"},"count":{"type":"integer"},"per_page":{"type":"integer"},"current_page":{"type":"integer"},"total_pages":{"type":"integer"}}}}},"Curso":{"type":"object","description":"Curso liberado para o aluno, com o andamento dele.","required":["id","nome","slug"],"properties":{"id":{"type":"string","format":"uuid"},"tipo":{"type":"integer","description":"Identificador do tipo de conteúdo."},"tipo_slug":{"type":"string","description":"Tipo em texto.","examples":["curso"]},"nome":{"type":"string"},"slug":{"type":"string"},"cor":{"type":["string","null"],"description":"Cor do curso em hexadecimal."},"url_imagem":{"type":["string","null"],"format":"uri"},"url_painel":{"type":"string","format":"uri","description":"Acesso direto ao curso no painel do aluno. Use como `next` ao gerar a URL de login."},"url_landing":{"type":"string","format":"uri","description":"Página pública do curso."},"progresso":{"type":"integer","minimum":0,"maximum":100,"description":"0 a 100; 100 significa curso concluído."},"carga_horaria":{"type":"integer","description":"Tempo em segundos que o aluno passou no conteúdo."},"data_inicio":{"type":["string","null"],"format":"date-time"},"data_conclusao":{"type":["string","null"],"format":"date-time"},"data_ultimo_acesso":{"type":["string","null"],"format":"date-time"},"data_vigencia":{"type":["string","null"],"format":"date-time","description":"Até quando o aluno tem acesso ao curso."},"vigente":{"type":"boolean","description":"Se o acesso ainda está dentro da vigência."},"favorito":{"type":"boolean"},"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}}}},"CursoDetalhado":{"type":"object","description":"Curso com o conteúdo programático e o andamento por subaula.","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Curso"},{"type":"object","properties":{"aulas":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Aula"}}}}}}]}}},"Aula":{"type":"object","properties":{"ordem":{"type":"integer"},"titulo":{"type":"string"},"descricao":{"type":["string","null"]},"carga_horaria":{"type":"integer","description":"Tempo em segundos que o aluno passou na aula."},"subaulas":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SubAula"}}}}}},"SubAula":{"type":"object","properties":{"ordem":{"type":"integer"},"tipo":{"type":"integer"},"tipo_slug":{"type":"string","examples":["apostila"]},"titulo":{"type":"string"},"data_ultimo_acesso":{"type":["string","null"],"format":"date-time","description":"Nulo quando o aluno ainda não abriu a subaula."},"carga_horaria":{"type":"integer","description":"Tempo em segundos que o aluno passou na subaula."}}},"Token":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Token novo do contrato. O anterior deixa de valer."}}},"UrlDeLogin":{"type":"object","required":["token","url"],"properties":{"token":{"type":"string","description":"JWT de uso único embutido na URL."},"url":{"type":"string","format":"uri","description":"URL de login direto; expira em 10 minutos e só funciona uma vez."}}},"RequisicaoJsonRpc":{"type":"object","description":"Envelope JSON-RPC 2.0 do protocolo MCP.","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["integer","string"]},"method":{"type":"string","examples":["tools/list"]},"params":{"type":"object"}}}},"responses":{"NaoAutenticado":{"description":"Token ausente, inválido ou sem permissão para o recurso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Proibido":{"description":"Token válido, mas sem permissão para este recurso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NaoEncontrado":{"description":"Recurso não encontrado para esta conta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"LimiteExcedido":{"description":"Limite de requisições por minuto excedido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}