Pular para o conteúdo
← Voltar para o Skalablog

Artigo publicado

Como fazer design de APIs com contrato bem definido

Engenharia de SoftwareOpenAI

Bom design de APIs começa pelo contrato: a API é o ponto central do software web moderno, e alterá-la é como renegociar um acordo assinado. Este artigo reúne as decisões que importam — code first, contract first e consumer first, tratamento de erros, idempotência, versionamento e BFF — com exemplos práticos de cada escolha.

Design de APIs: por que o contrato importa mais que o código

Bom design de APIs começa pelo contrato: a API é o ponto central do software web moderno e mudar um contrato é como renegociar um acordo assinado. Se o front end espera um campo e o back end devolve outro, a aplicação quebra. Se o consumidor é um cliente externo, o estrago é maior ainda, porque ele depende do seu formato de resposta.

O palestrante do vídeo — que apresenta o canal do Augusto Galego — resume o raciocínio: quase todo código hoje é escrito com ajuda de IA, mas a API continua sendo a parte que sustenta performance, funcionamento e custo da aplicação. Uma query pesada escondida atrás de um endpoint deixa o produto lento. Um payload mal modelado vira dívida técnica difícil de pagar.

Antes de desenhar, porém, existe uma decisão de arquitetura: REST, GraphQL ou RPC. E depois vem a decisão de processo: começar pelo código, pelo contrato ou pelo consumidor. As duas escolhas são diferentes, e confundi-las é um erro comum.

REST, GraphQL ou RPC: qual estilo usar em cada caso

Não existe um estilo universalmente melhor; existe um estilo adequado ao formato das suas queries e ao vínculo entre as equipes. REST é o padrão mais web e funciona muito bem em equipes full stack, quando o mesmo time controla front e back. GraphQL brilha quando você encadeia queries profundas, como autor → livros → edições, cenário comum em e-commerce. RPC costuma fazer sentido entre dois back ends, com foco em performance.

O caso do Facebook ajuda a fixar o contexto. A empresa criou o GraphQL em 2015 justamente porque mantinha vários aplicativos crescendo rápido e não dava conta de criar um endpoint novo para cada tela. É uma solução complexa para um problema complexo: se você tem uma ou duas telas complicadas, endpoints específicos resolvem sem introduzir toda a máquina do GraphQL.

EstiloMelhor cenárioPonto de atenção
RESTApp web, equipes full stackEvite rigor excessivo com RESTful puro
GraphQLQueries nesteadas, muitos clientes diferentesComplexidade operacional alta
RPCComunicação entre back endsMenos natural para front end

Code first, contract first ou consumer first: como começar a construir

A escolha entre code first, contract first e consumer first é mais organizacional do que técnica. O resultado final dos três caminhos pode ser idêntico; o que muda é como o trabalho flui entre as pessoas.

Code first. Você escreve o back end primeiro e uma ferramenta gera a spec. Um exemplo clássico é o FastAPI, que define o endpoint em código e produz automaticamente a documentação no Swagger. É rápido, mas acopla a API à implementação: alterou o back end, alterou o contrato. Em produto interno isso é tolerável; em API pública, é arriscado.

Contract first. Times definem endpoints, parâmetros, respostas e erros antes do código. O fluxo típico fica assim:

  1. Front end e back end se reúnem e listam o que a feature precisa.
  2. O contrato é escrito e documentado, por exemplo em OpenAI, a especificação nascida do Swagger em 2015.
  3. Cada time constrói em paralelo usando a spec como única fonte de verdade.

O palestrante prefere esse caminho: ele força o time a pensar antes de codar e permite que front e back evoluam de forma independente. Em repositórios separados, muitas vezes a spec sozinha basta como contexto.

Consumer first. O front end especifica o que precisa receber e o back end se adapta. O autor vê utilidade em microsserviços, em que um serviço declara o que quer consumir, mas não recomenda como padrão geral.

Uma comparação útil é a API pública do Shopify, que mantém especificações estáveis porque clientes externos dependem delas. Contrato bem definido é promessa, e promessa com terceiro não se quebra sem aviso.

Como padronizar métodos e projetar erros que ajudam sem vazar dados

O padrão é seu amigo: IA sabe gerar código REST convencional, o mercado conhece as convenções e a previsibilidade economiza tempo. GET para buscar, POST para criar, PATCH e PUT para atualizar, DELETE para remover. Ninguém precisa de rigor absoluto — deletar via POST não é tragédia. O que incomoda de verdade é update via POST, e um POST que faz busca só se justifica no caso raro de parâmetros de URL estourarem o limite de caracteres.

Outra regra: fale no domínio, não na implementação. Todo mundo entende /users; ninguém precisa saber que sua tabela se chama tbl_user_records. O contrato da API não deve estar acoplado ao banco de dados nem ao front end — são camadas que evoluem separadas.

Erro também faz parte do contrato, em duas frentes:

  • Prevenção. Se um status aceita apenas quatro valores, modele como enum e documente na spec. Uma spec bem feita orienta o consumidor antes do erro acontecer.
  • Resposta. Devolva código e mensagem claros, mais úteis que um 400 genérico. "Saldo insuficiente" para um usuário logado é informativo e seguro.

