Construir uma API que move dinheiro ou dados sensíveis exige uma mentalidade paranóica. Diferente de uma aplicação tradicional onde um erro gera um layout quebrado, numa API financeira um erro ou brecha gera perda de capital irrecuperável.
Uma segurança robusta é baseada em defesa em profundidade (Defense in Depth). Se uma camada falhar, a próxima deve segurar a anomalia.
1. Idempotência: O Escudo Contra Duplicidade
O problema mais clássico em APIs de pagamento é o timeout de rede. O cliente envia a requisição de pagamento, o servidor processa e debita o saldo, mas a resposta de sucesso se perde na rede. O cliente, achando que falhou, tenta novamente. Resultado: cobrança duplicada.
A solução é o uso rigoroso de Chaves de Idempotência (Idempotency Keys).
POST /api/v1/payments
Authorization: Bearer <token>
Idempotency-Key: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
{
"amount": 5000,
"currency": "BRL",
"recipient_id": "usr_123"
}
Como o servidor deve processar:
- Recebe a requisição e verifica se a
Idempotency-Keyjá existe num banco de dados de alta performance (ex: Redis). - Se não existir: Cria um registro marcando a chave como "em processamento". Processa o pagamento, salva o resultado associado à chave e retorna.
- Se existir e estiver pronta: Retorna exatamente o mesmo payload de resposta da primeira vez, sem tocar na regra de negócios.
- Se existir e estiver em processamento: Retorna um erro
409 Conflict, avisando o cliente para aguardar.
2. Rate Limiting com Token Bucket (Redis)
Ataques de força bruta, Carding (testar milhares de cartões roubados num endpoint) ou clientes mal programados podem derrubar a sua infraestrutura. O Rate Limit não deve ser uma simples trava no Nginx, mas algo inteligente.
A estratégia de Token Bucket no Redis é excelente porque permite pequenos picos (bursts) mas restringe o fluxo contínuo.
// Exemplo em Node.js com Redis
async function checkRateLimit(userId) {
const limit = 5; // 5 reqs
const window = 10; // por 10 segundos
const key = `ratelimit:tx:${userId}`;
const currentCount = await redis.incr(key);
if (currentCount === 1) {
await redis.expire(key, window);
}
if (currentCount > limit) {
throw new Error('Too Many Requests');
}
}
Em APIs financeiras, aplique o Rate Limit de forma granular: bloqueie por IP, por UserID e, crucialmente, por Device Fingerprint, para evitar ataques distribuídos.
3. Assinatura de Webhooks (HMAC)
Quando gateways como Stripe ou Pagar.me notificam a sua API de que um Pix foi pago, como você garante que aquele payload veio realmente do gateway e não de um hacker tentando falsificar a transação?
A resposta é HMAC (Hash-based Message Authentication Code).
O gateway assina o payload usando uma chave secreta que só você e ele conhecem. O resultado vai no header (ex: Stripe-Signature).
No seu servidor, você pega o raw payload recebido, aplica a mesma chave secreta e compara os hashes. Se não baterem perfeitamente, a requisição é descartada instantaneamente com um 401 Unauthorized.
Conclusão
APIs financeiras não perdoam amadorismo. Idempotência garante a integridade lógica, Rate Limiting garante a resiliência operacional, e HMAC assegura a autenticidade da comunicação ponta-a-ponta. Construa essas defesas na infraestrutura (como middlewares) para que a equipe de produto foque na regra de negócio sem medo de expor a empresa.