API pública
O helpdesk expõe uma única API pública: um endpoint GraphQL. Toda operação do schema é alcançável fora do navegador com um token de acesso pessoal (Personal Access Token, PAT).
Esta página é o contrato — o que é estável, como se autenticar, o que os escopos concedem e qual é o formato dos erros. A CLI hdmx é construída sobre ela, e o versionamento da API descreve como essa superfície evolui.
O endpoint
POST https://<your-host>/backend/<subdomain>/api/<version>/graphql
<subdomain>identifica sua conta (o mesmo identificador que você usa para entrar).<version>é uma versão datada da API, como2026-07— veja versionamento da API. Você também pode omitir o segmento de versão e chamar…/backend/<subdomain>/graphql; a requisição é então atendida pela versão mais antiga suportada, e cada resposta informa qual versão respondeu.
Autenticação
Envie um token de acesso pessoal como credencial Bearer:
Authorization: Bearer hdmx_<random>
Um PAT é de longa duração (com expiração obrigatória), tem escopos, é restrito por IP e revogável. Ele está vinculado a uma conta: apresentar um token ao subdomínio de outra conta é rejeitado com HTTP 401.
Criar um token
Crie e gerencie os tokens você mesmo no app do agente, em Settings → API tokens:
- Clique em New token.
- Dê a ele um nome que você reconheça depois.
- Escolha uma expiração (até 365 dias — não existe "nunca").
- Defina uma política de acesso — ative exatamente os recursos de que este token precisa, em leitura ou em leitura e escrita. Por padrão não há acesso a nada.
- Adicione pelo menos um endereço IP ou CIDR à lista de permitidos (obrigatório — veja Lista de IPs permitidos). O formulário pode adicionar seu IP atual para você.
- Revise e crie. O token completo é mostrado exatamente uma vez — copie-o imediatamente. Apenas um hash é armazenado, então ele nunca pode ser exibido de novo; se você o perder, faça a rotação do token para obter um novo.
Depois você pode editar a política de acesso e a lista de permitidos de um token, fazer sua rotação (emitir um novo segredo enquanto o antigo continua funcionando por um curto período de carência, para você migrar sem indisponibilidade) e revogá-lo. Cada token mostra quando e de onde foi usado pela última vez, além de um registro de atividade recente.
Escopos
O acesso é de granularidade grossa e organizado por famílias de recursos. Um token carrega um conjunto fixo de escopos; toda operação de nível superior verifica um deles.
| Escopo | Concede |
|---|---|
tickets:read | Ler tickets, mensagens, rascunhos, histórico, anexos, relatórios |
tickets:write | Criar / atualizar / excluir tickets, publicar mensagens, enviar anexos. Implica tickets:read |
chat:read | Ler chats, conversas, mensagens, sessões |
chat:write | Enviar mensagens do agente, entrar / sair / fechar / reabrir conversas. Implica chat:read |
customers:read | Ler registros de clientes |
customers:write | Criar / atualizar / mesclar registros de clientes. Implica customers:read |
settings:read | Ler configurações da conta (departamentos, status, prioridades, caixas de correio — sem segredos) |
Os campos de credenciais das caixas de correio (usuários, senhas e hosts de IMAP/SMTP) nunca são devolvidos a um token, independentemente do escopo — esses segredos pertencem ao seu provedor de e-mail e permanecem fora do alcance da API pública.
Taxonomia de erros
As respostas GraphQL usam errors[].extensions.code:
| Código | Significado | HTTP |
|---|---|---|
SCOPE_DENIED | O token não tem o escopo exigido. extensions.valid_values lista os escopos que satisfariam a operação | 200 |
RATE_LIMITED | O orçamento de requisições por token se esgotou. extensions.retryAfter são os segundos até a reinicialização, e o cabeçalho Retry-After traz o mesmo número | 429 |
INVALID_API_TOKEN | Token não encontrado, malformado ou inutilizável por outro motivo | 200 |
Tokens revogados, tokens expirados, incompatibilidades entre contas e recusas pela lista de IPs permitidos são rejeitados antes de a query rodar e aparecem como HTTP 401 sem corpo GraphQL. Trate um 401 em uma requisição com token como "este token não é mais válido para esta requisição — verifique sua expiração, seus escopos e sua lista de IPs permitidos".
Limites de taxa
Toda requisição com token carrega cabeçalhos:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 96
X-RateLimit-Reset: 1715692800
O orçamento padrão é de 120 requisições por minuto por token. Cada requisição custa 1, seja de leitura ou de escrita. Ultrapassar retorna HTTP 429 com um cabeçalho Retry-After e extensions.code = "RATE_LIMITED"; um cliente bem-comportado espera até o instante de reinicialização.
Lista de IPs permitidos
Todo token criado por autoatendimento precisa carregar pelo menos um IP ou CIDR — não existem tokens de "qualquer IP". O IP de origem de cada requisição é comparado com a lista do token; uma divergência é rejeitada com HTTP 401 e extensions.sub_code = "ip_not_allowed".
- IPv4, IPv6 e faixas CIDR são todos aceitos. Use
/32(IPv4) ou/128(IPv6) para um único host. - As faixas são validadas e normalizadas ao serem salvas.
- A lista de permitidos pode ser editada após a criação — editá-la não altera o segredo.
Use um token a partir de uma saída estável: um runner de CI, uma tarefa agendada, um NAT de escritório fixo ou seus próprios servidores em uma faixa de IP conhecida. Um token vazado é inútil de qualquer lugar fora da sua lista de permitidos.
Atividade do token
Toda requisição autenticada feita por um token é registrada: o horário, o nome da operação, o IP de origem, o resultado (sucesso, erro, limite de taxa, escopo negado, revogado ou expirado) e a latência de ida e volta. É esta a trilha a consultar se um token se comportar de forma inesperada.
Versionamento e descontinuação
A API é versionada com versões datadas YYYY-MM. Fixe uma na URL e ela se mantém estável por no mínimo 12 meses; as descontinuações são anunciadas no próprio canal antes que algo que você usa desapareça. Veja Versionamento da API para a política completa.
Descoberta do schema
O schema é autodescritivo: use a introspecção GraphQL padrão no endpoint versionado para gerar tipos e explorar a superfície. O GraphQL Playground interativo está disponível em …/backend/<subdomain>/playground.
Início rápido com curl
Estes exemplos assumem o host helpdesk.example.com, o subdomínio acme, a versão 2026-07 e um token em $TOKEN.
Ler o usuário atual (qualquer escopo)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ currentUser { id email firstname lastname } }"}'
Listar tickets recentes (tickets:read)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query ($first: Int!) {
ticketList(first: $first) {
edges { node { code subject status { name } updatedAt } }
}
}",
"variables": { "first": 10 }
}'
Publicar uma resposta pública (tickets:write)
curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation ($input: SaveTicketInput!) {
saveTicket(input: $input) {
ticket { code }
error { code message }
}
}",
"variables": {
"input": {
"id": "TICKET-UUID-HERE",
"message": "Thanks — fixing this now.",
"messageType": "PUBLIC"
}
}
}'
Para o dia a dia, a CLI hdmx envolve toda essa superfície atrás de comandos ergonômicos.