Cuidado com o que a mensagem revela. Dizer que o usuário não foi encontrado, que o e-mail existe ou que a senha está errada entrega pistas a um atacante. Erro útil e erro seguro são coisas diferentes, e o design precisa equilibrar as duas.

Idempotência: como evitar o pedido duplicado no Pix e no seu endpoint

Uma chave de idempotência é um identificador que permite ao back end reconhecer se um request é repetição do anterior. Ela resolve o problema clássico do duplo clique no botão de postar, que dispararia dois requests e criaria conteúdo duplicado.

O exemplo mais cotidiano é bancário: se você faz um Pix de 10 centavos e tenta repetir cinco segundos depois, o banco bloqueia e avisa que a operação acabou de acontecer. Existe idempotência naquele endpoint, e é ela que impede a transferência duplicada.

Existem duas escolas. Na primeira, o front end envia a chave a cada request, mantendo o controle do lado do cliente. Na segunda, defendida pelo autor do vídeo, a chave é computada no back end com um hash do ID do usuário, do conteúdo exato e de uma janela temporal — você elimina a dependência do front end, embora exista discordância razoável, já que o cliente perde o controle de definir o que é igual ou diferente. A escolha depende de quanta segurança e de quem detém a decisão no seu produto.

Versionamento e evolução: quebrar compatibilidade sem quebrar clientes

Adicionar campos é seguro: um cliente que não espera o campo id junto do name simplesmente o ignora. O problema é mudar ou remover o que foi prometido. Trocar name por full_name quebra retrocompatibilidade, porque o cliente espera um campo que não vem mais.

Para evoluir sem quebrar, existem três caminhos práticos:

  1. Versionar na URL, como /api/v1 e /api/v2, prática comum e bastante razoável; para o autor, onde a versão aparece (URL ou parâmetro) é detalhe, desde que todo mundo concorde.
  2. Duplicar temporariamente, retornando name e full_name juntos até os clientes migrarem.
  3. Deprecar campo a campo dentro da mesma versão, monitorando quem ainda consome o campo antigo.

O autor prefere quebras limpas de versão, acumulando mudanças e lançando V2 de uma vez, em vez de deprecações espalhadas. Independentemente da preferência, a pergunta guia é a mesma: o que é um usuário no meu domínio, e o que /users deve poder retornar no futuro? Projetar essa semântica com folga é o que faz a API sobreviver às mudanças do software.

Backend for frontend: quando o caso de uso fica complexo demais para o domínio

Backend for frontend, o BFF, é criar endpoints que mapeiam diretamente para páginas. A motivação aparece quando montar uma tela exige vários requests encadeados: buscar usuários, depois os posts de cada usuário, depois os comentários e a mídia. Com 10 usuários e 10 posts cada, você já está servindo centenas de comentários em chamadas em cascata — e o banco de dados sente.

O BFF inverte o desenho: um único GET no feed calcula tudo no back end e retorna apenas os campos daquela tela. Quando um ou dois casos de uso ficam muito complexos, endpoints específicos assim fazem sentido, mesmo fugindo do domínio puro.

Quando as telas se multiplicam — apps web, mobile, iOS cresciendo ao mesmo tempo, como no Facebook de meados dos anos 2010 — criar endpoint novo para cada tela deixa de ser viável, e aí entra GraphQL ou o BFF. A lição: a complexidade das suas telas, e não a moda do momento, é que decide o desenho.

FAQ: perguntas rápidas sobre design de APIs

  • O que é design de APIs? É o processo de definir endpoints, parâmetros, respostas, erros e regras de evolução de uma API antes e durante a implementação. Um bom design trata o contrato como produto, pensa no domínio e garante previsibilidade para quem consome.
  • Code first ou contract first: qual escolher? Code first acelera a entrega e gera documentação automática a partir do código. Contract first permite que front e back trabalhem em paralelo e mantém a API desacoplada da implementação, sendo preferível quando há clientes externos.
  • Quando usar GraphQL em vez de REST? GraphQL compensa quando as telas exigem queries profundamente nesteadas ou quando vários clientes diferentes precisam de recortes distintos dos mesmos dados. Para uma aplicação web comum com equipe enxuta, REST costuma bastar.
  • Por que usar chave de idempotência? Ela impede que o mesmo request seja processado duas vezes, como um post duplicado ou um Pix repetido. A chave pode ser enviada pelo front end ou computada no back end a partir de um hash do conteúdo e de uma janela de tempo.
  • Adicionar campos em uma API quebra os clientes? Não, desde que os clientes ignorem campos desconhecidos, como um cliente bem desenhado faz. O que quebra retrocompatibilidade é remover, renomear ou alterar o formato de um campo prometido no contrato.

Transforme suas explicações em artigos com o Skala Blog

A ideia central deste artigo é que um contrato bem pensado transforma conhecimento difuso em algo que times inteiros conseguem consumir. Com conhecimento técnico em vídeo acontece o mesmo: muita explicação boa fica presa no formato de áudio e imagem.

Se você grava vídeos com aulas, opiniões ou lições como as que o Augusto Galego compartilha, o Skala Blog converte esse material em artigo escrito: você cola a URL do YouTube, o vídeo é transcrito e o artigo é gerado para você revisar e publicar.

Source video