Uma API REST permite que aplicações diferentes troquem informações por meio da web. Um sistema de vendas, por exemplo, pode disponibilizar produtos, clientes e pedidos para um site, aplicativo móvel ou serviço externo. Cada aplicação mantém suas próprias responsabilidades, enquanto a API estabelece uma forma previsível de comunicação.
Embora o assunto envolva HTTP, endpoints, JSON, códigos de status e segurança, seu funcionamento pode ser entendido com uma sequência prática. Neste guia, construiremos uma pequena API de produtos usando C# e ASP.NET Core. Depois, enviaremos requisições para consultar, cadastrar, atualizar e excluir registros.
Ao final, você terá uma visão completa do fluxo entre cliente e servidor e uma base sólida para desenvolver integrações profissionais. Prepare o ambiente, acompanhe os exemplos e continue lendo para criar sua primeira API passo a passo.
O que é API REST?
API é a sigla de Application Programming Interface, ou Interface de Programação de Aplicações. Trata-se de um contrato que define como um software pode solicitar dados ou operações a outro. Esse contrato informa quais recursos estão disponíveis, quais dados devem ser enviados e quais respostas podem ser recebidas.
REST significa Representational State Transfer. É um estilo arquitetural que orienta a construção de sistemas distribuídos baseados em recursos, representações e uma interface uniforme. Em vez de expor operações como /buscarProduto ou /excluirProduto, uma API REST bem organizada representa entidades por URLs.
/api/produtos
/api/produtos/10
/api/clientes
/api/pedidos/2026O endereço /api/produtos/10 identifica o produto de código 10. O que será feito com ele depende do método HTTP utilizado. Uma requisição GET consulta o produto; PUT pode substituí-lo; PATCH altera parte de seus dados; DELETE solicita sua exclusão.
Nem toda API que utiliza HTTP e JSON segue todos os princípios REST. Muitas são APIs HTTP com características RESTful. Na prática profissional, o termo API REST costuma designar serviços que organizam URLs em torno de recursos, usam corretamente os métodos HTTP e retornam códigos de status coerentes.
Como uma API REST funciona?
A comunicação acontece principalmente entre um cliente e um servidor. O cliente pode ser um navegador, aplicativo móvel, sistema corporativo ou outro serviço. O servidor recebe a solicitação, executa as validações e regras de negócio, consulta os dados necessários e devolve uma resposta.
A requisição contém método, endereço, cabeçalhos e, quando necessário, um corpo. A resposta contém um código de status, cabeçalhos e, geralmente, uma representação do recurso.
GET /api/produtos/10 HTTP/1.1
Host: exemplo.com
Accept: application/jsonUma resposta bem-sucedida poderia ser:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 10,
"nome": "Teclado mecânico",
"preco": 299.90
}JSON é muito utilizado porque possui uma estrutura textual simples e pode ser processado facilmente em C#, JavaScript, Java, PHP e várias outras tecnologias.
Recursos e endpoints
Um recurso é uma entidade relevante para o sistema, como produto, pedido ou colaborador. Um endpoint é a combinação de uma URL com um método HTTP. Portanto, GET /api/produtos e POST /api/produtos são endpoints diferentes, ainda que compartilhem o mesmo caminho.
Prefira substantivos nas rotas, como /api/produtos, /api/clientes/25 e /api/pedidos/18/itens. Evite caminhos como /api/listarProdutos ou /api/apagarProduto, pois os métodos HTTP já expressam a operação.
Comunicação sem estado
Uma característica importante do REST é a ausência de estado de sessão entre as requisições, conhecida como statelessness. Cada solicitação deve levar as informações necessárias para ser compreendida. Se um endpoint protegido exige um token, o cliente deve enviá-lo em cada chamada relevante.
Isso não significa que o servidor não possa armazenar dados. Ele continuará usando bancos, caches e arquivos. A regra significa que o processamento de uma solicitação não deve depender de uma conversa de sessão oculta mantida exclusivamente pelo servidor.
Principais métodos HTTP
A RFC 9110 define a semântica dos métodos e códigos do protocolo HTTP. Respeitar essa semântica torna a integração mais previsível.
| Método | Finalidade | Exemplo |
|---|---|---|
| GET | Consultar recursos | GET /api/produtos/10 |
| POST | Criar um recurso | POST /api/produtos |
| PUT | Substituir um recurso | PUT /api/produtos/10 |
| PATCH | Alterar parte de um recurso | PATCH /api/produtos/10 |
| DELETE | Excluir um recurso | DELETE /api/produtos/10 |
GET
GET solicita uma representação de um recurso e não deve modificar informações no servidor. Uma listagem pode aceitar filtros e paginação: GET /api/produtos?categoria=informatica&pagina=2&tamanho=20. O método é considerado seguro e idempotente.
POST
POST geralmente cria um recurso subordinado à coleção indicada pela URL. Ao criar o registro, o servidor normalmente responde com 201 Created e pode incluir o cabeçalho Location, apontando para a URL do novo recurso.
POST /api/produtos
Content-Type: application/json
{
"nome": "Monitor 27 polegadas",
"preco": 1499.90
}
PUT, PATCH e DELETE
PUT é usado para substituir a representação completa de um recurso. PATCH representa uma alteração parcial. DELETE solicita sua remoção. Em sistemas sujeitos a auditoria, a exclusão pode ser lógica, mantendo o registro armazenado e marcando-o como inativo.
Códigos de status HTTP
O código de status informa o resultado da solicitação. Respostas 2xx indicam sucesso; 3xx, redirecionamento; 4xx, problemas associados à requisição do cliente; e 5xx, falhas do servidor.
| Código | Significado | Uso comum |
|---|---|---|
| 200 | OK | Consulta ou atualização bem-sucedida |
| 201 | Created | Recurso criado |
| 204 | No Content | Operação concluída sem conteúdo |
| 400 | Bad Request | Dados ou formato inválidos |
| 401 | Unauthorized | Autenticação ausente ou inválida |
| 403 | Forbidden | Usuário sem permissão |
| 404 | Not Found | Recurso inexistente |
| 409 | Conflict | Conflito com o estado atual |
| 500 | Internal Server Error | Erro inesperado do servidor |
Não devolva 200 OK para toda situação e coloque o erro somente no JSON. Isso prejudica consumidores, ferramentas de monitoramento, proxies e bibliotecas HTTP.
Planejando nossa API de produtos
| Método | Rota | Resultado |
|---|---|---|
| GET | /api/produtos | Lista todos os produtos |
| GET | /api/produtos/{id} | Retorna um produto |
| POST | /api/produtos | Cadastra um produto |
| PUT | /api/produtos/{id} | Atualiza um produto |
| DELETE | /api/produtos/{id} | Exclui um produto |
Para manter o exemplo concentrado nos fundamentos, os registros ficarão em memória. Em uma aplicação real, essa coleção pode ser substituída por SQL Server, PostgreSQL ou outro mecanismo de persistência.
Como criar uma API REST com ASP.NET Core
1. Verifique e prepare o ambiente
Para criar uma API REST com ASP.NET Core, instale uma versão suportada do SDK do .NET e execute dotnet --version.
2. Crie o projeto
dotnet new webapi --use-controllers -n LojaApi
cd LojaApi
3. Configure o arquivo Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();AddControllers() registra os serviços necessários. MapControllers() conecta as rotas definidas nos controladores ao pipeline da aplicação.
4. Crie o modelo Produto
namespace LojaApi.Models;
public class Produto
{
public int Id { get; set; }
public string Nome { get; set; } = string.Empty;
public decimal Preco { get; set; }
}
5. Crie um DTO com validações
using System.ComponentModel.DataAnnotations;
namespace LojaApi.Dtos;
public class CriarProdutoDto
{
[Required]
[StringLength(120, MinimumLength = 3)]
public string Nome { get; set; } = string.Empty;
[Range(0.01, 999999.99)]
public decimal Preco { get; set; }
}DTO significa Data Transfer Object. Ele controla os dados aceitos e impede que propriedades internas sejam alteradas indevidamente pelo cliente.
6. Implemente o controlador
using LojaApi.Dtos;
using LojaApi.Models;
using Microsoft.AspNetCore.Mvc;
namespace LojaApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ProdutosController : ControllerBase
{
private static readonly List<Produto> Produtos =
[
new Produto { Id = 1, Nome = "Mouse sem fio", Preco = 129.90m },
new Produto { Id = 2, Nome = "Teclado mecânico", Preco = 299.90m }
];
[HttpGet]
public ActionResult<IEnumerable<Produto>> Listar()
=> Ok(Produtos);
[HttpGet("{id:int}")]
public ActionResult<Produto> ObterPorId(int id)
{
var produto = Produtos.FirstOrDefault(p => p.Id == id);
return produto is null ? NotFound() : Ok(produto);
}
[HttpPost]
public ActionResult<Produto> Criar(CriarProdutoDto dto)
{
var produto = new Produto
{
Id = Produtos.Count == 0 ? 1 : Produtos.Max(p => p.Id) + 1,
Nome = dto.Nome,
Preco = dto.Preco
};
Produtos.Add(produto);
return CreatedAtAction(nameof(ObterPorId), new { id = produto.Id }, produto);
}
[HttpPut("{id:int}")]
public IActionResult Atualizar(int id, CriarProdutoDto dto)
{
var produto = Produtos.FirstOrDefault(p => p.Id == id);
if (produto is null) return NotFound();
produto.Nome = dto.Nome;
produto.Preco = dto.Preco;
return NoContent();
}
[HttpDelete("{id:int}")]
public IActionResult Excluir(int id)
{
var produto = Produtos.FirstOrDefault(p => p.Id == id);
if (produto is null) return NotFound();
Produtos.Remove(produto);
return NoContent();
}
}O atributo [ApiController] ativa comportamentos úteis, incluindo respostas automáticas para determinados erros de validação. CreatedAtAction() gera uma resposta de criação e aponta para a ação que recupera o novo registro.
7. Execute o projeto
dotnet runCopie o endereço local exibido no terminal. Para aprofundar a implementação.
Como testar a API REST
Crie um arquivo chamado LojaApi.http e ajuste a URL para o endereço exibido durante a execução:
@baseUrl = https://localhost:7001
GET {{baseUrl}}/api/produtos
Accept: application/json
###
POST {{baseUrl}}/api/produtos
Content-Type: application/json
{
"nome": "Webcam Full HD",
"preco": 249.90
}
###
PUT {{baseUrl}}/api/produtos/1
Content-Type: application/json
{
"nome": "Mouse sem fio ergonômico",
"preco": 159.90
}
###
DELETE {{baseUrl}}/api/produtos/1Verifique corpo, cabeçalhos, tempo de resposta e código de status. Uma resposta visualmente correta com status inadequado ainda representa um contrato defeituoso.
Como consumir uma API REST com JavaScript
A Fetch API oferece uma interface JavaScript para enviar requisições HTTP e processar respostas.
async function carregarProdutos() {
const resposta = await fetch("https://localhost:7001/api/produtos");
if (!resposta.ok) {
throw new Error(`Falha HTTP: ${resposta.status}`);
}
const produtos = await resposta.json();
console.table(produtos);
}
carregarProdutos().catch(console.error);É necessário verificar resposta.ok, porque o fetch() não rejeita automaticamente a Promise apenas porque o servidor respondeu com 404 ou 500.
Cadastro com POST
async function cadastrarProduto(produto) {
const resposta = await fetch("https://localhost:7001/api/produtos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(produto)
});
if (!resposta.ok) {
const detalhe = await resposta.text();
throw new Error(`Erro ${resposta.status}: ${detalhe}`);
}
return await resposta.json();
}
cadastrarProduto({ nome: "Headset USB", preco: 189.90 })
.then(console.log)
.catch(console.error);
Validação e tratamento de erros
Uma API REST confiável nunca considera válidos todos os dados recebidos. O cliente pode estar desatualizado, conter defeitos ou agir maliciosamente. Por isso, a validação definitiva deve acontecer no servidor.
- Valide campos obrigatórios e tamanhos permitidos.
- Confira faixas numéricas e formatos de datas.
- Verifique a existência de entidades relacionadas.
- Trate duplicidades e conflitos de concorrência.
- Confirme as permissões do usuário.
Não exponha rastreamentos de pilha, comandos SQL, credenciais ou detalhes internos. Registre as informações técnicas em logs protegidos e devolva uma mensagem segura com um identificador de correlação.
Para padronizar erros, considere o formato Problem Details da RFC 9457.
Segurança em APIs REST
Use HTTPS
HTTPS protege os dados em trânsito contra leitura e alteração. Tokens, senhas ou dados pessoais nunca devem circular em HTTP aberto.
Diferencie autenticação de autorização
Autenticação identifica quem está fazendo a solicitação. Autorização determina se essa identidade pode executar a operação. Um token válido não deve conceder acesso automático a todos os recursos.
Authorization: Bearer TOKEN_DE_ACESSO
Aplique o menor privilégio
Cada usuário ou sistema deve possuir somente as permissões necessárias. A autorização também deve considerar o recurso específico: alguém pode consultar os próprios pedidos sem poder acessar pedidos de outra conta.
Imponha limites
Limitação de requisições, tamanho máximo do corpo, tempo limite e paginação ajudam a proteger a disponibilidade da aplicação.
Boas práticas para uma API REST profissional
Mantenha contratos consistentes
Escolha um padrão de nomes e aplique-o em toda a aplicação. Defina também formatos de data, valores monetários, paginação e erros.
Utilize DTOs
DTOs reduzem o acoplamento entre banco e consumidor e ajudam a evitar over-posting, situação em que o cliente envia propriedades que não deveria controlar.
Implemente paginação
Uma rota que devolve milhares de registros prejudica cliente, rede e servidor. Prefira parâmetros como ?pagina=1&tamanho=20 e estabeleça um limite máximo.
Entenda a idempotência
Uma operação é idempotente quando repeti-la produz o mesmo efeito pretendido no estado do servidor. Em operações sensíveis, como pagamentos ou liberação de benefícios, use uma chave de idempotência para impedir processamento duplicado após uma tentativa repetida.
Planeje a concorrência
Dois usuários podem alterar o mesmo recurso quase simultaneamente. Versionamento de registro, ETag e atualizações condicionais ajudam a detectar conflitos. No banco, use transações e constraints, pois uma verificação isolada antes da gravação não elimina condições de corrida.
Versione com critério
Mudanças que removem campos, alteram tipos ou modificam significados podem quebrar consumidores. Um padrão comum é publicar rotas como /api/v1/produtos e /api/v2/produtos, acompanhado de uma política de migração e descontinuação.
Documente com OpenAPI
A OpenAPI Specification descreve APIs HTTP em um formato independente de linguagem. Documente operações, parâmetros, esquemas, respostas, autenticação, exemplos e limitações.
Registre e monitore
Acompanhe taxa de erros, latência, volume e disponibilidade. Utilize identificadores de correlação para rastrear solicitações, mas nunca registre senhas, tokens ou dados pessoais desnecessários.
Como testar uma API REST corretamente
Testes unitários avaliam regras isoladas. Testes de integração verificam a interação entre rotas, serviços, persistência e serialização. Testes de contrato confirmam que o formato esperado pelos consumidores continua válido.
Inclua ainda testes de segurança e carga. Eles ajudam a avaliar autorização, entradas malformadas, exposição de informações, concorrência e comportamento sob picos de tráfego. Integre os testes ao pipeline para impedir que alterações incompatíveis cheguem à produção.
Publicação e cuidados em produção
Separe configurações por ambiente. URLs, segredos e strings de conexão não devem ficar fixados no código-fonte. Use variáveis de ambiente ou um gerenciador seguro de segredos.
- Controle as migrações do banco de dados.
- Implemente verificações de integridade.
- Defina uma política de rollback.
- Centralize logs e configure alertas úteis.
- Estabeleça limites de recursos e cópias de segurança.
- Planeje falhas de serviços externos.
Erros comuns ao criar APIs
Um erro frequente é colocar toda a lógica dentro do controlador. Ele deve coordenar entrada e saída; regras de negócio e acesso a dados devem ficar em componentes próprios. Também é incorreto confiar somente na interface do usuário para validar informações, pois qualquer consumidor pode chamar o endpoint diretamente.
- Não retorne dados sensíveis em mensagens de erro.
- Não crie rotas inconsistentes.
- Não ignore códigos de status HTTP.
- Não permita listagens sem limite.
- Não exponha entidades persistidas desnecessariamente.
- Não reprocesse operações críticas sem idempotência.
- Não publique endpoints sem documentação e monitoramento.

Conclusão
Criar e consumir uma API REST envolve mais do que enviar JSON por HTTP. É necessário modelar recursos, escolher métodos adequados, retornar códigos coerentes, validar entradas e proteger operações. Neste guia, construímos uma API de produtos com endpoints para consulta, cadastro, atualização e exclusão, além de consumi-la com JavaScript. O próximo passo é adicionar banco de dados, camada de serviços, autenticação, testes automatizados e observabilidade. Ao evoluir cada parte sem abandonar a consistência do contrato, você transforma um exemplo didático em uma integração segura e preparada para produção.

