Documentação da API
Referência
Todos os endereços da API, gerados da especificação OpenAPI 1.0.0-beta. Os exemplos usam o endereço deste servidor.
Baixar openapi.jsonDescoberta
Descoberta automática dos endereços de autorização.
/.well-known/oauth-authorization-server
Metadados do servidor de autorização
Sem chave de acesso
Documento RFC 8414 com os endereços de autorização, troca e revogação, os escopos aceitos e o método PKCE (S256).
Exemplo
curl https://hotlearn.com.br/.well-known/oauth-authorization-serverRespostas
200
Metadados
application/json
{
"issuer": "https://hotlearn.com.br",
"authorization_endpoint": "https://hotlearn.com.br/oauth/authorize",
"token_endpoint": "https://hotlearn.com.br/oauth/token",
"revocation_endpoint": "https://hotlearn.com.br/oauth/revoke",
"scopes_supported": [
"catalog:public",
"account:read",
"catalog:read"
],
"response_types_supported": [
"code"
],
"grant_types_supported": [
"authorization_code",
"refresh_token",
"client_credentials"
],
"code_challenge_methods_supported": [
"S256"
],
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic",
"none"
],
"service_documentation": "https://hotlearn.com.br/desenvolvedores"
}/.well-known/oauth-protected-resource
Metadados da API (recurso protegido)
Sem chave de acesso
Documento RFC 9728 da /api/v1, apontando para o servidor de autorização. Também responde em /.well-known/oauth-protected-resource/api/v1. Usado por clientes MCP.
Exemplo
curl https://hotlearn.com.br/.well-known/oauth-protected-resourceRespostas
200
Metadados
application/json
{
"resource": "https://hotlearn.com.br/api/v1",
"authorization_servers": [
"https://hotlearn.com.br"
],
"scopes_supported": [
"catalog:public",
"account:read",
"catalog:read"
],
"bearer_methods_supported": [
"header"
],
"resource_name": "HotLearn API",
"resource_documentation": "https://hotlearn.com.br/desenvolvedores"
}Autorização
Autorização OAuth 2.1: pedir acesso, trocar o código pela chave, renovar e revogar.
/oauth/authorize
Pedir autorização (abre a tela do HotLearn)
Abrir no navegador da pessoa
Abra este endereço no navegador da pessoa. Ela entra no HotLearn (se ainda não estiver), vê o que o aplicativo poderá fazer e autoriza. Só o dono de uma conta com assinatura ativa ou em teste autoriza. Ao autorizar, o HotLearn volta para o redirect_uri com code e state; ao negar, com error=access_denied. Endereço de retorno fora do cadastro do aplicativo não volta para ele: o HotLearn mostra uma página de erro.
Antes de tudo (inclusive antes de mandar ao cadastro com signup=1), o HotLearn confere o pedido: PKCE S256 (senão, código invalid_request) e external_id (external_id_required, invalid_external_id). Pedido recusado mostra a página de erro com status 400, sem voltar ao aplicativo.
Reconectar: se a conta já tem conexão ativa com o mesmo aplicativo, o mesmo external_id e o mesmo redirect_uri exato (e escopos já aprovados), o HotLearn aprova sem mostrar a tela e só emite uma chave nova: as chaves antigas continuam valendo e display_name/url não mudam. Quando o dono aprova na tela (sempre numa conexão nova, ou quando o aplicativo manda prompt=consent), a conexão é substituída: as chaves antigas param e o nome e o endereço são atualizados.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
response_typeobrigatório |
string = code |
Sempre code. |
client_idobrigatório |
string |
Identificador do aplicativo, recebido no cadastro. |
redirect_uriobrigatório |
string |
Endereço de retorno cadastrado (aceita padrão de subdomínio, ex.: https://*.exemplo.com/retorno). Em produção, só https; http vale apenas fora de produção (testes). |
scopeobrigatório |
string |
Escopos separados por espaço, ex.: account:read catalog:read. |
stateobrigatório |
string |
Valor aleatório seu; volta igual no retorno. Confira-o. Com signup=1, a pessoa pode voltar até 2 horas depois com o mesmo state: guarde-o por pelo menos 2 horas (recomendado: 2 h 15 min). |
code_challengeobrigatório |
string |
PKCE: BASE64URL(SHA256(code_verifier)). |
code_challenge_methodobrigatório |
string = S256 |
Sempre S256. |
external_idopcional |
string |
Identificador do cliente do seu lado (ex.: a escola; o id do tenant, um UUID cabe). Cada (conta, aplicativo, external_id) é uma conexão. De 1 a 64 caracteres entre A-Z a-z 0-9 . _ : -; fora disso (inclusive mais de 64), página de erro 400 com o código invalid_external_id — nunca é cortado. Opcional para aplicativo de uma conta só (ex.: assistente de IA); obrigatório para aplicativo cadastrado como de várias escolas (como o EstudioLMS): sem ele, página de erro 400 com o código external_id_required. |
display_nameopcional |
string |
Opcional. Nome para mostrar ("Em nome de …"). Só é aceito quando o host de url é o mesmo do redirect_uri. |
urlopcional |
string |
Opcional. Endereço do seu lado (ex.: a escola), do mesmo host do redirect_uri. |
promptopcional |
string |
Opcional. consent mostra a tela mesmo quando a conexão já existe. Aprovar na tela substitui a conexão: as chaves antigas param e o nome e o endereço são atualizados. Use quando quiser trocar ou atualizar a conexão. |
signupopcional |
integer |
Opcional. Quem não está logado vai ao cadastro do HotLearn (aviso "Você está assinando por …") e, depois do plano ou do teste grátis, volta uma vez para esta tela. O pedido fica guardado por 2 horas (guarde o state por pelo menos esse tempo). PKCE e external_id são conferidos antes de mandar ao cadastro. |
Exemplo de endereço
https://hotlearn.com.br/oauth/authorize?response_type=code&client_id=SEU_CLIENT_ID&redirect_uri=https%3A%2F%2Fescola.exemplo.com%2Fhotlearn%2Fretorno&scope=account%3Aread%20catalog%3Aread&state=ALEATORIO&code_challenge=DESAFIO&code_challenge_method=S256&external_id=42&display_name=Escola%20Exemplo&url=https%3A%2F%2Fescola.exemplo.comRespostas
302
Volta ao redirect_uri com code e state (ou error=access_denied).
400
Pedido inválido: página de erro do HotLearn, sem redirecionar. Código na página: invalid_request (PKCE ausente ou diferente de S256), external_id_required ou invalid_external_id.
401 Aplicativo desconhecido ou retorno fora do cadastro: página de erro do HotLearn, sem redirecionar.
/oauth/token
Trocar o código pela chave, renovar ou pedir chave de aplicativo
Sem chave de acesso
Três usos, pelo grant_type:
authorization_code: troca ocode(vale 10 minutos, uso único) pela chave de acesso e pela chave de renovação. Mande ocode_verifierdo PKCE.refresh_token: troca a chave de renovação por um par novo. A antiga deixa de valer; usá-la de novo desfaz a conexão inteira.client_credentials: só aplicativo confidencial; a chave só vale para a vitrine pública (catalog:public).
A chave de acesso vale 1 hora; a de renovação, 30 dias sem uso. Erros seguem o padrão OAuth (error, error_description). Limite: 60 chamadas/min por aplicativo e endereço. Depois que a conexão foi desfeita, a renovação responde no formato do OAuth ({"error": "invalid_grant", …}, status 400), e não em application/problem+json: peça para o dono autorizar de novo.
Exemplo
curl -X POST https://hotlearn.com.br/oauth/token \
-d grant_type=authorization_code \
-d client_id=SEU_CLIENT_ID \
-d client_secret=SEU_SEGREDO \
-d code=CODIGO_RECEBIDO \
-d redirect_uri=https://escola.exemplo.com/hotlearn/retorno \
-d code_verifier=SEU_VERIFIERRespostas
200
Chaves emitidas
application/json
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9…",
"refresh_token": "def50200a1b2c3…"
}
400
Código ou chave de renovação inválido, vencido ou já usado
application/json
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked…"
}
401
Aplicativo ou segredo inválido
application/json
{
"error": "invalid_client",
"error_description": "Client authentication failed"
}
429
Limite de chamadas estourado (ver Retry-After)
/oauth/revoke
Revogar uma chave ou desconectar
Sem chave de acesso
RFC 7009. Com a chave de renovação, desfaz a conexão inteira (é assim que o aplicativo desconecta). Com a chave de acesso, revoga só ela. Responde 200 também para chave desconhecida, como manda a RFC. Aplicativo confidencial manda o segredo. Limite: 30 chamadas por minuto.
Exemplo
curl -X POST https://hotlearn.com.br/oauth/revoke \
-d token='def50200a1b2c3…' \
-d client_id=SEU_CLIENT_ID \
-d client_secret=SEU_SEGREDORespostas
200
Revogado (ou chave desconhecida)
application/json
[]
400
token ausente
application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Envie a chave em `token`.",
"code": "invalid_request"
}
401
Aplicativo ou segredo inválido
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Aplicativo desconhecido.",
"code": "invalid_client"
}Conta e conexão
A conta conectada e a própria conexão.
/api/v1/me
A conta conectada
Chave com
account:read
Conta, quem autorizou, plano, situação da assinatura e saldo de créditos. Bom para conferir a conexão logo depois de autorizar. Em subscription vêm só status (trialing, active ou inactive), on_trial e trial_ends_at: não há past_due, data de renovação nem uso do teste.
Exemplo
curl https://hotlearn.com.br/api/v1/me \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Conta
application/json
{
"data": {
"account": {
"id": 12,
"name": "Escola Exemplo"
},
"user": {
"id": 34,
"name": "Ana Souza",
"email": "ana@escola.exemplo.com",
"role": "owner"
},
"plan": {
"name": "Essencial",
"slug": "essencial"
},
"subscription": {
"status": "active",
"on_trial": false,
"trial_ends_at": null
},
"credits": {
"balance": 40,
"unlimited": false
},
"scopes": [
"account:read",
"catalog:read"
]
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}
429
Limite de chamadas estourado (rate_limited); veja Retry-After. Mais de 300 respostas 401 sem chave válida por minuto, do mesmo endereço de rede, também bloqueiam esse endereço com 429.
application/problem+json
{
"type": "about:blank",
"title": "Too Many Requests",
"status": 429,
"detail": "Muitas chamadas. Tente de novo depois do tempo indicado em `Retry-After`.",
"code": "rate_limited"
}/api/v1/usage
Créditos pelo uso da API
Chave com
account:read
A tabela que vale para esta chave: para cada ação medida (export_pdf_section, export_pdf, export_scorm, acquisition, publication, login_link), quantos créditos ela custa, se a cobrança já está ligada (charging), a franquia grátis do mês e o limite por dia, com o que já foi usado. Consulte antes de uma operação pesada para avisar a pessoa. Detalhes no guia Créditos e limites de uso.
Com charging: false, a regra está em simulação: o uso é contado, mas nenhum crédito sai (X-Credits-Charged: 0). O limite por dia vale nos dois casos. O plano Ilimitado não fica isento sozinho: vale o que a tabela diz para ele.
Exemplo
curl https://hotlearn.com.br/api/v1/usage \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Tabela vigente
application/json
{
"data": {
"balance": 4200,
"unlimited": false,
"actions": [
{
"action": "export_pdf",
"credits": 20,
"charging": true,
"free_monthly": 20,
"used_this_month": 20,
"daily_limit": 50,
"used_today": 3
},
{
"action": "publication",
"credits": 0,
"charging": false,
"free_monthly": null,
"used_this_month": 0,
"daily_limit": null,
"used_today": 0
}
]
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}
429
Limite de chamadas estourado (rate_limited); veja Retry-After. Mais de 300 respostas 401 sem chave válida por minuto, do mesmo endereço de rede, também bloqueiam esse endereço com 429.
application/problem+json
{
"type": "about:blank",
"title": "Too Many Requests",
"status": 429,
"detail": "Muitas chamadas. Tente de novo depois do tempo indicado em `Retry-After`.",
"code": "rate_limited"
}/api/v1/connection
A própria conexão
Qualquer chave de aplicativo
O que o HotLearn sabe da conexão desta chave: aplicativo, external_id, nome e endereço, link "abrir lá" e ações. Chave pessoal não tem conexão (404 no_connection).
Exemplo
curl https://hotlearn.com.br/api/v1/connection \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Conexão
application/json
{
"data": {
"id": 7,
"client": {
"id": "01a13fdf-7c67-70b3-a3b7-bb60430403d8",
"name": "EstudioLMS"
},
"external_id": "42",
"display_name": "Escola Exemplo",
"url": "https://escola.exemplo.com",
"open_url_template": "https://escola.exemplo.com/hotlearn/enviar?produto={product}&material={material}&acao={action}",
"actions": [
{
"key": "course",
"label": "Criar um curso novo",
"materials": [
"apostila"
]
}
],
"scopes": [
"account:read",
"catalog:read",
"connection:write"
],
"authorized_by": {
"name": "Ana Souza"
},
"authorized_at": "2026-10-15T14:02:11-03:00",
"last_used_at": "2026-10-16T09:40:00-03:00"
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Chave pessoal (sem conexão)
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Esta chave não pertence a uma conexão de aplicativo (chave pessoal).",
"code": "no_connection"
}/api/v1/connection
Ensinar ao HotLearn como abrir o seu lado
Chave com
connection:write
Atualiza display_name, url, open_url_template e actions. É daí que sai o botão "Enviar para {display_name}" nos materiais do assinante. O open_url_template precisa ser https (em produção) e do mesmo host de url; use {product}, {material} e {action} onde precisar. Campos ausentes ficam como estão.
Exemplo
curl -X PUT https://hotlearn.com.br/api/v1/connection \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Content-Type: application/json" \
-d '{"display_name":"Escola Exemplo","url":"https://escola.exemplo.com","open_url_template":"https://escola.exemplo.com/hotlearn/enviar?produto={product}&material={material}&acao={action}","actions":[{"key":"course","label":"Criar um curso novo","materials":["apostila"]},{"key":"scorm","label":"Criar uma aula SCORM","materials":["scorm"]}]}'Respostas
200
Conexão atualizada
application/json
{
"data": {
"id": 7,
"client": {
"id": "01a13fdf-7c67-70b3-a3b7-bb60430403d8",
"name": "EstudioLMS"
},
"external_id": "42",
"display_name": "Escola Exemplo",
"url": "https://escola.exemplo.com",
"open_url_template": "https://escola.exemplo.com/hotlearn/enviar?produto={product}&material={material}&acao={action}",
"actions": [
{
"key": "course",
"label": "Criar um curso novo",
"materials": [
"apostila"
]
}
],
"scopes": [
"account:read",
"catalog:read",
"connection:write"
],
"authorized_by": {
"name": "Ana Souza"
},
"authorized_at": "2026-10-15T14:02:11-03:00",
"last_used_at": "2026-10-16T09:40:00-03:00"
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}404 Chave pessoal (sem conexão)
422
Dados inválidos (validation_failed)
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"open_url_template": [
"Precisa ser do mesmo domínio de `url`."
]
}
}/api/v1/login-links
Link de entrada já logado
Chave com
login_links:write
Gera um link que abre o HotLearn já logado, direto num destino: studio (painel), library (Meus produtos, ou os materiais de um produto com product_id), material (o editor da apostila) ou scorm (o editor do curso SCORM), com material_id.
- Vale 60 segundos e uma vez só: gere na hora do clique e redirecione a pessoa.
- Se o e-mail for de quem já é membro da conta, a pessoa entra direto. Se não for, o link abre o login do HotLearn com o e-mail preenchido (ninguém entra sem senha) e, depois de entrar, leva ao destino. O dono da conta e os administradores do HotLearn nunca entram só pelo link: vão ao login com o e-mail preenchido e, depois de entrar, seguem ao destino. Se alguém da mesma conta já estiver logado naquele navegador, segue com a própria sessão; se for alguém de outra conta, a sessão é encerrada e o HotLearn pede o login.
- Nos editores, a pessoa vê "Voltar para {nome da conexão}", que leva ao
urlda conexão. - Só aplicativo autorizado (com conexão). Pode consumir créditos da conta conforme a tabela de uso (
GET /usage): a resposta cobrada trazX-Credits-ChargedeX-Credits-Balance; sem saldo,402 insufficient_credits; acima do limite do dia,429 daily_limit_reached. - Limite: 30 chamadas por minuto.
Exemplo
curl -X POST https://hotlearn.com.br/api/v1/login-links \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"coordenacao@escola.exemplo.com","target":"material","material_id":161}'Respostas
201
Link criado
application/json
{
"data": {
"url": "https://hotlearn.com.br/login-link/Q2x8kWm4…",
"expires_in": 60
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Dados inválidos (validation_failed)
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"open_url_template": [
"Precisa ser do mesmo domínio de `url`."
]
}
}Acervo
Acervo: produtos, sumário, prévia, capa, categorias e licença.
/api/v1/products
Listar produtos
Chave com
catalog:readcatalog:public
Acervo (padrão, no idioma pedido), biblioteca da conta (collection=acquired) ou criações da conta (collection=created). Em páginas, por cursor.
owned: a conta já adquiriu (ou é criação dela).exportable: há matriz de conteúdo (a cópia personalizada, o original do acervo ou a da criação), que sempre exporta (PDF), ou um curso SCORM da conta sem erro. Quando falso,export_blocktraz{code, message}:no_matrix(nenhum material) ouscorm_invalid(só cursos SCORM, todos com erro na verificação). Exportável:export_block: null.- O filtro
exportable=trueé feito no banco e não roda a verificação do SCORM: um produto só com cursos SCORM com erro aparece nele, mas vem comexportable: falseescorm_invalid.
Com a chave de aplicativo sem conta (catalog:public), só o acervo e só os campos públicos (sem owned, exportable, credit_cost, público e objetivo).
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
collectionopcional |
string |
catalog (padrão), acquired ou created. |
qopcional |
string |
Busca no título, na descrição curta, no público e no objetivo (não busca no sumário). |
categoryopcional |
string |
Categoria: id ou slug. |
levelopcional |
string |
iniciante, intermediario ou avancado. |
exportableopcional |
boolean |
true ou false. Feito no banco, sem a verificação do SCORM: confira o exportable de cada item. |
localeopcional |
string |
Idioma do acervo (pt_BR, en, es); também pelo Accept-Language. |
limitopcional |
integer |
De 1 a 50 (padrão 12). |
cursoropcional |
string |
O next_cursor da página anterior. |
Exemplo
curl "https://hotlearn.com.br/api/v1/products?collection=catalog&limit=12" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Página de produtos
application/json
{
"data": [
{
"id": 136,
"slug": "arte-e-cultura",
"title": "Arte e Cultura",
"short_description": "Apostila para turmas do ensino médio.",
"locale": "pt_BR",
"category": {
"id": 5,
"slug": "educacao-e-ead",
"name": "Educação e EAD"
},
"level": "iniciante",
"level_label": "Iniciante",
"workload": "30h",
"contents": [
"apostila",
"quiz_lms"
],
"cover_url": "https://hotlearn.com.br/storage/negocio-pronto/products/136/capa.jpg",
"published_at": "2026-10-08T14:38:56+00:00",
"origin": "catalog",
"audience": "Professores do ensino médio",
"objective": "Trabalhar arte e cultura com projetos.",
"credit_cost": 1000,
"version": "1.0",
"owned": true,
"exportable": true,
"export_block": null,
"publications_count": 1
},
{
"id": 141,
"slug": "oficina-de-teatro",
"title": "Oficina de Teatro",
"short_description": "Curso SCORM para turmas do ensino médio.",
"locale": "pt_BR",
"category": {
"id": 5,
"slug": "educacao-e-ead",
"name": "Educação e EAD"
},
"level": "iniciante",
"level_label": "Iniciante",
"workload": "30h",
"contents": [],
"cover_url": "https://hotlearn.com.br/storage/negocio-pronto/products/141/capa.jpg",
"published_at": null,
"origin": "created",
"audience": "Professores do ensino médio",
"objective": "Trabalhar arte e cultura com projetos.",
"credit_cost": 0,
"version": "1.0",
"owned": true,
"exportable": false,
"export_block": {
"code": "scorm_invalid",
"message": "Os cursos SCORM deste produto têm erros e ainda não podem ser exportados. Corrija-os no HotLearn."
},
"publications_count": 0
}
],
"next_cursor": "eyJpZCI6MTM2LCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9"
}
400
O cursor informado é inválido. Recomece a lista sem ele.
application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "O `cursor` informado é inválido. Recomece a lista sem ele.",
"code": "invalid_cursor"
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}
422
Dados inválidos.
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"collection": [
"Use catalog, acquired ou created."
]
}
}
429
Limite de chamadas estourado (rate_limited); veja Retry-After. Mais de 300 respostas 401 sem chave válida por minuto, do mesmo endereço de rede, também bloqueiam esse endereço com 429.
application/problem+json
{
"type": "about:blank",
"title": "Too Many Requests",
"status": 429,
"detail": "Muitas chamadas. Tente de novo depois do tempo indicado em `Retry-After`.",
"code": "rate_limited"
}/api/v1/products/{product}
Detalhe do produto, com o sumário
Chave com
catalog:read
Tudo da lista mais o sumário (toc), a licença e os links de prévia e capa.
toc são as seções da matriz, cortadas nos títulos principais: kind é module, intro (abertura curta) ou appendix (glossário, referências, gabarito…). source diz de onde veio: personalizada (a cópia que a conta editou), original (a do acervo) ou criacao. Ler pela API nunca cria a cópia personalizada.
Produto de outra conta, ou fora do ar e não adquirido: 404.
exportable e export_block seguem a mesma regra da lista: export_block é null quando exporta; senão, {code, message} com no_matrix ou scorm_invalid.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
productobrigatório |
integer |
Identificador do produto. |
Exemplo
curl https://hotlearn.com.br/api/v1/products/136 \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Produto
application/json
{
"data": {
"id": 136,
"slug": "arte-e-cultura",
"title": "Arte e Cultura",
"short_description": "Apostila para turmas do ensino médio.",
"locale": "pt_BR",
"category": {
"id": 5,
"slug": "educacao-e-ead",
"name": "Educação e EAD"
},
"level": "iniciante",
"level_label": "Iniciante",
"workload": "30h",
"contents": [
"apostila",
"quiz_lms"
],
"cover_url": "https://hotlearn.com.br/storage/negocio-pronto/products/136/capa.jpg",
"published_at": "2026-10-08T14:38:56+00:00",
"origin": "catalog",
"audience": "Professores do ensino médio",
"objective": "Trabalhar arte e cultura com projetos.",
"credit_cost": 1000,
"version": "1.0",
"owned": true,
"exportable": true,
"export_block": null,
"source": "personalizada",
"toc": [
{
"index": 0,
"title": "Como aproveitar esta apostila",
"kind": "intro",
"words": 310,
"est_bytes": 4200
},
{
"index": 1,
"title": "Capítulo 1 — Arte para quê?",
"kind": "module",
"words": 1194,
"est_bytes": 14706
},
{
"index": 2,
"title": "Glossário",
"kind": "appendix",
"words": 420,
"est_bytes": 5120
}
],
"license": {
"id": 1,
"title": "Licença Comercial",
"version": "2.0"
},
"has_preview": true,
"links": {
"preview": "https://hotlearn.com.br/api/v1/products/136/preview",
"cover": "https://hotlearn.com.br/api/v1/products/136/cover",
"license": "https://hotlearn.com.br/api/v1/licenses/1"
}
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/products/{product}/preview
Prévia em PDF
Chave com
catalog:read
O PDF de amostra do produto, entregue direto (application/pdf). 404 quando o produto não tem prévia. Exige chave de conta com catalog:read: a vitrine pública (catalog:public, sem conta) tem só a lista, a capa e as categorias, sem prévia.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
productobrigatório |
integer |
Identificador do produto. |
Exemplo
curl https://hotlearn.com.br/api/v1/products/136/preview \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
O arquivo PDF
application/pdf
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/products/{product}/cover
Capa
Chave com
catalog:readcatalog:public
A imagem da capa, entregue direto. Para mostrar numa página, o cover_url da lista já é um endereço público, sem chave.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
productobrigatório |
integer |
Identificador do produto. |
Exemplo
curl https://hotlearn.com.br/api/v1/products/136/cover \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
A imagem
image/*
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/categories
Categorias
Chave com
catalog:readcatalog:public
Todas as categorias, com quantos produtos do acervo publicado cada uma tem no idioma pedido. Lista curta: vem inteira, sem cursor.
Exemplo
curl https://hotlearn.com.br/api/v1/categories \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Categorias
application/json
{
"data": [
{
"id": 5,
"slug": "educacao-e-ead",
"name": "Educação e EAD",
"products_count": 12
}
]
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}/api/v1/licenses/{license}
Licença comercial
Chave com
catalog:read
Título, versão e texto (HTML) da licença, para mostrar antes de adquirir. O id vem em license no detalhe do produto.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
licenseobrigatório |
integer |
Identificador da licença. |
Exemplo
curl https://hotlearn.com.br/api/v1/licenses/1 \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Licença
application/json
{
"data": {
"id": 1,
"title": "Licença Comercial",
"version": "2.0",
"active": true,
"body_html": "<h3>Licença Comercial</h3><p>…</p>"
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}Aquisições
Adquirir produtos com os créditos da conta e ver o histórico.
/api/v1/acquisitions
Adquirir um produto
Chave com
acquisitions:write
Desbloqueia o produto para a conta, com a mesma regra do botão do HotLearn: debita os créditos (o custo está em credit_cost), respeita o limite do período de teste, e plano ilimitado não debita.
Idempotency-Keyobrigatório. Repetir a chamada com a mesma chave devolve a mesma resposta, sem cobrar de novo.- Produto já adquirido:
200comcharged: false, sem cobrar. license_version: a versão da licença mostrada à pessoa (GET /licenses/{id}). Se mudou,409 license_outdatedcom a versão vigente.on_behalf_of: quem clicou do lado do aplicativo (fica na auditoria do HotLearn).- Quem assina do lado do HotLearn é quem autorizou a conexão (ou, se essa pessoa saiu da conta, o dono). Sem nenhum dos dois:
409 connection_owner_missing. Pode consumir créditos da conta conforme a tabela de uso (GET /usage): a resposta cobrada trazX-Credits-ChargedeX-Credits-Balance; sem saldo,402 insufficient_credits; acima do limite do dia,429 daily_limit_reached.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
Idempotency-Keyobrigatório |
string |
Obrigatório: um valor único por operação (ex.: um UUID). Sem ele, 400 idempotency_key_required. A resposta (inclusive 4xx) fica guardada por 24 horas e volta igual para a mesma chave; mesma chave com outros dados, 422 idempotency_key_reused; chamada simultânea com a mesma chave, 409 idempotency_in_progress. Use uma chave nova a cada nova tentativa (por exemplo, depois de corrigir o pedido). |
Exemplo
curl -X POST https://hotlearn.com.br/api/v1/acquisitions \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Idempotency-Key: 6f1c2e8a-3b0d-4c55-9a7e-2f1d9b8c4a10" \
-H "Content-Type: application/json" \
-d '{"product_id":136,"license_version":"2.0","on_behalf_of":{"external_user_id":"u-9","name":"Coordenação da Escola","email":"coordenacao@escola.exemplo.com"}}'Respostas
201
Adquirido agora
application/json
{
"data": {
"acquisition": {
"id": 58,
"product": {
"id": 136,
"slug": "arte-e-cultura",
"title": "Arte e Cultura"
},
"acquired_at": "2026-10-16T10:12:00-03:00",
"source": "plan_credit",
"credits_spent": 2,
"license_version": "2.0",
"acquired_by": {
"name": "Ana Souza"
},
"via": {
"app": "EstudioLMS",
"client_id": "01a13fdf-7c67-70b3-a3b7-bb60430403d8",
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola",
"email": "coordenacao@escola.exemplo.com"
}
}
},
"charged": true,
"balance": {
"credits": 38,
"unlimited": false
}
}
}
200
Já era da conta (charged: false, nada cobrado)
400
Envie o cabeçalho Idempotency-Key (um valor único por operação).
application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Envie o cabeçalho `Idempotency-Key` (um valor único por operação).",
"code": "idempotency_key_required"
}
402
A conta não tem créditos suficientes para este produto.
application/problem+json
{
"type": "about:blank",
"title": "Payment Required",
"status": 402,
"detail": "A conta não tem créditos suficientes para este produto.",
"code": "insufficient_credits",
"required": 5,
"available": 1
}
403
A assinatura da conta não está ativa. Para adquirir, a conta precisa de assinatura ativa ou do período de teste.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A assinatura da conta não está ativa. Para adquirir, a conta precisa de assinatura ativa ou do período de teste.",
"code": "subscription_inactive"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
409
A licença mudou: a versão vigente é 2.0. Mostre a licença nova à pessoa e envie essa versão.
application/problem+json
{
"type": "about:blank",
"title": "Conflict",
"status": 409,
"detail": "A licença mudou: a versão vigente é 2.0. Mostre a licença nova à pessoa e envie essa versão.",
"code": "license_outdated",
"license": {
"id": 1,
"version": "2.0"
}
}
422
Dados inválidos (validation_failed)
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"open_url_template": [
"Precisa ser do mesmo domínio de `url`."
]
}
}/api/v1/acquisitions
Histórico de aquisições
Chave com
acquisitions:read
Tudo o que a conta adquiriu, do mais recente para o mais antigo, pelo HotLearn ou por qualquer aplicativo: produto, data, origem (plan_credit, trial, unlimited, admin), créditos gastos, versão da licença e, quando veio de um aplicativo, qual (via). Filtro opcional product_id. Em páginas, por cursor.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
product_idopcional |
integer |
Só as aquisições deste produto. |
limitopcional |
integer |
De 1 a 50 (padrão 12). |
cursoropcional |
string |
O next_cursor da página anterior. |
Exemplo
curl "https://hotlearn.com.br/api/v1/acquisitions?limit=12" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Página de aquisições
application/json
{
"data": [
{
"id": 58,
"product": {
"id": 136,
"slug": "arte-e-cultura",
"title": "Arte e Cultura"
},
"acquired_at": "2026-10-16T10:12:00-03:00",
"source": "plan_credit",
"credits_spent": 2,
"license_version": "2.0",
"acquired_by": {
"name": "Ana Souza"
},
"via": {
"app": "EstudioLMS",
"client_id": "01a13fdf-7c67-70b3-a3b7-bb60430403d8",
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola",
"email": "coordenacao@escola.exemplo.com"
}
}
}
],
"next_cursor": null
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}Materiais e arquivos
Materiais de um produto (matriz, curso SCORM, quadro) e pedidos de arquivo.
/api/v1/products/{product}/materials
Materiais do produto
Chave com
materials:read
O que a conta tem deste produto:
- a matriz: a cópia que a conta personalizou (
source: personalizada) ou, sem cópia, a original do acervo (original). Ler nunca cria a cópia; - o que a conta criou sobre o produto: outras matrizes, cursos SCORM, quadros (
criacao).
formats lista os arquivos que já dá para pedir. Curso SCORM traz valid e errors (com erro, o pacote não sai). Exige o produto adquirido (ou criação da conta) e assinatura ativa ou em teste.
Quando a escola personaliza um produto do acervo, a matriz vira uma cópia com outro id (source passa de original a personalizada). Liste os materiais de novo em vez de guardar o id; as publicações antigas avisam com outdated_reason: "personalized" e current_material_id.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
productobrigatório |
integer |
Identificador do produto. |
Exemplo
curl https://hotlearn.com.br/api/v1/products/136/materials \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Materiais
application/json
{
"data": [
{
"id": 161,
"product_id": 136,
"type": "apostila",
"title": "Arte e Cultura",
"source": "personalizada",
"version": "1790850188",
"updated_at": "2026-10-08T14:03:08+00:00",
"formats": [
"pdf"
],
"exportable": true,
"sections_count": 26
},
{
"id": 162,
"product_id": 136,
"type": "scorm",
"title": "Curso de Arte",
"source": "criacao",
"version": "1791390405",
"updated_at": "2026-10-14T20:06:45+00:00",
"formats": [
"scorm12",
"scorm2004",
"html5"
],
"exportable": true,
"valid": true,
"errors": []
}
]
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/materials/{material}
Um material
Chave com
materials:read
Dados do material, com as seções (capítulos) da matriz ou os avisos do curso SCORM. A resposta traz ETag com a versão: mande If-None-Match com ela e, se nada mudou, a resposta é 304, sem corpo. A versão muda a cada salvamento.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
materialobrigatório |
integer |
Identificador do material. |
Exemplo
curl https://hotlearn.com.br/api/v1/materials/162 \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Material
application/json
{
"data": {
"id": 161,
"product_id": 136,
"type": "apostila",
"title": "Arte e Cultura",
"source": "personalizada",
"version": "1790850188",
"updated_at": "2026-10-08T14:03:08+00:00",
"formats": [
"pdf"
],
"exportable": true,
"sections_count": 26,
"sections": [
{
"index": 0,
"title": "Capítulo 1 — Arte para quê?",
"kind": "module",
"words": 1194,
"est_bytes": 14706
}
]
}
}
304
Não mudou desde a versão do If-None-Match
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/materials/{material}/content
Conteúdo da matriz
Chave com
materials:read
A matriz inteira, no format pedido:
html: HTML de lição, para colar num editor de LMS. Só estrutura simples (títulos, parágrafos, listas, tabelas, citações, imagens) e cor em estilo dentro das próprias tags: caixas viram tabela de uma célula com fundo, que os editores (como o CKEditor 4) mantêm ao editar. Sem classes, sem<style>, sem script. As respostas das perguntas vão num bloco Gabarito no fim.markdown: para IA, MCP e ferramentas de texto. Caixas viram citação; checklist vira- [ ]; gabarito no fim.json: o documento do editor (o mesmo do "Exportar JSON" do HotLearn).
Rótulos ("Gabarito", "Questão", "Atividade") saem no idioma do material. ETag e If-None-Match como em GET /materials/{id}.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
materialobrigatório |
integer |
Identificador da matriz. |
formatopcional |
string |
html (padrão), markdown ou json. |
Exemplo
curl "https://hotlearn.com.br/api/v1/materials/161/content?format=html" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Conteúdo
application/json
{
"data": {
"material_id": 161,
"version": "1790850188",
"source": "personalizada",
"format": "html",
"title": "Inglês para Viagem",
"content": "<h2>O cartão de embarque</h2><p>Boarding é quando o embarque começa…</p><table cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;border-collapse:collapse;margin:16px 0\"><tr><td style=\"background:#e8f3f5;border-left:4px solid #1d8a9c;padding:12px 16px\"><p><strong>Dica</strong></p><p>Confira o painel.</p></td></tr></table>…<h2>Gabarito</h2><ol style=\"list-style:none;padding-left:0\"><li>Questão 1. D) Até 22:35</li></ol>"
}
}304 Não mudou
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Formato não disponível para este material. Use: html, markdown, json.
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Formato não disponível para este material. Use: html, markdown, json.",
"code": "format_unavailable",
"formats": [
"html",
"markdown",
"json"
]
}/api/v1/materials/{material}/sections/{section}
Um capítulo da matriz
Chave com
materials:read
Uma seção do sumário (index de GET /materials/{id}), em html ou markdown. O título do capítulo vem em title, fora do corpo: no LMS, ele vira o nome da lição. O gabarito das perguntas do capítulo vai no fim do corpo.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
materialobrigatório |
integer |
Identificador da matriz. |
sectionobrigatório |
integer |
index da seção. |
formatopcional |
string |
html (padrão) ou markdown. |
Exemplo
curl "https://hotlearn.com.br/api/v1/materials/161/sections/1?format=html" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Capítulo
application/json
{
"data": {
"material_id": 161,
"version": "1790850188",
"source": "personalizada",
"format": "html",
"title": "Módulo 2 — No aeroporto e a bordo",
"section": {
"index": 1,
"title": "Módulo 2 — No aeroporto e a bordo",
"kind": "module",
"words": 2210,
"est_bytes": 26003
},
"content": "<h2>O cartão de embarque</h2><p>Boarding é quando o embarque começa…</p><table cellpadding=\"0\" cellspacing=\"0\" style=\"width:100%;border-collapse:collapse;margin:16px 0\"><tr><td style=\"background:#e8f3f5;border-left:4px solid #1d8a9c;padding:12px 16px\"><p><strong>Dica</strong></p><p>Confira o painel.</p></td></tr></table>…<h2>Gabarito</h2><ol style=\"list-style:none;padding-left:0\"><li>Questão 1. D) Até 22:35</li></ol>"
}
}304 Não mudou
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Formato não disponível para este material. Use: html, markdown, json.
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Formato não disponível para este material. Use: html, markdown, json.",
"code": "format_unavailable",
"formats": [
"html",
"markdown",
"json"
]
}/api/v1/materials/{material}/exports
Pedir um arquivo
Chave com
materials:read
Pede o arquivo de um material num dos formats dele:
-
matriz:
pdf— inteira, ou só um capítulo comsection(oindexdo sumário; o PDF do capítulo sai sem capa, sumário e contracapa); -
curso SCORM:
scorm12,scorm2004ouhtml5. -
Já há um arquivo pronto da mesma versão, formato e capítulo:
200com o pedidoready. -
Senão:
202com o pedidoqueued. Acompanhe emGET /exports/{id}atéreadye baixe em/file. -
Curso SCORM com erro:
422 scorm_invalidcom a lista emerrors(corrigir no editor SCORM do HotLearn). -
Idempotency-Keyobrigatório. Pode consumir créditos da conta conforme a tabela de uso (GET /usage): a resposta cobrada trazX-Credits-ChargedeX-Credits-Balance; sem saldo,402 insufficient_credits; acima do limite do dia,429 daily_limit_reached.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
materialobrigatório |
integer |
Identificador do material. |
Idempotency-Keyobrigatório |
string |
Obrigatório: um valor único por operação (ex.: um UUID). Sem ele, 400 idempotency_key_required. A resposta (inclusive 4xx) fica guardada por 24 horas e volta igual para a mesma chave; mesma chave com outros dados, 422 idempotency_key_reused; chamada simultânea com a mesma chave, 409 idempotency_in_progress. Use uma chave nova a cada nova tentativa (por exemplo, depois de corrigir o pedido). |
Exemplo
curl -X POST https://hotlearn.com.br/api/v1/materials/162/exports \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Idempotency-Key: 6f1c2e8a-3b0d-4c55-9a7e-2f1d9b8c4a10" \
-H "Content-Type: application/json" \
-d '{"format":"scorm12"}'Respostas
202
Pedido criado (queued)
application/json
{
"data": {
"id": 31,
"material_id": 162,
"format": "scorm12",
"section": null,
"version": "1791390405",
"status": "queued",
"size": null,
"expires_at": null,
"error": null,
"links": {
"self": "https://hotlearn.com.br/api/v1/exports/31",
"file": null
}
}
}
200
Já estava pronto (ready)
application/json
{
"data": {
"id": 31,
"material_id": 162,
"format": "scorm12",
"section": null,
"version": "1791390405",
"status": "ready",
"size": 98155,
"expires_at": "2026-10-17T19:42:58+00:00",
"error": null,
"links": {
"self": "https://hotlearn.com.br/api/v1/exports/31",
"file": "https://hotlearn.com.br/api/v1/exports/31/file"
}
}
}
400
Envie o cabeçalho Idempotency-Key (um valor único por operação).
application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Envie o cabeçalho `Idempotency-Key` (um valor único por operação).",
"code": "idempotency_key_required"
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
O curso SCORM tem erros e não pode ser gerado. Corrija no editor SCORM do HotLearn.
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "O curso SCORM tem erros e não pode ser gerado. Corrija no editor SCORM do HotLearn.",
"code": "scorm_invalid",
"errors": [
{
"code": "no_screens",
"message": "O curso não tem telas."
}
]
}/api/v1/exports/{export}
Andamento do pedido
Chave com
materials:read
status: queued (na fila), running (gerando), ready (pronto, com size e expires_at), failed (com error) ou expired (passou das 24 horas; peça de novo). Consulte a cada poucos segundos até sair de queued/running.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
exportobrigatório |
integer |
Identificador do pedido. |
Exemplo
curl https://hotlearn.com.br/api/v1/exports/31 \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Pedido
application/json
{
"data": {
"id": 31,
"material_id": 162,
"format": "scorm12",
"section": null,
"version": "1791390405",
"status": "ready",
"size": 98155,
"expires_at": "2026-10-17T19:42:58+00:00",
"error": null,
"links": {
"self": "https://hotlearn.com.br/api/v1/exports/31",
"file": "https://hotlearn.com.br/api/v1/exports/31/file"
}
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/exports/{export}/file
Baixar o arquivo
Chave com
materials:read
O arquivo pronto (application/pdf ou application/zip). Fica disponível por 24 horas. Ainda não pronto (ou falhou): 409 export_not_ready. Vencido: 410 export_expired.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
exportobrigatório |
integer |
Identificador do pedido. |
Exemplo
curl https://hotlearn.com.br/api/v1/exports/31/file \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
O arquivo
application/pdf
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
409
O arquivo ainda não está pronto. Consulte o pedido e tente de novo em instantes.
application/problem+json
{
"type": "about:blank",
"title": "Conflict",
"status": "running",
"detail": "O arquivo ainda não está pronto. Consulte o pedido e tente de novo em instantes.",
"code": "export_not_ready"
}
410
O arquivo venceu (fica 24 horas). Faça um pedido novo.
application/problem+json
{
"type": "about:blank",
"title": "Gone",
"status": 410,
"detail": "O arquivo venceu (fica 24 horas). Faça um pedido novo.",
"code": "export_expired"
}/api/v1/products/{product}/quizzes
Provas do produto
Chave com
materials:read
A prova do produto, com o número de questões e os formats disponíveis: o CSV de cada plataforma que o produto traz (csv-lms-estudio, csv-moodle, csv) e sempre json. Mesmas regras de posse dos materiais.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
productobrigatório |
integer |
Identificador do produto. |
Exemplo
curl https://hotlearn.com.br/api/v1/products/136/quizzes \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Provas
application/json
{
"data": [
{
"id": 412,
"product_id": 136,
"title": "Prova — CSV (LMS Estúdio)",
"questions_count": 10,
"formats": [
"csv-lms-estudio",
"csv-moodle",
"json"
]
}
]
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}/api/v1/quizzes/{quiz}
Uma prova num formato
Chave com
materials:read
csv-lms-estudio,csv-moodle,csv: o arquivo original (text/csv), para importar com o importador da própria plataforma.json(padrão): as perguntas lidas do CSV, com as alternativas e qual é a certa.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
quizobrigatório |
integer |
id da prova (de GET /products/{id}/quizzes). |
formatopcional |
string |
json (padrão) ou um dos CSV. |
Exemplo
curl "https://hotlearn.com.br/api/v1/quizzes/412?format=json" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
A prova
application/json
{
"data": {
"id": 412,
"product_id": 136,
"title": "Prova — CSV (LMS Estúdio)",
"questions_count": 10,
"formats": [
"csv-lms-estudio",
"csv-moodle",
"json"
],
"questions": [
{
"text": "Qual o portão do voo?",
"points": 10,
"options": [
{
"text": "B12",
"correct": false
},
{
"text": "B15",
"correct": true
}
]
}
]
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Formato não disponível para este material. Use: csv-lms-estudio, csv-moodle, json.
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Formato não disponível para este material. Use: csv-lms-estudio, csv-moodle, json.",
"code": "format_unavailable",
"formats": [
"csv-lms-estudio",
"csv-moodle",
"json"
]
}Publicações
O que o aplicativo criou do lado dele a partir dos materiais.
/api/v1/publications
Registrar uma publicação
Chave com
publications:write
Conta ao HotLearn o que o aplicativo criou do lado dele a partir de um material: um curso, uma lição, uma aula SCORM. A publicação aparece para a escola na página Integrações do HotLearn.
- Informe
material_id(ou sóproduct_id) ekind(course,lesson,scorm_lesson,other). material_versioné a versão usada (padrão: a atual). Quando a escola salvar o material de novo (ou personalizar o original do acervo), a publicação volta comoutdated: truee o motivo emoutdated_reason(updatedoupersonalized): é a deixa para oferecer a atualização.parts: os capítulos enviados (indexdo sumário), cada um com a referência do seu lado.external_refeexternal_url: como achar o item do seu lado.- Só aplicativo autorizado (com conexão).
Idempotency-Keyobrigatório. Pode consumir créditos da conta conforme a tabela de uso (GET /usage): a resposta cobrada trazX-Credits-ChargedeX-Credits-Balance; sem saldo,402 insufficient_credits; acima do limite do dia,429 daily_limit_reached.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
Idempotency-Keyobrigatório |
string |
Obrigatório: um valor único por operação (ex.: um UUID). Sem ele, 400 idempotency_key_required. A resposta (inclusive 4xx) fica guardada por 24 horas e volta igual para a mesma chave; mesma chave com outros dados, 422 idempotency_key_reused; chamada simultânea com a mesma chave, 409 idempotency_in_progress. Use uma chave nova a cada nova tentativa (por exemplo, depois de corrigir o pedido). |
Exemplo
curl -X POST https://hotlearn.com.br/api/v1/publications \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Idempotency-Key: 6f1c2e8a-3b0d-4c55-9a7e-2f1d9b8c4a10" \
-H "Content-Type: application/json" \
-d '{"material_id":161,"kind":"course","title":"Inglês para Viagem — Turma A","external_ref":"curso-77","external_url":"https://escola.lmsestudio.com/cursos/77","parts":[{"index":1,"title":"Módulo 2 — No aeroporto","external_ref":"licao-301"}],"on_behalf_of":{"external_user_id":"u-9","name":"Coordenação da Escola"}}'Respostas
201
Registrada
application/json
{
"data": {
"id": 15,
"product": {
"id": 136,
"title": "Inglês para Viagem"
},
"material_id": 161,
"current_material_id": 161,
"material_version": "1790850188",
"outdated": false,
"outdated_reason": null,
"kind": "course",
"external_ref": "curso-77",
"external_url": "https://escola.lmsestudio.com/cursos/77",
"title": "Inglês para Viagem — Turma A",
"status": "published",
"parts": [
{
"index": 1,
"title": "Módulo 2 — No aeroporto",
"external_ref": "licao-301"
}
],
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola"
},
"created_at": "2026-10-16T10:30:00-03:00",
"updated_at": "2026-10-16T10:30:00-03:00"
}
}
400
Envie o cabeçalho Idempotency-Key (um valor único por operação).
application/problem+json
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Envie o cabeçalho `Idempotency-Key` (um valor único por operação).",
"code": "idempotency_key_required"
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
A conta ainda não adquiriu este produto. Adquira para ler os materiais.
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A conta ainda não adquiriu este produto. Adquira para ler os materiais.",
"code": "not_acquired"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Dados inválidos (validation_failed)
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"open_url_template": [
"Precisa ser do mesmo domínio de `url`."
]
}
}/api/v1/publications
Publicações do aplicativo
Chave com
publications:read
As publicações que este aplicativo registrou nesta conta (de todas as conexões dele), da mais recente para a mais antiga. Filtros product_id, material_id e status. Em páginas, por cursor. Use outdated para saber o que mudou no HotLearn depois de publicado. Com chave pessoal (do dono), a lista traz as publicações de todos os aplicativos da conta, só para leitura.
Cada publicação traz outdated, outdated_reason e current_material_id:
- em dia:
outdated: false,outdated_reason: nullecurrent_material_idigual amaterial_id; updated: a escola salvou o material de novo (a versão mudou);personalized: a publicação saiu do original do acervo e a escola personalizou depois; a matriz dela agora é a cópia, com outro id (current_material_id).
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
product_idopcional |
integer |
Só deste produto. |
material_idopcional |
integer |
Só deste material. |
statusopcional |
string |
Situação. |
limitopcional |
integer |
De 1 a 50 (padrão 12). |
cursoropcional |
string |
O next_cursor da página anterior. |
Exemplo
curl "https://hotlearn.com.br/api/v1/publications?status=published" \
-H "Authorization: Bearer $HOTLEARN_KEY"Respostas
200
Publicações
application/json
{
"data": [
{
"id": 15,
"product": {
"id": 136,
"title": "Inglês para Viagem"
},
"material_id": 161,
"current_material_id": 161,
"material_version": "1790850188",
"outdated": false,
"outdated_reason": null,
"kind": "course",
"external_ref": "curso-77",
"external_url": "https://escola.lmsestudio.com/cursos/77",
"title": "Inglês para Viagem — Turma A",
"status": "published",
"parts": [
{
"index": 1,
"title": "Módulo 2 — No aeroporto",
"external_ref": "licao-301"
}
],
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola"
},
"created_at": "2026-10-16T10:30:00-03:00",
"updated_at": "2026-10-16T10:30:00-03:00"
},
{
"id": 12,
"product": {
"id": 136,
"title": "Inglês para Viagem"
},
"material_id": 158,
"current_material_id": 161,
"material_version": "1789000000",
"outdated": true,
"outdated_reason": "personalized",
"kind": "course",
"external_ref": "curso-70",
"external_url": "https://escola.lmsestudio.com/cursos/70",
"title": "Inglês para Viagem — Turma piloto",
"status": "published",
"parts": [],
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola"
},
"created_at": "2026-10-10T09:00:00-03:00",
"updated_at": "2026-10-10T09:00:00-03:00"
}
],
"next_cursor": null
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
403
Falta o escopo da rota (insufficient_scope) ou a conta está inativa (account_inactive)
application/problem+json
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "A chave não tem a permissão necessária: account:read.",
"code": "insufficient_scope",
"scopes": [
"account:read"
]
}/api/v1/publications/{publication}
Atualizar uma publicação
Chave com
publications:write
Muda title, status (draft, published, archived) ou external_url. Só as publicações deste aplicativo; de outro, 404. Só esses três campos mudam (parts não). Não há DELETE: quando o curso for apagado do seu lado, mande PATCH com status: archived.
Parâmetros
| Nome | Tipo | Descrição |
|---|---|---|
publicationobrigatório |
integer |
Identificador da publicação. |
Exemplo
curl -X PATCH https://hotlearn.com.br/api/v1/publications/15 \
-H "Authorization: Bearer $HOTLEARN_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"archived"}'Respostas
200
Atualizada
application/json
{
"data": {
"id": 15,
"product": {
"id": 136,
"title": "Inglês para Viagem"
},
"material_id": 161,
"current_material_id": 161,
"material_version": "1790850188",
"outdated": false,
"outdated_reason": null,
"kind": "course",
"external_ref": "curso-77",
"external_url": "https://escola.lmsestudio.com/cursos/77",
"title": "Inglês para Viagem — Turma A",
"status": "archived",
"parts": [
{
"index": 1,
"title": "Módulo 2 — No aeroporto",
"external_ref": "licao-301"
}
],
"on_behalf_of": {
"external_user_id": "u-9",
"name": "Coordenação da Escola"
},
"created_at": "2026-10-16T10:30:00-03:00",
"updated_at": "2026-10-16T10:30:00-03:00"
}
}
401
Chave ausente, inválida, vencida ou de conexão desfeita. unauthenticated: renove uma vez com a chave de renovação. connection_revoked: não renove; a escola desconectou, peça para conectar de novo.
application/problem+json
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Chave ausente, inválida ou vencida. Envie `Authorization: Bearer {chave}` ou renove a chave.",
"code": "unauthenticated"
}
404
Não encontrado.
application/problem+json
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Não encontrado.",
"code": "not_found"
}
422
Dados inválidos (validation_failed)
application/problem+json
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Dados inválidos.",
"code": "validation_failed",
"errors": {
"open_url_template": [
"Precisa ser do mesmo domínio de `url`."
]
}
}Documentação
Esta especificação.
/api/v1/openapi.json
Esta especificação (OpenAPI 3.1)
Sem chave de acesso
Para gerar clientes ou importar no Postman/Insomnia. Limite: 60 chamadas por minuto.
Exemplo
curl https://hotlearn.com.br/api/v1/openapi.json