> ## Documentation Index
> Fetch the complete documentation index at: https://ajuda.memberkit.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Referência da API de membros

> Endereço, autenticação, paginação, limites e erros da API para construir a sua própria área de membros.

A API de membros foi feita para você construir a sua própria área de membros, com o seu visual e no seu domínio. Cada chamada é feita em nome de um aluno logado: login, cursos, aulas, progresso, comentários, comunidade e o resto do que ele faz.

Ela é diferente da [API de operador](https://ajuda.memberkit.com.br/referencia-api/introducao.md), que administra a área de membros inteira com uma chave secreta e nunca deve ir para um site.

## Endereço

```
https://memberkit.com.br/api/headless/v1
```

O endereço é o mesmo para todas as áreas de membros. A chave headless, enviada em toda chamada, diz qual é a sua.

A API aceita chamadas de qualquer origem (CORS) e não usa cookies, então um site no navegador pode chamá-la diretamente.

## Autenticação

Toda chamada leva a chave headless da área de membros, inclusive as que já levam o token do aluno. Só os links de `download_url`, que o navegador abre sozinho, dispensam a chave.

```
X-Memberkit-Headless-Key: <chave headless>
```

Copie a chave no painel, em **Configurações > Acesso via API > Chave headless**. Ela é pública: pode ir no código do site ou do aplicativo. Se a chave vazar para um uso que você não autorizou, peça uma nova ao suporte da Memberkit por e-mail. A troca invalida a anterior na hora: o site que ainda usa a chave antiga para de funcionar, mesmo para alunos logados, até receber a nova.

`POST /auth/login` devolve o token do aluno em `access_token`. Envie-o, junto com a chave, em todas as outras chamadas:

```
Authorization: Bearer <access_token>
```

* **O token vale por duas semanas.** Não há token de renovação: quando ele expira, o aluno entra de novo.
* **Uma sessão por aluno.** Entrar em outro dispositivo, no seu site ou na área de membros hospedada, encerra a sessão anterior, que passa a responder `session_replaced`. Donos e administradores podem ter várias sessões.
* **Sair encerra só aquele dispositivo.** `POST /auth/logout` revoga o token enviado.
* **Trocar ou redefinir a senha encerra todos os tokens.** `POST /profile/change_password` devolve um token novo para o dispositivo atual.
* **Login único:** o token de login de 24 horas do aluno, gerado pela [API de operador](https://ajuda.memberkit.com.br/referencia-api/post-tokens.md) ou presente nos templates de e-mail, é trocado por um token comum em `POST /auth/exchange`.

### Por que não há token de renovação

Muitas APIs usam um token de acesso curto, de cerca de uma hora, e um token de renovação para estendê-lo sem novo login. A API de membros usa um único token de duas semanas de propósito:

* **Encerrar uma sessão vale na hora.** Sair, trocar a senha ou entrar em outro dispositivo invalida o token na requisição seguinte. Com tokens de renovação, uma sessão encerrada continua respondendo até o token de acesso expirar.
* **O site fica mais simples.** Não há renovação em segundo plano, disputa entre abas nem um segundo segredo para guardar. O site trata o `401` levando o aluno para o login, e só. Isso é o que permite um site estático, sem servidor.
* **A proteção é a mesma.** Um script malicioso na página roubaria o token de renovação junto com o de acesso. O que protege a sessão do aluno é não carregar scripts em que você não confia e nunca renderizar HTML digitado por usuários; veja [Segurança](https://ajuda.memberkit.com.br/headless/publique-em-seu-dominio.md#segurança).

O custo dessa escolha é que um token roubado vale até o aluno entrar em outro dispositivo, trocar a senha ou o prazo de duas semanas acabar. Para a área de membros, que guarda aulas e comentários, achamos a troca justa.

## Listas e paginação

Toda lista devolve o mesmo formato, com os itens em `data`:

```json theme={null}
{
  "data": [ ... ],
  "page": 1,
  "total_pages": 3
}
```

Nas listas paginadas, peça outras páginas com o parâmetro `page`, a partir de 1, até chegar a `total_pages`. O parâmetro `limit` define quantos itens vêm por página, de 1 a 100; sem ele, vêm 20 itens. As listas que não são paginadas vêm inteiras, com `page` e `total_pages` iguais a 1. Algumas listas trazem campos extras ao lado de `data`, como os totais por tipo em `counts` na busca.

## Limites de requisições

* Cerca de **120 requisições por minuto** por endereço IP.
* O login e a recuperação de senha têm limites bem menores, por endereço IP e por e-mail.
* O Assistente de IA aceita **10 mensagens por minuto** por aluno.
* As mensagens de contato são **5 por hora** por aluno.

Acima do limite, a API responde `429` com o código `rate_limited`. Espere um pouco antes de tentar de novo.

## Envios repetidos

Qualquer chamada que grava algo aceita o cabeçalho `Idempotency-Key`, com um valor único por envio, como um UUID. Se a mesma chave chegar de novo com o mesmo corpo em até 24 horas, a API devolve a primeira resposta, com o cabeçalho `Idempotent-Replayed`, em vez de gravar de novo. Use-o em formulários que criam algo, como comentários, publicações e mensagens de contato.

Só as respostas de sucesso são guardadas: depois de um erro, a mesma chave pode ser usada de novo com o corpo corrigido.

* A mesma chave com um corpo diferente responde `idempotency_key_reused`.
* Uma repetição que chega enquanto a primeira ainda está em andamento responde `request_in_progress`.

## Respostas

As chamadas que gravam algo devolvem o que criaram ou mudaram, para o site atualizar a tela pela resposta em vez de buscar tudo de novo. As ações cujo resultado o site já sabe, como seguir uma publicação, marcar a melhor resposta, marcar uma notificação como lida ou aceitar o onboarding, respondem `204`, sem corpo.

O conteúdo das aulas, o texto do onboarding, as publicações da comunidade e os textos dos quizzes chegam como HTML já renderizado. Os comentários chegam como texto simples. As respostas do Assistente de IA chegam em Markdown, transmitidas como *server-sent events*, e apontam para aulas com links `memberkit://courses/{curso}/lessons/{aula}`, que o site converte para os seus próprios endereços.

Arquivos das aulas e certificados trazem um `download_url` assinado para o aluno, válido por uma hora. É um link comum: o navegador baixa o arquivo sem precisar do token.

## Erros

Todo erro chega no mesmo formato:

```json theme={null}
{
  "code": "session_replaced",
  "message": "Suas credenciais de login foram usadas em outro navegador. Por favor, entre novamente para continuar neste navegador.",
  "request_id": "6f1c2a7e-0b1d-4c55-9a52-3f0d8e2b7c11"
}
```

Decida o que fazer pelo `code` e mostre a `message`, que já vem no idioma da área de membros. Informe o `request_id` ao suporte quando precisar de ajuda com uma chamada.

Erros de validação, com o código `validation_failed`, trazem também `errors`, com os problemas de cada campo. Cada um tem um `code`, como `blank`, `taken` ou `too_short`, para o seu site reagir ou traduzir, e uma `message` pronta para exibir:

```json theme={null}
{
  "code": "validation_failed",
  "message": "Nome não pode ficar em branco",
  "errors": {
    "full_name": [{ "code": "blank", "message": "não pode ficar em branco" }]
  },
  "request_id": "6f1c2a7e-0b1d-4c55-9a52-3f0d8e2b7c11"
}
```

### Erros que valem para a sessão inteira

Estes códigos podem aparecer em qualquer chamada e normalmente levam o aluno para outra tela:

| Código | Status | O que fazer |
| :- | :-: | :- |
| `invalid_headless_key` | 401 | Falta a chave headless, ela não existe ou foi trocada. Confira a chave no painel; levar o aluno para o login não resolve. |
| `unauthenticated` | 401 | Falta o token. Leve o aluno para o login. |
| `invalid_token` | 401 | O token é inválido ou expirou. Apague-o e leve para o login. |
| `session_replaced` | 401 | O aluno entrou em outro dispositivo. Apague o token e leve para o login. |
| `session_revoked` | 401 | O aluno saiu daquele dispositivo. Apague o token e leve para o login. |
| `subscription_suspended` | 402 | A assinatura da área de membros na MemberKit está suspensa. Mostre uma tela de manutenção. |
| `onboarding_required` | 403 | O aluno precisa aceitar o onboarding da área de membros. |

### Erros de uma tela ou ação

| Código | Status | Significado |
| :- | :-: | :- |
| `invalid_credentials` | 401 | E-mail ou senha incorretos. |
| `account_locked` | 403 | O aluno foi bloqueado no painel da área de membros. |
| `course_onboarding_required` | 403 | O aluno precisa aceitar o onboarding do curso. |
| `access_expired` | 403 | O acesso do aluno ao curso expirou. |
| `content_locked` | 403 | A aula ainda não foi liberada para o aluno. |
| `quiz_required` | 403 | A aula tem um quiz obrigatório em que o aluno ainda não foi aprovado. |
| `assistant_unavailable` | 403 | O Assistente de IA não está ativado na área de membros. |
| `forbidden` | 403 | O aluno não pode fazer essa ação. |
| `not_found` | 404 | O recurso não existe ou não pertence à área de membros. |
| `malformed_request` | 400 | O corpo da requisição não é um JSON válido. |
| `missing_parameter` | 422 | Falta um parâmetro obrigatório. |
| `validation_failed` | 422 | Um ou mais campos são inválidos; veja `errors`. |
| `unprocessable_certificate` | 422 | O certificado não pode ser gerado. |
| `idempotency_key_reused` | 422 | A mesma `Idempotency-Key` chegou com um corpo diferente. |
| `request_in_progress` | 409 | A requisição com essa `Idempotency-Key` ainda está em andamento. |
| `rate_limited` | 429 | Requisições demais em pouco tempo. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.