JSON Toolkit

Que estrutura uma resposta de API deve usar

Resumo: Objetos crus são limpos até você precisar de metadados; envelopes completos são seguros mas verbosos. Para a maioria dos projetos use status HTTP para resultados e um envelope estável para dados.

Intermediário~4 min de leituraPublicado em 2026-10-30Atualizado em 2026-10-30
Três formatos de resposta de API e seus trade-offs

Resumo da ópera: expresse resultados com códigos de status 4xx/5xx, carregue o payload em { "data": ..., "meta": ... } e mude para um envelope error em caso de falha; isso basta para APIs internas, e só plataformas públicas com muitos integradores precisam de JSON:API ou OpenAPI.

Descarte primeiro a pior opção: sempre retornar 200 com o resultado em um campo code.

Três formatos

A. Objeto cru

{ "id": 1, "name": "demo", "price": 99 }

Limpo, e a semântica HTTP faz o trabalho (404 é 404). Mas no momento em que você precisa de paginação, avisos ou um trace id, não há onde colocá-los sem mudar o contrato.

B. Envelope estável

{
  "data": { "id": 1, "name": "demo" },
  "meta": { "requestId": "abc", "took": 12 }
}

Payload e metadados vivem separados, então novos metadados nunca remodelam data. Custa um nível de aninhamento.

C. Envelope para tudo (evite)

{ "code": 0, "message": "success", "data": {...} }

O formato não é o pecado; a prática é. Status 200 para todo resultado significa que CDNs, gateways, circuit breakers, políticas de retentativa e dashboards todos veem sucesso. Todo alerta então precisa de análise customizada.

A recomendação

Status HTTP para o resultado, envelope para o payload.

{
  "data": { "id": 1, "name": "demo" },
  "meta": { "requestId": "req_8f2a", "took": 12 }
}
{
  "error": {
    "code": "ORDER_NOT_FOUND",
    "message": "O pedido não existe ou foi excluído",
    "details": [{ "field": "id", "issue": "not_found" }]
  },
  "meta": { "requestId": "req_8f2a" }
}

Status 4xx ou 5xx; code estável e legível por máquina; message para humanos; details para erros de formulário em nível de campo.

Regras rígidas

  1. Endpoints de lista precisam carregar metadados de paginação. Sem total ou um cursor, não há paginador.
  2. Listas vazias retornam [], nunca null. null.map é uma indisponibilidade recorrente.
  3. Timestamps em ISO 8601 com offset. Veja que formato para timestamps.
  4. Uma convenção de nomeação. snake_case ou camelCase, convertida uma vez na fronteira.
  5. Dinheiro como unidades menores inteiras ou strings. 99.99 não é exato em ponto flutuante binário.
  6. Não confunda null com ausente. Veja null ou omitir o campo.

Quando adotar uma especificação

  • Plataformas públicas com muitos integradores: JSON:API ou OpenAPI mais um envelope compartilhado
  • APIs internas de uma única equipe: o envelope acima basta
  • Contratos fortes: Schema primeiro, estruturas geradas a partir dele

Especificações economizam discussão e custam onboarding. Para uma equipe de cinco pessoas, JSON:API normalmente é trabalho negativo.

Perguntas frequentes

Como devo escolher entre um objeto cru e um envelope?

Use um envelope quando precisar de paginação, avisos ou um requestId, para que meta possa crescer sem remodelar data. Retorne o objeto cru apenas quando não precisar de metadados e aceitar que adicionar campos depois muda o contrato.

Por que uma API nunca deve retornar 200 para todo resultado?

CDNs, gateways, circuit breakers, políticas de retentativa e dashboards todos leem o status HTTP para decidir se devem fazer cache, retentar ou alertar. Com 200 em toda parte, eles tratam falhas como sucessos, e todo alerta precisa de análise customizada do código de negócio.

Endpoints de lista devem carregar metadados de paginação?

Sim. Sem total ou um cursor não há paginador, e listas vazias precisam retornar [] em vez de null, ou a chamada .map do frontend quebra.

Leitura adicional