Portal do desenvolvedor · API Gototem Partner
v1 llms.txt

API Gototem Partner — guia do desenvolvedor

Guia para o desenvolvedor do sistema parceiro: como abrir chamados no help desk da Gototem a partir do seu sistema.

Nesta página

Visão geral

A API permite que o seu sistema (por exemplo, um atendimento por chat) abra chamados no help desk da Gototem em nome do cliente atendido. O seu sistema escolhe a categoria, a prioridade, o nível de suporte e a natureza a partir de uma lista que a própria API fornece, e recebe de volta o número do chamado e o que foi gravado nele.

Endereço base de produção: https://api.gototem.com.br. Em homologação, o suporte informa o endereço junto com a chave.

Só existe a versão 1, sempre com /v1/ no caminho, e sem barra no fim (help-desk-ticket-options/ não é rota e recebe 404).

As respostas são JSON em UTF-8, e as recusas da própria API vêm em application/problem+json, com type, title, status, detail e code. Algumas recusas vêm do servidor, antes da API e sem code (um 404 e um 400 do webhook), e um caminho fora da API recebe uma página HTML: por isso, confira o status antes de ler o corpo como JSON, como fazem os exemplos deste guia (ver Erros).

As rotas, uma a uma, com o corpo, a resposta e os erros de cada uma, estão na referência da API, gerada do contrato.

Autenticação

A API não tem usuário e senha, e não usa conta nem licença: cada sistema parceiro tem uma chave, que identifica o sistema e diz o que ele pode fazer.

Como obter a chave

O suporte da Gototem cadastra o seu sistema e entrega uma chave no formato gtes_ seguido de 43 caracteres.

A chave não é mostrada de novo: guarde-a como diz Onde a chave deve ficar.

Junto com a chave, o suporte informa os escopos liberados (abaixo) e o identificador do seu sistema, usado no webhook. Nenhuma rota devolve esses dois dados: guarde-os com a chave.

Como enviar a chave

Envie a chave em toda chamada, no cabeçalho Authorization:

Cabeçalho
Authorization: Bearer gtes_SuaChaveAqui

A palavra Bearer vale em maiúsculas ou minúsculas. Envie a chave só por HTTPS.

Envie só o Authorization: um cabeçalho de autenticação de outro sistema da Gototem é recusado (ver Erros).

Sem a chave, ou com uma chave que não vale, a resposta é 401 unauthorized; com a chave válida e sem o escopo da rota, 403 forbidden_scope.

O que a chave libera

A chave também define o que o seu sistema pode fazer (abrir chamados, enviar leads). Chamada fora do que foi liberado recebe 403 forbidden_scope. Cada rota da referência diz, ao lado do endereço, o escopo que exige:

Escopos da chave
Escopo O que libera
help-desk-ticket.create Consultar as opções (help-desk-ticket-options), abrir chamado (help-desk-ticket) e abrir chamado por webhook.
lead.create Enviar lead (lead). Ainda não disponível: ver Enviar um lead.

A primeira chamada

Os exemplos leem a chave de uma variável de ambiente, GOTOTEM_INTEGRATION_KEY. No seu servidor, ela vem do cofre de segredos; para testar, defina-a no terminal em que você vai rodar os exemplos:

Variável (bash: Linux, macOS, Git Bash)
export GOTOTEM_INTEGRATION_KEY="<a chave que o suporte entregou>"
Variável (PowerShell, no Windows)
$env:GOTOTEM_INTEGRATION_KEY = "<a chave que o suporte entregou>"

Os exemplos vêm em cinco linguagens: bash (o terminal do Linux, do macOS ou o Git Bash, com o comando curl), PowerShell (o Windows PowerShell 5.1 ou o PowerShell 7), Python (com a biblioteca requests), JavaScript (o fetch do Node 18 ou mais novo, num arquivo .mjs) e PHP (com a extensão curl). Escolha a sua numa aba: a escolha vale para todos os exemplos da página e fica guardada neste navegador. Os exemplos em Python, JavaScript e PHP leem a mesma variável de ambiente. Os ids dos exemplos são ilustrativos e variam por ambiente: use os que a sua consulta devolver.

A primeira chamada consulta as opções que o seu sistema pode usar ao abrir um chamado. É a chamada mais simples da API: não tem corpo e não cria nada.

GET/v1/api-external-system/help-desk-ticket-optionsEscopo help-desk-ticket.create
curl
curl -s https://api.gototem.com.br/v1/api-external-system/help-desk-ticket-options \
  -H "Authorization: Bearer $GOTOTEM_INTEGRATION_KEY"
PowerShell
try {
    $response = Invoke-WebRequest -UseBasicParsing `
        -Uri 'https://api.gototem.com.br/v1/api-external-system/help-desk-ticket-options' `
        -Headers @{ Authorization = "Bearer $env:GOTOTEM_INTEGRATION_KEY" }
    # o corpo é UTF-8: lido assim, o acento sai certo também no Windows PowerShell 5.1
    [Text.Encoding]::UTF8.GetString($response.RawContentStream.ToArray()) | ConvertFrom-Json
} catch {
    $refusal = $_.Exception.Response
    if ($null -eq $refusal) { throw }
    "HTTP $([int]$refusal.StatusCode) (X-Request-Id $($refusal.Headers.GetValues('X-Request-Id')))"
}
Python (requests)
import os

import requests

resp = requests.get(
    "https://api.gototem.com.br/v1/api-external-system/help-desk-ticket-options",
    headers={"Authorization": "Bearer " + os.environ["GOTOTEM_INTEGRATION_KEY"]},
    timeout=30,
)
if resp.status_code == 200:
    print(resp.json())
else:
    print("HTTP", resp.status_code, resp.headers.get("X-Request-Id"), resp.text)
