Docs
Referência

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:

json
{ "Ok": <valor> }

Erro vem com o status resolvido e a mensagem sob Err. A mensagem traz toda a cadeia de contexto:

json
{ "Err": <mensagem> }

Endpoints de listagem retornam um array puro sob Ok, não um objeto embrulhado:

json
{ "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ídaFormato
Relatórios e exportação de estatísticas de eventostext/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çãoTexto puro (text/plain)
Rejeições de Host/TLSCorpo literal, sem Content-Type
Erros de extração do corpoFora do envelope Err
Parâmetro de query inválido400, 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 um name solto.
  • 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çãoStatus
Mensagem com prefixo Error NNNNNN
Mensagem sem esse prefixo500
Credencial ausente ou malformada401
Token inválido ou insuficiente403
Conta sem a feature flag da rota, com token válido e privilégio suficiente: "Feature disabled: <flag>"403
Falha interna na autenticação500
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 403 de feature flag é distinto do 403 de token inválido ou insuficiente. WebTracking, por exemplo, gateia /track/rules: uma conta sem essa flag toma 403 "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 NNN e 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 ETag forte no cabeçalho: um token opaco entre aspas. A camada CORS expõe o cabeçalho ETag, 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-Match malformado, ou o coringa * (não suportado), responde 400 pedindo um ETag de 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.

bash
# 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.