Convenções e erros
Toda resposta da API compartilha o mesmo envelope, e estas convenções valem para todos os recursos. Cada página de recurso, como Links, aponta para cá em vez de repetir as regras.
Envelope de resposta
Os recursos JSON usam o envelope Ok/Err com Content-Type: application/json.
Sucesso vem com 200 OK e JSON formatado, com o valor embrulhado sob Ok:
{ "Ok": <valor> }
Erro vem com o status resolvido e a mensagem sob Err. A mensagem traz toda a cadeia de contexto:
{ "Err": <mensagem> }
Endpoints de listagem retornam um array puro sob Ok, não um objeto embrulhado:
{ "Ok": [...] }
Nota
Quatro listas fogem dessa forma e embrulham o resultado: ab_tests, a lista de chaves do armazenamento chave-valor da conta (/account-kv), GET /track/rules e GET /track/tag. As duas últimas respondem { "Ok": { "rules": [ ... ] } }. Um recurso único com filhos aninhados (uma página com seus widgets, por exemplo) é legitimamente um objeto; a regra do array vale para listas.
Respostas fora do envelope Ok/Err:
| Saída | Formato |
|---|---|
| Relatórios e exportação de estatísticas de eventos | text/csv. Nas estatísticas de eventos, GET /events/stats responde JSON no envelope e GET /events/errors responde CSV. |
QR code de smart link (GET /servers/{server_name}/links/qr/{link_with_ext}) | Imagem crua, image/png ou image/svg+xml conforme a extensão pedida |
Logs de evento das plataformas (rotas .../logs) | text/event-stream (Server-Sent Events), com keep-alive a cada 15 s |
| Rejeições de autenticação | Texto puro (text/plain) |
| Rejeições de Host/TLS | Corpo literal, sem Content-Type |
| Erros de extração do corpo | Fora do envelope Err |
| Parâmetro de query inválido | 400, fora do envelope Err |
Aviso
Os corpos das rejeições de autenticação são textos como "Bad token", "Not authorized", "Insufficient privilege: ..." ou "Feature disabled: <flag>". Um cliente que faz JSON.parse de todo corpo de erro quebra nesses 401/403.
Nomes e campos
- Os campos no fio são snake_case verbatim:
dashboard_name,created_at,position. - A chave de negócio segue o padrão
<entidade>_name(account_name,link_name,server_name), nunca umnamesolto. - Os recursos são endereçados por nome de ponta a ponta. Parâmetros de caminho são nomes, e chamadas escopadas por conta levam a conta pelo nome. O identificador interno de cada recurso não é serializado.
- Data/hora segue ISO-8601 sem fuso horário (ex.:
2026-09-01T00:00:00), tanto em query params (since,until) quanto em campos serializados (epoch,happened_at,created_at,updated_at). - Valores de enum em query params vão em minúsculas (ex.:
?step=day).
Códigos de status
Quando o handler não fixa o status, ele sai do texto da mensagem; por isso as mensagens de erro do cliente têm a forma "Error 404: ...".
| Situação | Status |
|---|---|
Mensagem com prefixo Error NNN | NNN |
| Mensagem sem esse prefixo | 500 |
| Credencial ausente ou malformada | 401 |
| Token inválido ou insuficiente | 403 |
Conta sem a feature flag da rota, com token válido e privilégio suficiente: "Feature disabled: <flag>" | 403 |
| Falha interna na autenticação | 500 |
If-Match malformado ou * | 400 |
| Escrita obsoleta (token não é mais o atual) | 412 |
| Parâmetro de query inválido (ex.: valor de enum desconhecido) | 400 |
Host divergente do nome TLS: "Host header does not match TLS server name" | 400 |
Host ausente: "Missing host header in HTTP connection" | 400 |
Informação de conexão ausente: "Missing connection info" | 500 |
Nota
- As rejeições de autenticação usam status fixos, independentes da convenção
Error NNN. - O
403de feature flag é distinto do403de token inválido ou insuficiente.WebTracking, por exemplo, gateia/track/rules: uma conta sem essa flag toma403 "Feature disabled: WebTracking"ali mesmo com token válido. - As rejeições de Host acontecem antes do handler.
- As rejeições de query também ficam fora da convenção
Error NNN. - Os erros de extração do corpo (JSON malformado, tipo de conteúdo errado, corpo grande demais) não seguem a convenção
Error NNNe podem devolver um status fora desta tabela.
Tamanho do corpo
O corpo de cada requisição às rotas REST é limitado a 2 MiB.
Escritas condicionais (ETag e If-Match)
- Uma leitura de recurso que suporta concorrência otimista devolve um
ETagforte no cabeçalho: um token opaco entre aspas. A camada CORS expõe o cabeçalhoETag, então clientes no navegador conseguem lê-lo entre origens. - Para uma escrita condicional, reenvie esse valor no cabeçalho
If-Match. - Sem
If-Match, a escrita é incondicional. - Se o token não for mais o atual, porque o recurso mudou desde a leitura, a escrita falha com
412: releia o recurso e tente de novo. - Um
If-Matchmalformado, ou o coringa*(não suportado), responde400pedindo umETagde uma leitura anterior.
Importante
O token é opaco e efêmero: muda a cada escrita do recurso. Trate-o como caixa-preta, releia para obter um novo e não tente interpretá-lo nem guardá-lo por muito tempo.
Exemplo do fluxo: leia o recurso, guarde o ETag da resposta e use-o no If-Match da escrita.
# 1. Leia o recurso e guarde o ETag devolvido
curl -i https://tgsr.com.br/servers/<server_name>
# -> ETag: "<token>"
# 2. Escreva reenviando o token em If-Match
curl -X PUT https://tgsr.com.br/servers \
-H 'If-Match: "<token>"' \
-H 'Content-Type: application/json' \
-d '{ ... }'
# token obsoleto -> 412 (releia e repita)
Aceitam escrita condicional: servidores de rastreamento, smart links, pixels (Facebook), measurement IDs (GA4), pixels TikTok, conversões LinkedIn, ad accounts Pinterest, customers do Google Ads, ações de conversão do Google Ads, dashboards, usuários, contas e o armazenamento chave-valor da conta (/account-kv).
Veja também
- Autenticação: o modelo de scopes por trás dos
401/403. - Links: uma referência de recurso que segue estas convenções.
- Introdução: o modelo de host e a hierarquia de contas.