SaqSaq Docs
Boas práticas

Segurança

A integração Pix mexe com dinheiro real. Cada camada deve ter sua linha de defesa.

Armazenamento do token

Bearer token é a única credencial da Saq. Quem tem, movimenta o saldo.

Onde guardarOK?
Google Secret ManagerSim
AWS Secrets ManagerSim
HashiCorp VaultSim
Variável de ambiente no CISim
.env em produçãoNão
Hardcoded no códigoNão
localStorage / sessionStorageNão
Front-end (Web, Mobile)Nunca

Nunca exponha o token no front-end. Toda chamada Saq deve passar pelo seu backend, que injeta o Authorization no servidor.

Mascaramento em logs

Configure seu logger para mascarar o header Authorization e campos sensíveis do payload (payerDocument, pixKey, etc).

import pino from 'pino';

const logger = pino({
  redact: {
    paths: [
      'req.headers.authorization',
      'res.headers.authorization',
      '*.payerDocument',
      '*.pixKey',
    ],
    censor: '[REDACTED]',
  },
});
import logging, re

class RedactFilter(logging.Filter):
    def filter(self, record):
        if isinstance(record.msg, str):
            record.msg = re.sub(r'Bearer\s+[A-Za-z0-9._\-]+', 'Bearer [REDACTED]', record.msg)
        return True

logging.getLogger().addFilter(RedactFilter())
logger, _ := zap.NewProduction()
defer logger.Sync()

logger.Info("saq call",
    zap.String("url", url),
    zap.String("authorization", "[REDACTED]"),
)

Rotação do token

Quando rotacionarAção
Alguém com acesso deixa a empresaImediato
Suspeita de vazamento (commit acidental, log público)Imediato + auditoria
Rotação preventivaTrimestral ou semestral
Após teste de pen-testImediato se foi exposto durante o teste

Solicite a rotação ao suporte da Saq. Tenha rollover planejado (dois tokens ativos por uma janela) para não derrubar produção.

Proteção do endpoint de webhook

Aceite callbacks apenas do IP oficial da Saq. Solicite o IP atual ao suporte.

location /webhooks/saq {
  allow 35.199.0.0/16;
  deny all;
  proxy_pass http://backend;
}

Crie uma WAF rule: (http.request.uri.path eq "/webhooks/saq" and ip.src ne <IP_SAQ>) → Block.

const SAQ_IPS = (process.env.SAQ_WEBHOOK_IPS ?? '').split(',');

app.post('/webhooks/saq', (req, res, next) => {
  const ip = req.ip;
  if (!SAQ_IPS.includes(ip)) return res.status(403).end();
  next();
});

Validação DICT antes de pagar

Em saques Pix por chave, valide o titular via DICT antes de transferir. Detecta troca de banco/CPF e evita pagar para destinatário errado.

async function safeWithdraw(pixKey: string, pixType: string, expectedName: string, amount: number) {
  const url = new URL('https://api.saq.processamento.com/v1/pix/key');
  url.searchParams.set('key', pixKey);

  const dict = await fetch(url, {
    headers: {
      Authorization: `Bearer ${process.env.SAQ_TOKEN}`,
      'Content-Type': 'application/json',
    },
  }).then(r => r.json());

  if (dict.name?.toLowerCase().trim() !== expectedName.toLowerCase().trim()) {
    throw new Error(`Titular divergente: esperado ${expectedName}, encontrado ${dict.name}`);
  }

  return createWithdraw({ pixKey, pixType, amount });
}

Detalhes em Consulta DICT.

2FA em operações sensíveis

Considere 2FA adicional na sua aplicação (não na Saq) antes de:

  • Saque acima de um limite alto.
  • Cadastro/alteração de chave Pix de saque.
  • Login admin com permissão de movimentar saldo.

A Saq já valida no backend, mas 2FA aplicacional reduz o blast radius de uma sessão comprometida. Detalhes em 2FA.

Princípio do menor privilégio

SetupRecomendação
Token único pra prod + devSepare: token de sandbox vs token de prod.
Mesmo token compartilhado entre serviçosUm token por serviço/equipe (pra auditar uso).
Devs com acesso ao token de prodSó infra/SRE deveria ter, devs usam sandbox.

Armadilhas comuns

ArmadilhaSintoma
Token em .env versionadoVaza no primeiro git push --force errado
Logger imprime header AuthorizationToken vaza em qualquer captura de log
Webhook aberto para qualquer IPPayloads forjados podem ser aceitos
Pagar sem DICT em saque por chavePode pagar destinatário errado
Mesmo token em sandbox e produçãoErro de ambiente vira incidente em prod

On this page