JavaScript (Node 18+, arquivo .mjs)
const response = await fetch('https://api.gototem.com.br/v1/api-external-system/help-desk-ticket-options', {
  headers: { Authorization: 'Bearer ' + process.env.GOTOTEM_INTEGRATION_KEY },
});
if (response.status === 200) {
  console.log(await response.json());
} else {
  console.log('HTTP ' + response.status, response.headers.get('X-Request-Id'), await response.text());
}
PHP (curl)
<?php
$curl = curl_init('https://api.gototem.com.br/v1/api-external-system/help-desk-ticket-options');
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('GOTOTEM_INTEGRATION_KEY')],
    CURLOPT_TIMEOUT => 30,
]);
$raw = curl_exec($curl);
if ($raw === false) {
    throw new RuntimeException('Rede: ' . curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
echo 'HTTP ', $status, PHP_EOL;
print_r($status === 200 ? json_decode($raw, true) : $raw . PHP_EOL);

No Windows PowerShell 5.1, se a chamada falhar com erro de conexão segura, rode antes [Net.ServicePointManager]::SecurityProtocol = 'Tls12'; e, se salvar o exemplo num arquivo .ps1, salve-o em UTF-8 com BOM, senão o acento do corpo do chamado chega trocado. No Git Bash do Windows, o acento escrito dentro do -d do curl sai na codificação do Windows e o corpo é recusado (422 invalid_body): grave o corpo num arquivo em UTF-8 e envie com --data-binary @corpo.json.

Veio 200? A chave funciona. A resposta traz as categorias liberadas para o seu sistema e as empresas, prioridades, níveis e naturezas ativas; o exemplo completo e o significado de cada campo estão na referência da rota. 401 quer dizer que a chave não foi aceita; 403, que o sistema está desativado ou sem o escopo (ver Erros).

O próximo passo é abrir o primeiro chamado: veja Abrir um chamado.

Contrato e ferramentas

Três arquivos acompanham este guia, publicados ao lado dele: o contrato OpenAPI, a coleção pronta para o Postman e o Insomnia e um resumo para agentes de IA. Nenhum deles precisa de chave.

Contrato OpenAPI

O contrato completo, com todos os campos e respostas, está em openapi.yaml e, em JSON, em openapi.json. Use-o para gerar um cliente ou validar chamadas.

Se você gerar cliente a partir dele, não transforme o code de erro ou de aviso em enumeração fechada: no contrato ele é texto, com os valores conhecidos listados em x-extensible-enum, e um código novo pode surgir a qualquer momento (ver Versões e compatibilidade). Não gere cliente para a rota de lead, que ainda não está disponível.

Coleção do Postman e do Insomnia

Para chamar a API sem escrever código, use a coleção. Ela é gerada do contrato e traz uma requisição para cada rota que já está no ar, com o corpo de exemplo.

  1. Baixe o arquivo postman.json.
  2. Postman: clique em Import e escolha o arquivo. Insomnia: use Import e escolha o mesmo arquivo (o Insomnia lê coleções do Postman).
  3. Abra as variáveis da coleção e preencha api_key com a chave que o suporte entregou. base_url já vem com o endereço de produção; em homologação, troque pelo endereço que o suporte informou. Na requisição do webhook, preencha a variável de caminho system com o identificador do seu sistema.
  4. Envie O que o seu sistema pode escolher ao abrir um chamado primeiro: os ids do corpo de exemplo de Abre um chamado no help desk são ilustrativos e têm de ser trocados pelos que essa consulta devolver.

A coleção chama a API de verdade: um chamado enviado por ela é aberto no help desk da Gototem.

llms.txt

O arquivo llms.txt é um resumo desta API em texto puro, para agentes de IA: o endereço base, de onde vem a chave, as rotas no ar e os links para o contrato e para este guia. Aponte o seu agente para ele antes de pedir que escreva a integração.

Segurança

Trate a chave como uma senha: quem a tem abre chamados no help desk da Gototem em nome do seu sistema.

Onde a chave deve ficar

Guarde a chave num cofre de segredos do seu servidor e entregue-a ao processo por variável de ambiente, como fazem os exemplos deste guia (GOTOTEM_INTEGRATION_KEY). Ela nunca vai no código-fonte, num repositório, no navegador nem num aplicativo distribuído. A chave é mostrada uma única vez, na entrega: se ela se perder, peça uma chave nova ao suporte.

Rotação da chave

Quando o suporte gera uma chave nova, a anterior continua valendo por 24 horas (o padrão; se o suporte combinou outro prazo, vale o combinado): atualize os servidores um a um dentro desse prazo. Passado o prazo, o servidor que ainda usar a anterior recebe 401; troque a chave dele e não repita a chamada em laço (ver Os casos do 429).

Se a chave vazou, peça ao suporte que pare a anterior na hora: aí ela deixa de valer no mesmo instante.

Quem troca a chave é o suporte da Gototem: o seu sistema não a rotaciona nem a revoga por rota nenhuma.

Como saber o estado da chave

Não se aplica a esta API: nenhuma rota informa o estado ou a validade da chave. Chave que deixou de valer responde 401 unauthorized, e sistema desativado responde 403 system_inactive (ver Erros).

Para conferir a chave e o escopo sem abrir chamado, chame GET help-desk-ticket-options: 200 confirma os dois.

Glossário

Termos deste guia
Termo O que é
Sistema O cadastro do seu sistema na Gototem, feito pelo suporte. A chave pertence a ele.
Identificador do sistema O nome curto do seu cadastro (letras minúsculas, números, - e _), informado pelo suporte junto com a chave. Vai no endereço do webhook.
Chave O segredo que autentica o seu sistema, no formato gtes_ seguido de 43 caracteres.
Escopo O que a chave pode fazer: help-desk-ticket.create ou lead.create (ver O que a chave libera).
Chamado O registro aberto no help desk da Gototem a partir do seu atendimento.
external_id O id do atendimento no seu sistema. É por ele que um reenvio é reconhecido (ver Reenvio e idempotência).
Tipo O grupo da categoria: Incidente, Problema, Solicitação de Serviço ou Solicitação de Mudança. Não vai no chamado: escolher a categoria já define o tipo.
Categoria O assunto do chamado, dentro de um tipo. O seu sistema usa a categoria padrão e as que o suporte liberou.
Empresa, prioridade, nível de suporte e natureza As outras escolhas do chamado, sempre a partir das listas de Consultar as opções.
Rotas JSON As rotas que exigem o corpo em JSON: help-desk-ticket e lead (ver Formatos e convenções).
Webhook O endereço para abrir chamado a partir de uma ferramenta de webhook (ver Abrir um chamado com webhook).
applied O bloco da resposta com o que foi gravado no chamado (ver Ler a resposta).
warnings Os avisos da resposta: escolha trocada pelo padrão, CNPJ ignorado, campos fora do contrato, solicitante cortado ou reenvio com outra descrição (ver Avisos).

Formatos e convenções

As respostas são JSON em UTF-8.

Neste guia, rotas JSON são as que exigem o corpo em JSON: help-desk-ticket e lead. Nelas, envie Content-Type: application/json (; charset=utf-8 também vale, e também um tipo com o sufixo +json, como application/vnd.exemplo+json), com o tipo em minúsculas; sem ele, com outro ou em maiúsculas (Application/JSON), a resposta é 415 unsupported_media_type. O webhook aceita qualquer Content-Type.

Num campo opcional do corpo, null é o mesmo que não enviar o campo. Num campo obrigatório, null vale como ausente.

Datas e fuso

Não se aplica a esta API: nenhuma rota recebe nem devolve data.

Dinheiro

Não se aplica a esta API: nenhuma rota recebe nem devolve valor em dinheiro.

Identificadores

Os ids de categoria, de prioridade e de nível de suporte são números inteiros; o id de empresa e o identifier da natureza são texto.

  • Envie os ids como número inteiro: "category": 3, nunca "category": "3". Um id enviado como texto ("3") ou com fração (3.5) não é reconhecido: o chamado é aberto com a opção padrão e a resposta traz um aviso de troca. O inteiro com casa decimal zero (3.0, que algumas bibliotecas produzem ao serializar número) vale como o inteiro.
  • Os ids mudam entre homologação e produção e podem mudar com o tempo: leia-os de help-desk-ticket-options e nunca os fixe no código.
  • O ticket e o id da resposta são opacos: guarde-os e mostre-os como vieram, sem deduzir nada da forma deles.

Paginação

Não se aplica a esta API: nenhuma rota devolve lista paginada.

Limites de uso

Limites da API
O que Limite
Chamadas por minuto, por sistema 120 (o suporte pode combinar outro)
Corpo da chamada 65.536 bytes em UTF-8
external_id 120 caracteres
description 20.000 caracteres
requester.name e requester.contact 120 e 160 caracteres (o excedente é cortado, com o aviso requester_truncated)
Chamadas repetidas com chave errada, do mesmo IP bloqueiam o IP por até um minuto

Acima do limite, external_id e description recebem 422 field_too_long, sem corte. Só esses dois campos são recusados por tamanho: o requester é cortado, e a resposta traz o aviso requester_truncated. O corpo acima do teto recebe 413 payload_too_large; o teto é em bytes, e não em caracteres (ver Montar e enviar o corpo).

Toda resposta depois da conferência do limite (o chamado criado, o reenvio, as opções, e também o 403 forbidden_scope, os 422 dos campos e o próprio 429) traz o saldo em três cabeçalhos:

Cabeçalhos da resposta
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1791481927
  • X-RateLimit-Limit é o limite por janela, e X-RateLimit-Remaining, quantas chamadas ainda cabem.
  • X-RateLimit-Reset é o instante, em segundos Unix, em que a chamada mais antiga da janela deixa de contar e o saldo sobe; com saldo 0, é quando a próxima chamada passa.
  • Sem os três cabeçalhos, o limite não está sendo medido naquela chamada: trate a ausência como "sem informação", nunca como limite zero.

Use-os para espaçar as chamadas antes de chegar ao 429.

O limite e o saldo são do sistema, não de cada servidor nem de cada chave: todos os seus servidores, e também a chave anterior durante uma troca, gastam o mesmo saldo. Por isso ele pode cair mais do que as chamadas de um servidor explicam.

Os casos do 429

Ao passar de um limite, a resposta é 429 rate_limited, com o cabeçalho Retry-After em segundos. São dois casos:

Os casos do 429
Quem recusou Retry-After X-RateLimit-*
A cota do seu sistema: 120 chamadas por minuto, ou o combinado com o suporte a espera real até a próxima chamada passar vêm, com X-RateLimit-Remaining: 0
O IP bloqueado por chamadas repetidas com chave errada a espera real, até um minuto não vêm: o seu sistema ainda não foi identificado

O Retry-After é a espera real, e não a janela inteira; só quando o servidor não consegue medir a espera ele manda a janela inteira. Espere esse tempo antes de tentar de novo, com o mesmo external_id; não reenvie em laço. No código, basta esperar o Retry-After: a diferença entre os casos serve para investigar.

O IP bloqueado. Chamadas repetidas com chave errada, vindas do mesmo IP, bloqueiam esse IP por até um minuto, mesmo com a chave certa. Pare de repetir, confira a chave e espere o Retry-After.

A chave anterior do seu sistema, depois do prazo da troca, recebe 401 mas não conta para o bloqueio do IP: numa troca, você pode atualizar os servidores um a um (ver Rotação da chave).

Erros

Toda recusa desta API traz code e tem o mesmo formato, em application/problem+json:

  • type: sempre about:blank (o erro é identificado pelo code);
  • title: o nome do status HTTP, em inglês (Unprocessable Entity);
  • status: o status HTTP, como número;
  • detail: a explicação, em inglês;
  • code: o que o seu código usa.

Programe contra o code; o detail é para leitura humana, vem em inglês e pode mudar. O code é texto aberto: o que você não conhecer, trate pelo status HTTP, sem falhar (ver Contrato OpenAPI). As recusas que vêm do servidor, antes da API, chegam sem code: estão na tabela abaixo (linhas sem code) e em Os casos do 404.

Nos 422 de um campo do corpo vem também param, com o nome do campo (external_id, description, company, nature, requester.name ou requester.contact); no 403 forbidden_scope, vem required_scope, com o escopo que a rota exige e a chave não tem:

Resposta de erro
{
  "type": "about:blank",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "Unknown company. Use one of: gototem, melhoretec.",
  "code": "invalid_company",
  "param": "company"
}

Toda resposta das rotas desta API traz o cabeçalho X-Request-Id, inclusive as recusas. Ao falar com o suporte sobre uma chamada, informe esse valor: é por ele que a achamos no nosso registro (ver O que enviar ao pedir ajuda). O 404 que vem sem code, e o único que não traz o X-Request-Id, estão em Os casos do 404.

Códigos de erro
HTTP code Quando O que fazer
400 conflicting_credentials Veio um cabeçalho de autenticação de outro sistema da Gototem. O detail é informativo e pode mudar. Remova o cabeçalho e envie só o Authorization.
400 (application/problem+json, sem code) Só no webhook, com Content-Type JSON: o corpo não é objeto nem lista JSON (JSON quebrado, texto que não é UTF-8, ou um valor sozinho como "oi" ou 5). Quem recusa é o servidor, depois da chave. Corrija o corpo.
401 unauthorized Chave ausente, fora do formato ou que não vale; no webhook, também identificador desconhecido ou chave de outro sistema. Traz o cabeçalho WWW-Authenticate: Bearer. Confira o cabeçalho Authorization; se a chave foi trocada, use a nova. Não repita em laço (Os casos do 429).
403 system_inactive O seu sistema está desativado na Gototem. Fale com o suporte e guarde o chamado (Corrigir, reenviar ou falar com o suporte).
403 forbidden_scope O seu sistema não tem o escopo da rota (O que a chave libera). O campo required_scope diz o escopo que falta. Peça a liberação desse escopo ao suporte e guarde o chamado.
404 not_found O endereço está errado: o caminho começa com /v1/api-external-system/, mas não é rota desta API, ou é desta API em outra versão ou sem versão. O 404 tem outros casos, sem code. Corrija o endereço; veja Os casos do 404.
405 method_not_allowed Método HTTP diferente do da rota. Traz o cabeçalho Allow com o método aceito. Use o método do Allow (ver abaixo).
413 payload_too_large Corpo acima de 65.536 bytes, contados como enviado. Encurte a descrição, ou envie o JSON sem escapar o Unicode (Montar e enviar o corpo).
415 unsupported_media_type Numa rota JSON, corpo sem Content-Type: application/json (Formatos e convenções). Envie Content-Type: application/json.
422 invalid_body O corpo não é um objeto JSON: JSON quebrado, UTF-8 inválido, texto ("oi"), lista ou número. Envie um objeto JSON válido, em UTF-8.
422 invalid_field Um texto (external_id, description, requester.name ou requester.contact) tem o caractere NUL (\u0000). O param diz qual. Remova o caractere do campo.
422 missing_external_id Sem external_id. Envie o id do atendimento.
422 missing_description Sem description. Envie o relato.
422 missing_company Sem company (o detail lista as válidas). Envie um id de companies.
422 field_too_long external_id ou description acima do limite (Limites de uso). Encurte o campo.
422 invalid_company Empresa desconhecida ou inativa (o detail lista as válidas). Use um id de companies.
422 invalid_nature Natureza desconhecida ou inativa. Consulte as opções de novo e use um identifier de natures, ou remova o campo.
429 rate_limited Limite de chamadas atingido. Espere os segundos do Retry-After (Os casos do 429).
500 misconfigured_system O cadastro do seu sistema na Gototem está incompleto. Fale com o suporte e guarde o chamado.
500 internal_error Falha inesperada do nosso lado. Tente de novo em alguns minutos, com o mesmo external_id.
501 not_implemented Rota de lead, ainda não disponível. Não integre a rota (Enviar um lead).
503 temporarily_unavailable A API está desligada por um tempo, em qualquer rota. Traz o cabeçalho Retry-After, em segundos. Sai antes da chave e não conta no limite de chamadas. Guarde o chamado e reenvie depois do Retry-After, com o mesmo external_id; nunca o descarte. Se durar, fale com o suporte.

Método errado. Um método diferente do da rota (por exemplo, GET em help-desk-ticket) recebe 405 method_not_allowed, com o cabeçalho Allow dizendo o método aceito. HEAD numa rota GET também recebe 405: use GET. OPTIONS é diferente: ele exige a chave, conta no limite de chamadas e recebe 200 sem corpo, com o Allow.

Cabeçalho de outro sistema. Um cabeçalho de autenticação de outro sistema da Gototem é recusado com 400 conflicting_credentials ou com um 404 em application/problem+json, sem code. Nos dois casos, remova o cabeçalho e envie só o Authorization.

Os casos do 404

O 404 é sempre erro de endereço: corrija-o antes de reenviar. A API desligada não responde 404, e sim 503 temporarily_unavailable (ver Erros). O 404 tem três formas; separe-as pelo corpo:

Os casos do 404
HTTP Como vem O que quer dizer O que fazer
404 not_found Em application/problem+json, com o X-Request-Id. O caminho começa com /v1/api-external-system/, mas não é rota: erro de digitação, barra no fim (help-desk-ticket-options/) ou {system} fora do padrão no webhook. Ou o caminho é desta API em outra versão ou sem versão (/v2/api-external-system/..., /api-external-system/...). Confira o endereço contra a referência da API: só existe a versão 1, com /v1/. Reenviar igual não resolve.
404 (application/problem+json, sem code) Veio um cabeçalho de autenticação de outro sistema da Gototem. Quem recusa é o servidor, antes da API. Traz o X-Request-Id. Remova o cabeçalho e envie só o Authorization.
404 página HTML, sem X-Request-Id O caminho está fora desta API, como /v1/api-external-system sem a barra final ou /v1/outra-coisa: a chamada não chega a esta API. Corrija o endereço.

Corrigir, reenviar ou falar com o suporte

Cada recusa cai num destes três grupos:

  • Corrija antes de reenviar: 400, 401, todo 404 (é sempre erro de endereço, em qualquer das três formas), 405, 413, 415 e 422. Reenviar a mesma chamada não resolve.
  • Reenvie depois, com o mesmo external_id: 429 (depois dos segundos do Retry-After), 500 internal_error (em alguns minutos), 503 temporarily_unavailable (a API está desligada por um tempo: depois dos segundos do Retry-After) e falha de rede ou tempo esgotado.
  • Fale com o suporte e guarde o chamado para reenviar depois da correção, com o mesmo external_id: 403 system_inactive, 403 forbidden_scope e 500 misconfigured_system. O 501 not_implemented só vem da rota de lead, que ainda não deve ser integrada.

Em nenhum desses casos o chamado do seu cliente precisa ser descartado: guardado, ele entra com o mesmo external_id quando a causa for resolvida, sem duplicar (Reenvio e idempotência).

Ordem das conferências

A API responde um problema por chamada. Quando há mais de um, corrigir um pode revelar o seguinte: por exemplo, um 415 corrigido vira 401 se a chave também estiver errada.

Antes de tudo, inclusive da chave, sai o 503 temporarily_unavailable: com a API desligada, toda chamada o recebe, sem contar no limite. Saem também antes da conferência da chave, e não contam no limite de chamadas do seu sistema: o 400 conflicting_credentials, o 404, 405, 413, 415 e, nas rotas JSON, o 422 invalid_body. O 413 sai antes da chave em toda rota, inclusive no webhook. Os 422 dos campos saem por último (no webhook, o invalid_body e o 400 do corpo que não é objeto nem lista JSON também saem depois da chave).

Versões e compatibilidade

A v1 só muda de forma aditiva: campo novo na resposta, aviso novo em warnings e code de erro novo podem surgir a qualquer momento, então ignore o que não conhecer (o erro desconhecido, trate pelo status HTTP). Remover um campo ou mudar o tipo dele só numa v2, avisada antes. Para quem gera cliente a partir do contrato, veja Contrato OpenAPI.

As mudanças de forma até 2026-10-15 vieram antes da primeira integração, quando nenhum sistema tinha chave: foram o último ajuste de forma da v1.

Histórico de mudanças

  • 2026-10-15 — Quebra, feita antes da primeira integração: a API desligada passou a responder 503 temporarily_unavailable com Retry-After (antes, 404 sem corpo); o caminho de outra versão ou sem versão passou a receber o 404 not_found (antes, 404 sem corpo); toda recusa passou a vir em application/problem+json, com type, title, status, detail e code (o campo message do erro saiu; o texto está em detail); a frase do 400 conflicting_credentials passou a ser a do contrato. Acréscimos: required_scope no 403 forbidden_scope, o aviso requester_truncated (solicitante cortado) e o aviso description_differs (reenvio com outra descrição).
  • 2026-10-14 — Nome: a API passou a se chamar API Gototem Partner (antes, API de integração). Nenhuma rota, chave ou endereço mudou.
  • 2026-10-12 (9) — A documentação saiu da API e passou a ser publicada só no portal do desenvolvedor: os endereços /v1/api-external-system/docs e /v1/api-external-system/docs/openapi.yaml respondem 404. Nenhuma rota da API mudou.
  • 2026-10-12 (8) — Comportamento: depois de uma troca de chave, a anterior continua valendo por 24 horas (antes parava no ato), e a anterior vencida não conta mais para o bloqueio do IP (ver Rotação da chave).
  • 2026-10-12 (7) — Comportamento: o IP do bloqueio por chaves erradas passou a ser o do servidor que se conecta à API, nunca um header que o cliente escreva; em IPv6, conta o bloco /64 inteiro.
  • 2026-10-12 (6) — Forma: o 404 do caminho que começa com /v1/api-external-system/ mas não é rota ganhou o corpo {"code", "message"} (not_found; antes, a página HTML do servidor). O 404 sem corpo, o que manda guardar e reenviar, não mudou.
  • 2026-10-12 (5) — Forma: o 405 ganhou o corpo {"code", "message"} (method_not_allowed, com Allow) e passou a sair antes da chave, sem contar no limite.
  • 2026-10-12 (4) — Comportamento: caracteres invisíveis e de controle passaram a ser retirados de external_id e do requester (o NUL continua recusado).
  • 2026-10-12 (3) — Aditiva: o campo param nos 422 dos campos, com o nome do campo recusado.
  • 2026-10-12 (2) — Aditiva: o aviso ignored_fields em warnings para campo fora do contrato (o chamado é aberto do mesmo jeito).
  • 2026-10-12 (1) — Aditiva: os headers X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset em toda resposta depois da conferência do limite do sistema, e o Retry-After do 429 com a espera real (antes, a janela inteira).
  • 2026-10-11, todas aditivas: a resposta do chamado ganhou o bloco applied, com o que foi gravado; id com casa decimal zero (3.0) passou a valer como o inteiro; todo 401 traz WWW-Authenticate: Bearer; o code de erro e de aviso passou a ser texto aberto no contrato (antes, lista fechada).

Abrir um chamado

Abrir um chamado leva três passos: consultar o que o seu sistema pode escolher, montar o corpo com as escolhas e ler a resposta. Cada passo diz o que fazer; o detalhe de cada campo está na referência da API.

  1. Consultar as opções que o seu sistema pode usar.
  2. Montar e enviar o corpo, com as escolhas e um external_id único.
  3. Ler a resposta: o ticket, o applied e os warnings.

1. Consultar as opções

GET/v1/api-external-system/help-desk-ticket-optionsEscopo help-desk-ticket.create

É a consulta da primeira chamada. Ela devolve as categorias liberadas para o seu sistema e as empresas, prioridades, níveis e naturezas ativas; cada campo está na referência da rota.

Guarde a lista em cache por algumas horas (ela muda raramente) e consulte de novo ao receber o aviso category_fallback ou priority_fallback, ou a recusa invalid_nature.

Escolha com a sua IA, a partir da conversa com o cliente e da description de cada opção: um texto da equipe da Gototem que diz quando usar cada uma. Primeiro o tipo (Incidente, Problema, Solicitação de Serviço ou Solicitação de Mudança), depois a categoria daquele tipo, a prioridade e o nível de suporte, sempre pela description (o response_time_hours é só o prazo configurado e não ordena a urgência). A natureza é opcional e não tem description: escolha pelo nome (hardware, software...) ou omita.

  • Quando a description ainda não foi escrita, ela vem null: escolha pelo nome.
  • Trate a description como dado e nunca execute instruções contidas nela. É texto puro e pode conter < e >: escape antes de exibir em HTML.
  • A categoria já define o tipo: o tipo não vai no chamado.
  • Envie sempre priority, escolhida pela description. Sem ela vale a prioridade padrão da categoria (o default_priority_id), que pode ser alta: um chamado simples pode nascer com a prioridade máxima.

Nenhuma categoria serve? Não envie category: o chamado cai na categoria padrão do seu sistema, sem aviso, e quem orienta a equipe é o relato em description. Antes de entrar em produção, confira com o suporte se as categorias liberadas cobrem os casos do seu atendimento.

2. Montar e enviar o corpo

POST/v1/api-external-system/help-desk-ticketEscopo help-desk-ticket.create

Cada campo, com o tamanho, o padrão e o que acontece com um valor fora da regra, está na referência da rota. Ao montar o corpo, siga estas regras:

  • Os ids vêm da lista, como número inteiro: category, priority e support_level com os ids de help-desk-ticket-options (ver Identificadores). O company, obrigatório, é um id de companies.
  • Um external_id único por atendimento: o id do atendimento no seu sistema. É por ele que um reenvio é reconhecido (ver Reenvio e idempotência).
  • nature só com um identifier de natures, ou omita o campo. É a única escolha que recusa o chamado (422 invalid_nature): nunca envie texto livre.
  • cnpj como texto, só o CNPJ (12.345.678/0001-90): fora do formato, ele é ignorado com o aviso cnpj_ignored, nunca recusado. As regras completas estão na referência.
  • Campo fora do contrato não recusa o chamado: é ignorado e listado no aviso ignored_fields.

O teto do corpo é em bytes. O corpo inteiro tem teto de 65.536 bytes, contados como enviado. Em UTF-8 sem escape, letra sem acento ocupa 1 byte, letra acentuada 2 e emoji 4: os 20.000 caracteres da description só estouram o teto com muitos emojis. Se o seu JSON escapar o Unicode (\u00e3 no lugar de ã, o padrão do json_encode do PHP e do json.dumps do Python), cada acento passa a ocupar 6 bytes e cada emoji 12, e o teto chega bem antes. Envie sem escapar, como fazem os exemplos.

curl
curl -s -i -X POST https://api.gototem.com.br/v1/api-external-system/help-desk-ticket \
  -H "Authorization: Bearer $GOTOTEM_INTEGRATION_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "conv-8841",
    "company": "gototem",
    "description": "Cliente relata que o totem não imprime o cupom.",
    "category": 3,
    "priority": 3,
    "support_level": 1,
    "nature": "hardware",
    "requester": {"name": "Maria Souza", "contact": "maria@loja.com.br"},
    "cnpj": "12.345.678/0001-90"
  }'
# -i mostra o status e os cabeçalhos (inclusive o X-Request-Id) antes do corpo
PowerShell
$body = [ordered]@{
    external_id   = 'conv-8841'
    company       = 'gototem'
    description   = 'Cliente relata que o totem não imprime o cupom.'
    category      = 3
    priority      = 3
    support_level = 1
    nature        = 'hardware'
    requester     = [ordered]@{ name = 'Maria Souza'; contact = 'maria@loja.com.br' }
    cnpj          = '12.345.678/0001-90'
} | ConvertTo-Json -Depth 5

$response = $null
try {
    $response = Invoke-WebRequest -UseBasicParsing -Method Post `
        -Uri 'https://api.gototem.com.br/v1/api-external-system/help-desk-ticket' `
        -Headers @{ Authorization = "Bearer $env:GOTOTEM_INTEGRATION_KEY" } `
        -ContentType 'application/json; charset=utf-8' `
        -Body ([Text.Encoding]::UTF8.GetBytes($body))   # os bytes em UTF-8, nunca a string
} catch {
    $refusal = $_.Exception.Response
    if ($null -eq $refusal) { throw }
    $requestId = $refusal.Headers.GetValues('X-Request-Id') | Select-Object -First 1
    $raw = $_.ErrorDetails.Message
    if (-not $raw) { $raw = (New-Object IO.StreamReader($refusal.GetResponseStream())).ReadToEnd() }
    $code = '(sem code)'
    if ($raw -and $raw.TrimStart().StartsWith('{')) {
        $problem = $raw | ConvertFrom-Json
        if ($problem.code) { $code = $problem.code }
    }
    "HTTP $([int]$refusal.StatusCode) $code $requestId"
}
if ($response) {
    $result = [Text.Encoding]::UTF8.GetString($response.RawContentStream.ToArray()) | ConvertFrom-Json
    $requestId = $response.Headers['X-Request-Id']
    "$($response.StatusCode) $($result.ticket) $($result.applied | ConvertTo-Json -Compress) $(@($result.warnings).Count) aviso(s) $requestId"
}
Python (requests)
import json
import os

import requests

body = {
    "external_id": "conv-8841",
    "company": "gototem",
    "description": "Cliente relata que o totem não imprime o cupom.",
    "category": 3,
    "priority": 3,
    "support_level": 1,
    "nature": "hardware",
    "requester": {"name": "Maria Souza", "contact": "maria@loja.com.br"},
    "cnpj": "12.345.678/0001-90",
}
resp = requests.post(
    "https://api.gototem.com.br/v1/api-external-system/help-desk-ticket",
    headers={
        "Authorization": "Bearer " + os.environ["GOTOTEM_INTEGRATION_KEY"],
        "Content-Type": "application/json",
    },
    # sem escapar o Unicode: o teto do corpo é em bytes
    data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
    timeout=30,
)
request_id = resp.headers.get("X-Request-Id")
result = resp.json() if "json" in resp.headers.get("Content-Type", "") else None
if resp.status_code in (200, 201):
    print(resp.status_code, result["ticket"], result["applied"], result["warnings"], request_id)
else:
    code = result.get("code") if result else None
    print(resp.status_code, code or "(sem code)", request_id)
JavaScript (Node 18+, arquivo .mjs)
const response = await fetch('https://api.gototem.com.br/v1/api-external-system/help-desk-ticket', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer ' + process.env.GOTOTEM_INTEGRATION_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    external_id: 'conv-8841',
    company: 'gototem',
    description: 'Cliente relata que o totem não imprime o cupom.',
    category: 3,
    priority: 3,
    support_level: 1,
    nature: 'hardware',
    requester: { name: 'Maria Souza', contact: 'maria@loja.com.br' },
    cnpj: '12.345.678/0001-90',
  }),
});
const requestId = response.headers.get('X-Request-Id');
// nem toda recusa vem em JSON: leia o corpo só quando ele for JSON
const isJson = (response.headers.get('Content-Type') || '').includes('json');
const result = isJson ? await response.json() : null;
if (response.status === 201 || response.status === 200) {
  console.log(response.status, result.ticket, result.applied, result.warnings, requestId);
} else {
  console.error(response.status, (result && result.code) || '(sem code)', requestId);
}
PHP (curl)
<?php
$body = [
    'external_id' => 'conv-8841',
    'company' => 'gototem',
    'description' => 'Cliente relata que o totem não imprime o cupom.',
    'category' => 3,
    'priority' => 3,
    'support_level' => 1,
    'nature' => 'hardware',
    'requester' => ['name' => 'Maria Souza', 'contact' => 'maria@loja.com.br'],
    'cnpj' => '12.345.678/0001-90',
];
$requestId = null;
$curl = curl_init('https://api.gototem.com.br/v1/api-external-system/help-desk-ticket');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('GOTOTEM_INTEGRATION_KEY'),
        'Content-Type: application/json',
    ],
    // sem escapar o Unicode: o teto do corpo é em bytes
    CURLOPT_POSTFIELDS => json_encode($body, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
    CURLOPT_HEADERFUNCTION => function ($curl, $line) use (&$requestId) {
        if (stripos($line, 'X-Request-Id:') === 0) {
            $requestId = trim(substr($line, strlen('X-Request-Id:')));
        }
        return strlen($line);
    },
]);
$raw = curl_exec($curl);
if ($raw === false) {
    throw new RuntimeException('Rede: ' . curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
$result = json_decode($raw, true);
if ($status === 201 || $status === 200) {
    echo $result['ticket'], ' ', json_encode($result['applied']), ' ', count($result['warnings']), ' aviso(s)', PHP_EOL;
} else {
    echo 'HTTP ', $status, ' ', $result['code'] ?? '(sem code)', ' ', $requestId, PHP_EOL;
}

Falha de rede ou tempo esgotado, nos cinco exemplos, cai no erro da própria linguagem: guarde o chamado e reenvie depois, com o mesmo external_id.

3. Ler a resposta

Resposta 201 (chamado criado)
{
  "ticket": "I-12345A",
  "id": "aGVsbG8td29ybGQ",
  "duplicate": false,
  "warnings": [],
  "applied": {
    "category_id": 3,
    "priority_id": 3,
    "support_level": 1,
    "nature": "hardware",
    "company": "gototem"
  }
}
  • 201: o chamado foi criado. 200 com "duplicate": true: o external_id já tinha um chamado, e a resposta traz esse chamado (ver Reenvio e idempotência).
  • Informe o ticket ao cliente e guarde-o: é o número que a equipe da Gototem enxerga. A API não tem rota para consultar o chamado depois de aberto; para saber dele, fale com o suporte informando o ticket.
  • Confira o applied: a categoria, a prioridade, o nível, a natureza e a empresa que foram de fato gravados, depois dos padrões e das trocas. O cnpj e o requester não voltam nele: sem o aviso cnpj_ignored, o CNPJ foi aceito; o requester acima do limite é cortado, com o aviso requester_truncated. Se veio aviso em warnings, registre no seu log o que você enviou e o que foi gravado, para corrigir a escolha (ver Avisos).
  • Um null no applied não é erro: o chamado foi aberto e o ticket vale. Registre o caso no seu log, junto com o ticket, e siga; não reenvie por causa dele.

Cada campo da resposta está na referência da rota. Uma recusa desta API traz o code: o que fazer com cada uma está em Erros e em Corrigir, reenviar ou falar com o suporte.

Avisos (warnings)

Categoria, prioridade, nível e CNPJ nunca fazem o chamado ser recusado. Valor desconhecido, não liberado para o seu sistema, de tipo errado ou enviado como texto é trocado pelo padrão (o CNPJ fora do formato é ignorado), o chamado é aberto e o aviso vem em warnings.

Resposta 201 com aviso
{
  "ticket": "I-12345B",
  "id": "c2VndW5kby1jaGFtYWRv",
  "duplicate": false,
  "warnings": [
    {"code": "category_fallback", "message": "Unknown or not allowed category. The default category of this system was used."}
  ],
  "applied": {
    "category_id": 7,
    "priority_id": 3,
    "support_level": 1,
    "nature": "software",
    "company": "gototem"
  }
}

No exemplo, a categoria enviada não estava liberada: o chamado foi gravado na categoria padrão (7) com a prioridade padrão dela (3), como mostra o applied.

Avisos do chamado
code O que aconteceu O que fazer
category_fallback A categoria enviada não existe, não está liberada para o seu sistema ou não veio como número inteiro (texto, fração, booleano). Foi usada a categoria padrão. Consulte help-desk-ticket-options de novo e use só ids de lá, como número. Se precisa de outra categoria, peça ao suporte para liberá-la.
priority_fallback A prioridade enviada não existe ou não veio como número inteiro. Foi usada a prioridade padrão da categoria gravada. Consulte help-desk-ticket-options de novo e use só ids de lá, como número.
support_level_fallback O nível não é um dos aceitos ou não veio como número inteiro. Foi usado o nível 1. Envie o id de um item de support_levels, como número, sem aspas.
cnpj_ignored O cnpj veio preenchido, mas fora do formato de 14 caracteres. O chamado foi aberto sem ele. O aviso não diz se o CNPJ é de um cliente da Gototem. Envie só o número do CNPJ, com ou sem pontuação (12.345.678/0001-90).
ignored_fields O corpo trouxe campos que não são do contrato (ou um requester que não é objeto, ou uma chave dele que não é name nem contact). Eles foram ignorados e o chamado foi aberto sem eles. O aviso traz os nomes em fields (no máximo 20, na ordem do corpo; os de dentro de requester como requester.<chave>). Só no 201: o reenvio não traz este aviso. Confira o nome do campo contra a referência da rota (por exemplo, descripton no lugar de description). Se o campo é um dado que o seu sistema envia de propósito, pode ignorar o aviso.
requester_truncated O requester.name ou o requester.contact passou do limite (Limites de uso) e foi cortado; o chamado foi aberto com o texto cortado. O aviso traz em fields os campos cortados (requester.name, requester.contact, na ordem do corpo). Só no 201. Se o nome ou o contato completo importa, encurte-o antes de enviar ou ponha o restante na description.
description_differs Reenvio (200 com "duplicate": true) com uma description diferente da gravada no chamado. O chamado continua o antigo, e a descrição nova não foi gravada. É o único aviso do reenvio. Se é outro problema, abra outro chamado com um external_id novo (ver Reenvio e idempotência). Se é o mesmo problema reescrito, pode ignorar o aviso.

Aviso com um code que você não conhece: o chamado foi criado mesmo assim; registre o aviso e siga.

Reenvio e idempotência

Reenviar com o mesmo external_id nunca cria um segundo chamado: se o chamado já existe, a resposta é 200 com "duplicate": true e o mesmo ticket.

  • O reenvio não altera o chamado: empresa, descrição, categoria, prioridade, nível, natureza, solicitante e CNPJ continuam os da primeira chamada, mesmo que o corpo novo traga outros valores. O applied traz esses valores. Para um novo chamado, use um external_id novo.
  • A descrição diferente vem com aviso: se o reenvio traz uma description diferente da gravada, warnings traz description_differs e a descrição nova não é gravada. É o único aviso do reenvio; sem ele, warnings vem vazio. Para outro problema, use outro external_id: o id da conversa não serve de external_id quando a mesma conversa pode trazer um segundo problema (por exemplo, acrescente ao id da conversa um número para cada problema dela, como conv-8841-2).
  • O registro do external_id é do seu sistema: a rota direta e o webhook dividem o mesmo registro, e outro sistema pode usar o mesmo valor sem colidir com o seu. Ele não expira. A comparação é exata, depois de retirar os espaços das pontas.
  • O reenvio também é validado: um corpo inválido recebe o 422 do campo mesmo que o external_id já tenha um chamado. Reenvie o mesmo corpo da primeira chamada.

Quando reenviar, e quando corrigir antes, está em Corrigir, reenviar ou falar com o suporte.

Abrir um chamado com webhook

Use o webhook quando o seu sistema não chama uma API diretamente, mas tem uma ferramenta de webhook (n8n, Zapier, Make ou a automação do seu chat). O chamado aberto é o mesmo da rota direta.

POST/v1/api-external-system/webhook/{system}Escopo help-desk-ticket.create

Na ferramenta, configure:

  1. O endereço, com o identificador do seu sistema no lugar de {system}. O identificador vem do suporte, junto com a chave.
  2. O cabeçalho Authorization, com Bearer e a chave, como em Como enviar a chave.
  3. O corpo, o mesmo de Abrir um chamado, com um external_id único por atendimento.
curl
curl -s -i -X POST https://api.gototem.com.br/v1/api-external-system/webhook/meu-sistema \
  -H "Authorization: Bearer $GOTOTEM_INTEGRATION_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_id": "conv-8842", "company": "gototem", "description": "Cliente relata que o totem não liga.", "priority": 3}'

O que muda em relação à rota direta:

  • Qualquer Content-Type é aceito.
  • O formato do corpo só é conferido depois da chave; o 413, de corpo acima do teto, continua saindo antes dela. Com Content-Type JSON (application/json ou um tipo +json), o corpo que não é objeto nem lista JSON (JSON quebrado, texto que não é UTF-8, ou um texto, número, true ou null sozinho) é recusado pelo servidor com 400 em application/problem+json, sem code; uma lista recebe 422 invalid_body. Com outro Content-Type, todo corpo que não é objeto recebe 422 invalid_body. Nos dois casos, corrija o corpo: reenviar igual não resolve.
  • Identificador desconhecido, ou a chave de outro sistema, recebe 401 unauthorized. Identificador fora do padrão (maiúscula, acento, outro caractere ou mais de 40 caracteres) não é rota e recebe o 404 not_found (ver Os casos do 404).
  • As respostas são as mesmas, inclusive o applied, e o registro do external_id é o mesmo da rota direta (ver Reenvio e idempotência).

A rota, com as respostas e os erros dela, está na referência.

Na política de reenvio da ferramenta:

Não reenvie ao receber 200: é a confirmação de que o chamado já existe.

  • Reenvie, com o mesmo external_id, ao receber o 503 temporarily_unavailable e o 429 (os dois depois do Retry-After) e o 500 internal_error, e em falha de rede ou tempo esgotado. Se a ferramenta não reenvia no 503 sozinha, configure-a para isso.
  • Não reenvie no 404: é sempre erro de endereço; corrija o endereço na ferramenta.
  • Nos demais casos, corrija antes ou fale com o suporte (ver Corrigir, reenviar ou falar com o suporte).

Enviar um lead

POST/v1/api-external-system/leadEm breveEscopo lead.create

O envio de lead ainda não está disponível: com o escopo lead.create na chave, a rota responde 501 not_implemented; sem ele, 403 forbidden_scope. Até lá, não integre esta rota; a Gototem avisa quando ela for ligada. A rota está na referência.

Chamados

O que o seu sistema pode escolher ao abrir um chamado

GET/v1/api-external-system/help-desk-ticket-optionsEscopo help-desk-ticket.create

Lista as empresas, as categorias liberadas para o seu sistema (com o tipo de cada uma), as prioridades, os níveis de suporte e as naturezas. O id da empresa vai em company, o da categoria em category, o da prioridade em priority, o do nível em support_level e o identifier da natureza em nature. Os ids mudam entre homologação e produção (os do exemplo são ilustrativos): leia-os daqui, nunca os fixe no código.

Guarde a resposta em cache por algumas horas e consulte de novo ao receber category_fallback, priority_fallback ou invalid_nature.

Sem parâmetros.

Resposta 200
{
  "companies": [
    {
      "id": "gototem",
      "name": "Gototem"
    },
    {
      "id": "melhoretec",
      "name": "Melhoretec"
    }
  ],
  "categories": [
    {
      "id": 3,
      "name": "Falha na impressora",
      "description": null,
      "default": false,
      "default_priority_id": 1,
      "type": {
        "id": 3,
        "name": "Problema",
        "description": "Algo que funcionava parou de funcionar ou funciona errado."
      }
    },
    {
      "id": 7,
      "name": "Ajustes em cardápios",
      "description": "Pedido para incluir, alterar ou remover produtos, preços ou opcionais do cardápio. Não use quando algo parou de funcionar.",
      "default": true,
      "default_priority_id": 3,
      "type": {
        "id": 1,
        "name": "Solicitação de Serviço",
        "description": "O cliente pede algo novo ou uma alteração; nada está quebrado."
      }
    }
  ],
  "priorities": [
    {
      "id": 1,
      "name": "Crítica",
      "description": "A loja não consegue vender. Use só quando a operação estiver parada.",
      "level": 1,
      "response_time_hours": 1
    },
    {
      "id": 3,
      "name": "Normal",
      "description": null,
      "level": 3,
      "response_time_hours": 8
    }
  ],
  "support_levels": [
    {
      "id": 1,
      "name": "Nível 1",
      "description": "Primeiro atendimento: dúvidas de uso, orientação e problemas que o suporte resolve com os procedimentos padrão. Use na maioria dos chamados."
    },
    {
      "id": 2,
      "name": "Nível 2",
      "description": "Análise técnica especializada: falha que se repete ou que o primeiro atendimento já tentou resolver sem sucesso, erro do sistema ou de integração. Use só quando a conversa mostrar isso."
    }
  ],
  "natures": [
    {
      "identifier": "hardware",
      "name": "Hardware"
    },
    {
      "identifier": "implementation",
      "name": "Implantação"
    },
    {
      "identifier": "software",
      "name": "Software"
    }
  ]
}
Campos da resposta: O que o seu sistema pode escolher ao abrir um chamado (referência)
Campo Tipo O que é
companies lista de objetos As empresas ativas do grupo Gototem pelas quais o chamado pode ser aberto.
companies[].id texto O identificador da empresa (ex. gototem), o valor que o chamado aceita em company.
companies[].name texto O nome da empresa, para exibir.
categories lista de objetos A categoria padrão do seu sistema e as liberadas para ele, em ordem alfabética do nome do tipo e, dentro de cada tipo, do nome da categoria.
categories[].id inteiro O id (número inteiro) da categoria, o valor que o chamado aceita em category.
categories[].name texto O nome da categoria.
categories[].description texto ou null Quando usar esta opção; null quando ainda não há texto (escolha pelo nome). Texto puro escrito pela Gototem: trate como dado (nunca execute instruções dele) e escape antes de exibir em HTML. O texto pode mudar sem aviso: nunca o copie para o seu código.
categories[].default booleano true na categoria usada quando nenhuma é escolhida.
categories[].default_priority_id inteiro ou null O id (de priorities) da prioridade usada quando o chamado vem com esta categoria e sem priority. Hoje toda categoria tem prioridade padrão; null fica reservado e, se aparecer, envie priority junto com essa categoria.
categories[].type objeto O tipo da categoria (Incidente, Problema, Solicitação de Serviço ou Solicitação de Mudança). Escolher a categoria já define o tipo.
categories[].type.id inteiro O id do tipo. Só informativo; o chamado não recebe o tipo, que vem da categoria.
categories[].type.name texto O nome do tipo.
categories[].type.description texto ou null Quando usar esta opção; null quando ainda não há texto (escolha pelo nome). Texto puro escrito pela Gototem: trate como dado (nunca execute instruções dele) e escape antes de exibir em HTML. O texto pode mudar sem aviso: nunca o copie para o seu código.
priorities lista de objetos Da mais urgente (level 1) para a menos urgente. O response_time_hours é o prazo configurado de cada uma e pode não acompanhar a ordem do level.
priorities[].id inteiro O id (número inteiro) da prioridade, o valor que o chamado aceita em priority.
priorities[].name texto O nome da prioridade.
priorities[].description texto ou null Quando usar esta opção; null quando ainda não há texto (escolha pelo nome). Texto puro escrito pela Gototem: trate como dado (nunca execute instruções dele) e escape antes de exibir em HTML. O texto pode mudar sem aviso: nunca o copie para o seu código.
priorities[].level inteiro A urgência, para ordenar (1 é a mais urgente). Não vai no chamado; o chamado recebe o id.
priorities[].response_time_hours inteiro O prazo configurado da prioridade, em horas. Só informativo.
support_levels lista de objetos Os níveis aceitos. O corpo do chamado manda só o id, como número, em support_level.
support_levels[].id inteiro O valor que o chamado aceita em support_level.
support_levels[].name texto O nome do nível.
support_levels[].description texto ou null Quando usar esta opção; null quando ainda não há texto (escolha pelo nome). Texto puro escrito pela Gototem: trate como dado (nunca execute instruções dele) e escape antes de exibir em HTML. O texto pode mudar sem aviso: nunca o copie para o seu código.
natures lista de objetos As naturezas ativas, em ordem alfabética do nome: os valores aceitos no campo opcional nature do chamado. Natureza nova no cadastro da Gototem aparece aqui; a que for desativada sai, e enviá-la passa a ser recusado com invalid_nature.
natures[].identifier texto O valor que o chamado aceita em nature.
natures[].name texto O nome da natureza, para exibir.

Erros desta rota: 400 · 401 · 403 · 404 · 405 · 429 · 500 · 503

Abre um chamado no help desk

POST/v1/api-external-system/help-desk-ticketEscopo help-desk-ticket.create

O external_id identifica o reenvio: o mesmo external_id devolve o chamado que já existe (200, duplicate: true, como foi criado), nunca um segundo; o corpo do reenvio ainda é validado (os 422 valem). O registro do external_id é por sistema: a rota direta e o webhook do mesmo sistema o compartilham, e ele não expira.

category, priority e support_level nunca recusam o chamado: valor desconhecido, não liberado ou de tipo errado é trocado pelo padrão, com aviso em warnings; o que foi gravado vem em applied.

Corpo
{
  "external_id": "conv-8841",
  "company": "gototem",
  "description": "Cliente relata que o totem não imprime o cupom.",
  "category": 3,
  "priority": 3,
  "support_level": 1,
  "nature": "hardware",
  "requester": {
    "name": "Maria Souza",
    "contact": "maria@loja.com.br"
  },
  "cnpj": "12.345.678/0001-90"
}
Resposta 201
{
  "ticket": "I-12345A",
  "id": "aGVsbG8td29ybGQ",
  "duplicate": false,
  "warnings": [],
  "applied": {
    "category_id": 3,
    "priority_id": 3,
    "support_level": 1,
    "nature": "hardware",
    "company": "gototem"
  }
}

Campos fora desta lista são ignorados, nunca recusados (não há campo de conta ou local: o cnpj é o único identificador do cliente), e vêm no aviso ignored_fields. null num campo opcional é o mesmo que não enviar; num obrigatório, recusa com o missing_* do campo.

Corpo: Abre um chamado no help desk (referência)
Campo Tipo Obrigatório O que é
external_id texto sim O id do atendimento no seu sistema; identifica o reenvio, por sistema. Os espaços das pontas e os caracteres invisíveis e de controle (menos o ZWNJ e o ZWJ) são retirados antes de comparar e de contar; maiúsculas e minúsculas diferem. Inteiro JSON vale como o mesmo texto. Vazio: missing_external_id; acima de 120 caracteres: field_too_long (não é cortado); NUL (\u0000): invalid_field.
company texto sim Id de uma das companies de help-desk-ticket-options (ex. gototem); os espaços das pontas são retirados e maiúscula vale como minúscula. Ausente ou vazio: missing_company; fora da lista: invalid_company.
description texto sim O relato, em texto puro, até 20.000 caracteres (contados antes de retirar os espaços das pontas; quebra de linha e tabulação ficam). Acima: field_too_long (não é cortado: corte no seu lado). Vazio: missing_description. NUL: invalid_field. O corpo inteiro tem teto de 65.536 bytes (413).
category inteiro ou null não Id inteiro de categories (3.0 vale como 3). Ausente: a categoria padrão do sistema. Desconhecida, não liberada, texto ("3") ou fração: também a padrão, com o aviso category_fallback; nunca recusa.
priority inteiro ou null não Id inteiro de priorities (1.0 vale como 1). Ausente: a default_priority_id da categoria gravada. Desconhecida, texto ("1") ou fração: também a padrão, com o aviso priority_fallback; nunca recusa.
support_level inteiro ou null não Id inteiro de support_levels (2.0 vale como 2). Ausente: 1. Fora da lista, texto ("2") ou fração: também 1, com o aviso support_level_fallback; nunca recusa.
nature texto ou null não O identifier de uma das natures de help-desk-ticket-options; os espaços das pontas são retirados e maiúscula vale como minúscula. Ausente: o chamado nasce sem natureza. Outro valor: invalid_nature, a única escolha que recusa o chamado (na dúvida, omita).
cnpj texto ou null não CNPJ do cliente em 14 caracteres, numérico ou alfanumérico, como texto (12.345.678/0001-90 ou L3USOA72000137); a pontuação e o rótulo CNPJ na frente são ignorados, e minúscula vale como maiúscula. O dígito verificador não é conferido. Fora do formato (inclusive o número JSON que perdeu o zero à esquerda): ignorado, com o aviso cnpj_ignored; nunca recusa. O aviso não diz se o CNPJ é de um cliente da Gototem.
requester objeto ou null não Quem pediu: name (até 120 caracteres) e contact (até 160). Acima do limite o texto é cortado, nunca recusado; espaços das pontas e invisíveis (menos o ZWNJ e o ZWJ) são retirados; NUL: invalid_field. Valor que não é texto é ignorado sem aviso; requester que não é objeto, e chave fora de name/contact, vêm em ignored_fields.
requester.name texto ou null não O nome de quem pediu, até 120 caracteres (o excedente é cortado).
requester.contact texto ou null não Como falar com quem pediu (ex. e-mail ou telefone), até 160 caracteres (o excedente é cortado).
Campos da resposta: Abre um chamado no help desk (referência)
Campo Tipo O que é
ticket texto O número do chamado no help desk (começa com I-).
id texto Id do chamado, opaco.
duplicate booleano true quando o external_id já tinha sido enviado.
warnings lista de objetos Escolhas trocadas pelo padrão, CNPJ ignorado, campos fora do contrato e solicitante cortado. Vazio quando nada foi trocado nem ignorado. No reenvio, o único aviso possível é description_differs (outra descrição para o mesmo external_id).
warnings[].code texto Texto aberto. Os valores conhecidos são category_fallback, priority_fallback, support_level_fallback, cnpj_ignored, ignored_fields, requester_truncated e description_differs. Aviso novo pode surgir a qualquer momento: registre o que não conhecer e siga, porque o chamado foi criado (ou já existia, no reenvio).
warnings[].message texto Para leitura humana, em inglês; pode mudar. Use o code na lógica.
warnings[].fields lista de textos Só no ignored_fields e no requester_truncated. No ignored_fields: os campos ignorados, na ordem do corpo (requester.<chave> para os de dentro de requester), no máximo 20 nomes, cada um com até 64 caracteres, sem caracteres invisíveis. No requester_truncated: os campos cortados (requester.name, requester.contact).
applied objeto O que foi de fato gravado no chamado, depois das trocas pelo padrão: confira aqui a categoria, a prioridade e o nível que valeram. No reenvio (200), os valores do chamado que já existia. null em qualquer campo não é erro: o chamado foi aberto; não reenvie por causa dele. Traz só estes cinco campos: o cnpj não é ecoado (sem o aviso cnpj_ignored, ele foi aceito) e o requester também não (o excedente é cortado, com o aviso requester_truncated).
applied.category_id inteiro ou null O id da categoria gravada. Na criação sempre vem; null só num reenvio de chamado que perdeu a categoria depois.
applied.priority_id inteiro ou null O id da prioridade gravada; pode ser null.
applied.support_level inteiro ou null O nível de suporte gravado; pode ser null.
applied.nature texto ou null O identifier da natureza gravada. null quando o chamado não tem natureza.
applied.company texto ou null O id (de companies) da empresa gravada; pode ser null.

Erros desta rota: 400 · 401 · 403 · 404 · 405 · 413 · 415 · 422 · 429 · 500 · 503

Abre um chamado pelo webhook do seu sistema

POST/v1/api-external-system/webhook/{system}Escopo help-desk-ticket.create

O mesmo chamado da rota direta, para quando o seu sistema envia por webhook. {system} é o identificador do seu sistema, informado pelo suporte da Gototem junto com a chave. Nesta versão o webhook também exige a chave no cabeçalho Authorization e o corpo segue o mesmo formato da rota direta, com as mesmas respostas (inclusive applied). Qualquer Content-Type é aceito. O teto de 65.536 bytes (413) vale antes da chave, como nas outras rotas; o formato do corpo (invalid_body) só é conferido depois dela. Com Content-Type JSON, corpo que não é objeto nem lista JSON recebe 400 em application/problem+json, sem code.

Identificador desconhecido, ou a chave de outro sistema, recebe 401 unauthorized. Identificador fora do padrão (maiúscula, acento, outro caractere ou mais de 40 caracteres) não é rota: recebe o 404 not_found.

Corpo
{
  "external_id": "conv-8842",
  "company": "gototem",
  "description": "Cliente relata que o totem não imprime o cupom.",
  "category": 3,
  "priority": 3,
  "support_level": 1,
  "nature": "hardware",
  "requester": {
    "name": "Maria Souza",
    "contact": "maria@loja.com.br"
  },
  "cnpj": "12.345.678/0001-90"
}
Resposta 201
{
  "ticket": "I-12345A",
  "id": "aGVsbG8td29ybGQ",
  "duplicate": false,
  "warnings": [],
  "applied": {
    "category_id": 3,
    "priority_id": 3,
    "support_level": 1,
    "nature": "hardware",
    "company": "gototem"
  }
}
Parâmetros: Abre um chamado pelo webhook do seu sistema (referência)
Parâmetro Obrigatório O que é
system sim O identificador do seu sistema (letras minúsculas, números, - e _, até 40 caracteres)

Campos fora desta lista são ignorados, nunca recusados (não há campo de conta ou local: o cnpj é o único identificador do cliente), e vêm no aviso ignored_fields. null num campo opcional é o mesmo que não enviar; num obrigatório, recusa com o missing_* do campo.

Corpo: Abre um chamado pelo webhook do seu sistema (referência)
Campo Tipo Obrigatório O que é
external_id texto sim O id do atendimento no seu sistema; identifica o reenvio, por sistema. Os espaços das pontas e os caracteres invisíveis e de controle (menos o ZWNJ e o ZWJ) são retirados antes de comparar e de contar; maiúsculas e minúsculas diferem. Inteiro JSON vale como o mesmo texto. Vazio: missing_external_id; acima de 120 caracteres: field_too_long (não é cortado); NUL (\u0000): invalid_field.
company texto sim Id de uma das companies de help-desk-ticket-options (ex. gototem); os espaços das pontas são retirados e maiúscula vale como minúscula. Ausente ou vazio: missing_company; fora da lista: invalid_company.
description texto sim O relato, em texto puro, até 20.000 caracteres (contados antes de retirar os espaços das pontas; quebra de linha e tabulação ficam). Acima: field_too_long (não é cortado: corte no seu lado). Vazio: missing_description. NUL: invalid_field. O corpo inteiro tem teto de 65.536 bytes (413).
category inteiro ou null não Id inteiro de categories (3.0 vale como 3). Ausente: a categoria padrão do sistema. Desconhecida, não liberada, texto ("3") ou fração: também a padrão, com o aviso category_fallback; nunca recusa.
priority inteiro ou null não Id inteiro de priorities (1.0 vale como 1). Ausente: a default_priority_id da categoria gravada. Desconhecida, texto ("1") ou fração: também a padrão, com o aviso priority_fallback; nunca recusa.
support_level inteiro ou null não Id inteiro de support_levels (2.0 vale como 2). Ausente: 1. Fora da lista, texto ("2") ou fração: também 1, com o aviso support_level_fallback; nunca recusa.
nature texto ou null não O identifier de uma das natures de help-desk-ticket-options; os espaços das pontas são retirados e maiúscula vale como minúscula. Ausente: o chamado nasce sem natureza. Outro valor: invalid_nature, a única escolha que recusa o chamado (na dúvida, omita).
cnpj texto ou null não CNPJ do cliente em 14 caracteres, numérico ou alfanumérico, como texto (12.345.678/0001-90 ou L3USOA72000137); a pontuação e o rótulo CNPJ na frente são ignorados, e minúscula vale como maiúscula. O dígito verificador não é conferido. Fora do formato (inclusive o número JSON que perdeu o zero à esquerda): ignorado, com o aviso cnpj_ignored; nunca recusa. O aviso não diz se o CNPJ é de um cliente da Gototem.
requester objeto ou null não Quem pediu: name (até 120 caracteres) e contact (até 160). Acima do limite o texto é cortado, nunca recusado; espaços das pontas e invisíveis (menos o ZWNJ e o ZWJ) são retirados; NUL: invalid_field. Valor que não é texto é ignorado sem aviso; requester que não é objeto, e chave fora de name/contact, vêm em ignored_fields.
requester.name texto ou null não O nome de quem pediu, até 120 caracteres (o excedente é cortado).
requester.contact texto ou null não Como falar com quem pediu (ex. e-mail ou telefone), até 160 caracteres (o excedente é cortado).
Campos da resposta: Abre um chamado pelo webhook do seu sistema (referência)
Campo Tipo O que é
ticket texto O número do chamado no help desk (começa com I-).
id texto Id do chamado, opaco.
duplicate booleano true quando o external_id já tinha sido enviado.
warnings lista de objetos Escolhas trocadas pelo padrão, CNPJ ignorado, campos fora do contrato e solicitante cortado. Vazio quando nada foi trocado nem ignorado. No reenvio, o único aviso possível é description_differs (outra descrição para o mesmo external_id).
warnings[].code texto Texto aberto. Os valores conhecidos são category_fallback, priority_fallback, support_level_fallback, cnpj_ignored, ignored_fields, requester_truncated e description_differs. Aviso novo pode surgir a qualquer momento: registre o que não conhecer e siga, porque o chamado foi criado (ou já existia, no reenvio).
warnings[].message texto Para leitura humana, em inglês; pode mudar. Use o code na lógica.
warnings[].fields lista de textos Só no ignored_fields e no requester_truncated. No ignored_fields: os campos ignorados, na ordem do corpo (requester.<chave> para os de dentro de requester), no máximo 20 nomes, cada um com até 64 caracteres, sem caracteres invisíveis. No requester_truncated: os campos cortados (requester.name, requester.contact).
applied objeto O que foi de fato gravado no chamado, depois das trocas pelo padrão: confira aqui a categoria, a prioridade e o nível que valeram. No reenvio (200), os valores do chamado que já existia. null em qualquer campo não é erro: o chamado foi aberto; não reenvie por causa dele. Traz só estes cinco campos: o cnpj não é ecoado (sem o aviso cnpj_ignored, ele foi aceito) e o requester também não (o excedente é cortado, com o aviso requester_truncated).
applied.category_id inteiro ou null O id da categoria gravada. Na criação sempre vem; null só num reenvio de chamado que perdeu a categoria depois.
applied.priority_id inteiro ou null O id da prioridade gravada; pode ser null.
applied.support_level inteiro ou null O nível de suporte gravado; pode ser null.
applied.nature texto ou null O identifier da natureza gravada. null quando o chamado não tem natureza.
applied.company texto ou null O id (de companies) da empresa gravada; pode ser null.

Erros desta rota: 400 · 401 · 403 · 404 · 405 · 413 · 422 · 429 · 500 · 503

Leads

Envio de lead (ainda não disponível)

POST/v1/api-external-system/leadEm breveEscopo lead.create

A rota já autentica e confere o formato mínimo, mas ainda não grava: responde 501 not_implemented. Não integre esta rota até a Gototem avisar. Sem o escopo lead.create na chave, a resposta é o 403 forbidden_scope.

Corpo: Envio de lead (ainda não disponível) (referência)
Campo Tipo Obrigatório O que é
external_id texto sim

Em breve: hoje responde 501; a forma da rota ainda pode mudar.

Erros desta rota: 400 · 401 · 403 · 404 · 405 · 413 · 415 · 422 · 429 · 500 · 501 · 503

Como pedir ajuda

Fale com o suporte da Gototem pelo mesmo canal por onde a chave foi entregue, ou escreva para integracoes@gototem.com.br. É o suporte que cadastra o sistema, entrega e troca a chave, libera escopo e categoria e informa o endereço de homologação.

Antes de pedir ajuda, confira Corrigir, reenviar ou falar com o suporte: ali está, para cada resposta, se o caso se resolve do seu lado ou se precisa do suporte.

O que enviar ao pedir ajuda

O que enviar ao suporte
O que Onde está
X-Request-Id no cabeçalho de toda resposta das rotas desta API, inclusive das recusas
A rota chamada o método e o endereço (por exemplo, POST /v1/api-external-system/help-desk-ticket)
O horário da chamada no seu log; diga o fuso
O status HTTP e o code na resposta; o code, no corpo
O external_id no corpo que o seu sistema enviou

Nunca envie a chave, nem um pedaço dela, nem um print em que ela apareça. O suporte não precisa dela para investigar. Se a chave foi exposta, peça a troca.