Pular para o conteúdo principal

API — Visão Geral

Esta página descreve os contratos, convenções e comportamentos comuns de toda a camada de API do sistema LJ Velas & Aromas.


1. Base URLs

AmbienteURLObservação
Localhttp://localhost:3000Next.js dev server (npm run dev)
Staginghttps://beige-cassowary-235127.hostingersite.comSubdomínio Hostinger — deploy automático via CI
Produçãohttps://ljvelasearomas.com.brDomínio próprio — deploy manual controlado

Todas as rotas de API ficam sob o prefixo /api/ em qualquer ambiente.


2. Segmentos de API

PrefixoAutenticaçãoPropósitoCORS
/api/auth/*Pública (rate limited)Login, logout, refresh, registroSame-origin
/api/products/*PúblicaListagem e detalhe de produtosAberto (*)
/api/categoriesPúblicaListagem de categoriasAberto (*)
/api/shipping/*PúblicaCálculo de frete (Correios / Melhor Envio)Aberto (*)
/api/coupons/*PúblicaValidação de cupons de descontoAberto (*)
/api/orders/*JWT cookie — CUSTOMERCriação e consulta de pedidos do usuárioSame-origin
/api/user/*JWT cookie — CUSTOMERPerfil, endereços e histórico do clienteSame-origin
/api/payments/*JWT cookie — CUSTOMERInitiação e status de pagamentos (Pagar.me)Same-origin
/api/admin/*JWT cookie — ADMINPainel administrativo (CRUD completo)Same-origin
/api/v1/*Bearer API KeyAPI pública versionada para integrações externasConfigurável
/api/webhooks/stockBearer API Key (stock:write)Atualização de estoque via integração ERPSame-origin

Same-origin significa que apenas requisições vindas do próprio domínio são aceitas (sem header Access-Control-Allow-Origin aberto).


3. Formato de Resposta

Todas as respostas utilizam Content-Type: application/json.

Sucesso — o corpo retorna diretamente os dados da operação:

// GET /api/products/42
{
"id": 42,
"name": "Vela Aromática Lavanda",
"price": 3990,
"stock": 14
}

Erro — estrutura padronizada com campo obrigatório error e campo opcional details:

// 422 Unprocessable Entity
{
"error": "Dados inválidos",
"details": {
"name": "Campo obrigatório",
"price": "Deve ser maior que zero"
}
}

Preços são sempre representados em centavos (inteiro), ex.: R$ 39,903990.


4. Paginação

Rotas que retornam listas aceitam os query params:

ParâmetroTipoPadrãoDescrição
pageinteiro1Número da página (base 1)
limitinteiro20Itens por página (máximo: 100)

A resposta de listas inclui um objeto pagination no nível raiz:

{
"data": [ /* itens */ ],
"pagination": {
"total": 87,
"page": 2,
"limit": 20,
"totalPages": 5
}
}

5. Códigos de Status HTTP

StatusNomeQuando ocorre
200OKRequisição bem-sucedida (GET, PATCH, DELETE)
201CreatedRecurso criado com sucesso (POST)
400Bad RequestCorpo ou query params malformados / tipo incorreto
401UnauthorizedToken ausente, expirado ou inválido
403ForbiddenToken válido, mas papel insuficiente (ex.: CUSTOMER acessando /api/admin)
404Not FoundRecurso não encontrado pelo ID informado
409ConflictViolação de unicidade (ex.: e-mail já cadastrado, SKU duplicado)
422Unprocessable EntityDados semanticamente inválidos (validação Zod falhou)
429Too Many RequestsLimite de taxa atingido (ver seção Rate Limiting)
500Internal Server ErrorErro não tratado no servidor — verifique os logs

6. Rate Limiting

O rate limiting está ativo somente na rota /api/auth/login para mitigar ataques de força-bruta.

ConfiguraçãoValor
Janela15 minutos
Limite10 tentativas por IP
ArmazenamentoIn-memory (reinicia com o processo)

Quando o limite é atingido, a resposta 429 inclui o header:

Retry-After: 847 // segundos restantes até o reset da janela

7. Uploads de Arquivos

Imagens de produtos e banners são enviadas via POST /api/admin/upload.

CampoValor
Content-Typemultipart/form-data
Campo do arquivofile
Formatos aceitosimage/jpeg, image/png, image/webp, image/gif
Tamanho máximo5 MB por arquivo
Resposta de sucesso{ "url": "https://..." }

Exemplo de requisição com curl:

curl -X POST https://ljvelasearomas.com.br/api/admin/upload \
-H "Cookie: token=<jwt>" \
-F "file=@foto-produto.webp"

As imagens são armazenadas no diretório público do servidor Hostinger e servidas diretamente via URL.


8. Webhooks

8.1 Outbound — Notificações do Sistema

O sistema pode disparar webhooks para URLs externas configuradas no painel admin ao ocorrerem eventos como order.created, order.paid e order.shipped.

Assinatura (HMAC-SHA256):

Cada requisição carrega o header X-Webhook-Signature com a assinatura HMAC-SHA256 do corpo da requisição, usando a chave secreta configurada:

X-Webhook-Signature: sha256=a3f9c...

Para validar no receptor:

const expectedSig = "sha256=" + createHmac("sha256", WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");

if (sig !== expectedSig) return res.status(401).end();

8.2 Inbound — Atualização de Estoque

PropriedadeValor
RotaPOST /api/webhooks/stock
AutenticaçãoAuthorization: Bearer <api-key> com escopo stock:write
Corpo esperado{ "sku": string, "quantity": number }
Resposta{ "updated": true } ou erro padronizado

9. Versionamento

A API possui duas camadas distintas:

CamadaPrefixoPropósito
Interna/api/Rotas Next.js App Router (app/api/). Consumidas exclusivamente pelo frontend da loja. Podem mudar entre deploys sem aviso.
Pública v1/api/v1/API versionada e estável para integrações externas (ERPs, marketplaces, automações). Breaking changes só em nova versão (/api/v2/).

Regra prática: se você está construindo uma integração externa, use sempre /api/v1/. As rotas /api/ sem versão são contratos internos e não possuem garantia de estabilidade.