Visão geral da API
Todo endpoint REST do RolChat segue um único contrato: a mesma URL base, o mesmo envelope de resposta, a mesma paginação, o mesmo formato de erro. Aprenda uma vez, e todas as famílias de endpoints da referência de endpoints funcionam da mesma forma.
URL base e versionamento
Seção intitulada “URL base e versionamento”https://api.rolchat.com/api/v1/A versão fica no caminho. Adicionar campos opcionais, novos endpoints ou novos parâmetros de consulta com valores padrão não é uma mudança incompatível e não altera a versão. Mudanças incompatíveis são lançadas como v2, e os endpoints v1 descontinuados continuam funcionando por pelo menos seis meses após o anúncio (veja Descontinuação).
Autenticação
Seção intitulada “Autenticação”| Método | Cabeçalho | Usado para |
|---|---|---|
| JWT bearer | Authorization: Bearer <access_token> |
Sessões interativas (o app web, os apps móveis) |
| Chave de API | Authorization: Bearer rcp_<secret> |
Chamadas entre máquinas, chaves de API de plugins |
| Assinatura HMAC | X-RolChat-Signature: sha256=… |
Webhooks de entrada vindos dos seus sistemas, veja Webhooks |
| Nenhuma | - | Endpoints públicos do widget (/widget/…, /forms/…), restritos por site e origem |
Para integrações, use uma chave de API (um token de acesso pessoal). As chaves são criadas em Configurações → Plugins → Chaves de API do RolChat, exibidas uma única vez e armazenadas apenas como hash. Uma chave nunca pode fazer mais do que o membro que a criou: seus escopos são verificados em relação às permissões atuais desse membro a cada chamada. Veja Autenticação para a validade dos JWT, o cabeçalho X-Account-Id e sessões com várias empresas.
Envelope de resposta
Seção intitulada “Envelope de resposta”Um único recurso:
{ "data": { "id": "cnt_01HK…", "email": "ada@example.com" }, "meta": { "request_id": "req_01HK…" }}Uma lista:
{ "data": [ { … }, { … } ], "meta": { "request_id": "req_01HK…", "count": 50, "next_cursor": "cur_01HK…", "prev_cursor": "cur_01HK…", "has_more": true }}Respostas sem corpo (204 No Content após uma exclusão) ainda trazem o cabeçalho X-Request-Id.
Um erro:
{ "errors": [ { "code": "validation_failed", "message": "Email must be valid.", "field": "email", "details": { "received": "not-an-email" } } ], "meta": { "request_id": "req_01HK…" }}code é legível por máquina, em snake_case, e é o valor a usar nas ramificações do seu código; message fica em inglês e se destina aos logs. field e details aparecem quando ajudam e nunca contêm dados pessoais. A API nunca responde 200 com um array errors: se há erros, o status é 400 ou superior. A lista completa de códigos está na página Erros.
Paginação
Seção intitulada “Paginação”Os endpoints de listagem que podem crescer usam paginação por cursor. Peça a primeira página sem cursor e depois devolva o next_cursor recebido, exatamente como veio:
GET /api/v1/contacts?limit=50GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…limittem padrão 50 e máximo 200; valores maiores são rejeitados com400 validation_failed.- Os cursores são opacos e expiram após 24 horas (
400 validation_failedcomcode: cursor_expired). - Os resultados são consistentes com o instantâneo feito na primeira página: registros excluídos entre as páginas desaparecem, e novos registros só aparecem quando você recomeça sem cursor.
- Um cabeçalho
Linkcomrel="next"erel="prev"também é enviado para os clientes que preferem usá-lo.
Idempotência
Seção intitulada “Idempotência”Envie um cabeçalho Idempotency-Key (um UUID ou ULID, de até 255 caracteres) com qualquer POST, PATCH ou DELETE:
- A primeira requisição com uma chave é executada, e seu status e corpo são armazenados por 24 horas.
- Uma repetição com a mesma chave e o mesmo corpo retorna a resposta armazenada sem executar os efeitos colaterais de novo.
- Uma repetição com a mesma chave, mas com um corpo diferente, é rejeitada com
409 idempotency_key_conflict.
Use-o em toda chamada que cria algo com efeitos colaterais: enviar uma mensagem, um e-mail ou um SMS, fazer uma chamada, qualquer coisa que gere cobrança. As requisições GET são sempre idempotentes e ignoram o cabeçalho.
Limites de requisições
Seção intitulada “Limites de requisições”Os limites são contados por minuto e vinculados à conta, à chave de API ou ao usuário (ao endereço IP nas rotas que não exigem login). Os tetos padrão:
| Balde | Limite padrão | Por minuto |
|---|---|---|
| Requisições sem login (por IP) | 60 | por IP |
| Usuário logado (painel) | 1 000 | por usuário |
| Chave de API | 1 000 | por chave |
| Endpoints públicos do widget | 60 por visitante e 600 por endereço de rede | por minuto |
Login (/auth/login) |
5 | por IP |
| Webhooks de entrada | 300 | por minuto |
| Servidor MCP | 600 | por minuto |
| Endpoints OAuth | 600 | por minuto |
Os tetos são os padrões da plataforma e podem ser alterados pelo operador; seu plano não os multiplica, e os limites Enterprise são acordados em contrato. Os endpoints com limite retornam:
X-RateLimit-Limit: 1000X-RateLimit-Remaining: 543Quando você ultrapassa um limite, a resposta é 429 com code: rate_limited no array errors e um cabeçalho Retry-After em segundos. Aguarde esse tempo antes da próxima chamada. Dez logins malsucedidos bloqueiam a conta por 30 minutos.
Tamanhos e tempos limite
Seção intitulada “Tamanhos e tempos limite”| Categoria | Corpo máximo da requisição | Tempo limite do servidor |
|---|---|---|
| Padrão | 1 MB | 30 s |
| Mensagem com anexos | 25 MB | 30 s |
| Importação CSV | 50 MB | retorna 202 e é executada em segundo plano |
| Imagens da base de conhecimento | 10 MB | 30 s |
| API de operações em massa | 10 MB | 30 s |
| Busca | 1 MB | 10 s |
| Requisições de IA | 1 MB | 60 s |
| Endpoints do widget | 100 KB | 30 s |
Corpos grandes demais recebem 413 payload_too_large. Um serviço de origem que excede o tempo responde 504 com code: upstream_timeout e uma indicação retry_after quando uma nova tentativa pode ajudar.
Tipos de conteúdo, datas e IDs
Seção intitulada “Tipos de conteúdo, datas e IDs”- Requisições e respostas usam
application/json; charset=utf-8. Envios de arquivos usammultipart/form-data; exportações CSV retornamtext/csv. UTF-8 inválido é rejeitado com400 validation_failed. - Os registros de data e hora seguem a ISO-8601 em UTC com precisão de milissegundos:
2026-04-20T14:23:45.123Z. Qualquer deslocamento ISO-8601 é aceito na entrada e normalizado para UTC. - Os identificadores são ULIDs ou UUIDs opacos. Não há IDs numéricos, e endereços de e-mail ou números de telefone nunca aparecem em uma URL.
Isolamento de contas e permissões
Seção intitulada “Isolamento de contas e permissões”Toda requisição autenticada é executada dentro de uma conta. Um recurso que pertence a outra conta, ou a um site que a função de quem chama não cobre, responde 404 not_found em vez de 403, para que a existência de registros nunca seja revelada. Um token válido sem a permissão necessária (por exemplo, contacts.delete) responde 403 forbidden. Algumas permissões têm um sufixo de escopo (conversations.read:own, :team, :all) que restringe o que uma lista retorna.
PATCH aceita apenas campos graváveis. id, account_id, created_at, updated_at e campos de estado como resolved_at são somente leitura; enviar um deles retorna 400 validation_failed com details.forbidden_fields. As mudanças de estado passam por ações dedicadas, como POST /tickets/:id/resolve.
Toda gravação é registrada no log de auditoria da conta.
Cabeçalhos de observabilidade
Seção intitulada “Cabeçalhos de observabilidade”Toda resposta traz:
X-Request-Id: req_01HK…Registre o X-Request-Id nos seus logs. É a primeira coisa que o suporte pede.
A origem do painel no navegador é https://app.rolchat.com. Os endpoints públicos do widget permitem qualquer origem, ou apenas as origens que você verificar para um site. Chamadas entre servidores com uma chave de API não estão sujeitas a CORS.
Descontinuação
Seção intitulada “Descontinuação”- A mudança é anunciada no registro de alterações, e o endpoint afetado passa a enviar
Deprecation: truee um cabeçalhoSunsetcom a data de remoção. - Os endpoints públicos continuam funcionando por pelo menos seis meses após o anúncio.
- A remoção só acontece em uma nova versão principal. Dentro da
v1, as mudanças são apenas aditivas.
Todo serviço expõe /healthz (liveness) e /readyz (readiness).