Conceitos
Autenticação e chaves
Toda requisição à API da Pagnovo precisa ser autenticada usando HTTP Basic Authentication com a sua secret key. Essa chave equivale a uma senha master da sua conta — qualquer pessoa que tenha acesso a ela pode movimentar dinheiro em seu nome.
Regras operacionais básicas:
- Guarde a chave em variável de ambiente ou cofre de secrets. Nunca no código-fonte.
- Nunca a exponha em bundles de frontend, apps mobile, código de navegador ou logs públicos.
- Rotacione a chave sempre que um desenvolvedor sair do time ou houver suspeita de vazamento.
- Para saques (cash-out), habilite o IP allowlist — veja a seção abaixo.
Se quiser limitar o raio de impacto, crie chaves separadas por contexto: uma chave somente-leitura para o back office, uma chave de escrita para cash-in, uma chave crítica para cash-out com allowlist de IPs restrito. O princípio do menor privilégio impede que um único vazamento esvazie seu saldo.
Montando o header Authorization
O valor do header é o base64 de qualquer-coisa:SUA_SECRET_KEY. O servidor faz split no último dois-pontos e usa apenas o que vem depois — então o prefixo pode ser qualquer coisa. Recomendamos secret: por clareza.
Authorization: Basic {base64(secret:SUA_SECRET_KEY)}
cURL
SECRET="sua_secret_key_aqui"
TOKEN=$(echo -n "secret:$SECRET" | base64)
curl -X GET "https://api.pagnovo.com/accounts/balance" \
-H "Authorization: Basic $TOKEN"
Node.js / TypeScript
const secret = process.env.PAGNOVO_SECRET_KEY!;
const token = Buffer.from(`secret:${secret}`).toString("base64");
const res = await fetch(`https://api.pagnovo.com/accounts/balance`, {
headers: { Authorization: `Basic ${token}` },
});
Python
import base64, os, requests
secret = os.environ["PAGNOVO_SECRET_KEY"]
token = base64.b64encode(f"secret:{secret}".encode()).decode()
res = requests.get(
f"https://api.pagnovo.com/accounts/balance",
headers={"Authorization": f"Basic {token}"},
)
Permissões da chave
Cada chave carrega um conjunto fixo de permissões definido no momento da criação. Se uma chave tentar acessar um endpoint que exige uma permissão que ela não tem, a resposta é 403 Forbidden — não 401.
As permissões são organizadas por área. Marque apenas o que a chave precisa.
Pagamentos (PIX / cartão):
- viewBalance — consultar saldos via
GET /accounts/balance - createTransaction — criar transações de entrada (PIX, cartão de crédito)
- viewTransaction — consultar transações existentes
- createRefund — estornar transações já aprovadas
- createWithdraw — solicitar saques (por chave PIX ou QR Code)
- viewWithdraw — consultar saques existentes
- createAnticipation / viewAnticipation — solicitar e consultar antecipação de recebíveis
- viewPixKeyDetails — consultar dados da chave PIX cadastrada
Disputas:
- viewMeds / responseMeds — consultar e responder infrações PIX (MED)
- viewChargebacks / responseChargebacks — consultar e responder disputas de cartão
Recursos V2 (rotas /v2/*): cada recurso tem um par view (leitura — métodos GET) e manage (escrita — POST/PATCH/PUT/DELETE). Sem o scope correspondente, a rota responde 403 Forbidden.
| Recurso | Scope de leitura | Scope de escrita |
|---|---|---|
/v2/products | viewProduct | manageProduct |
/v2/offers | viewOffer | manageOffer |
/v2/quick-links | viewQuickLink | manageQuickLink |
/v2/customers | viewCustomer | manageCustomer |
/v2/subscriptions | viewSubscription | manageSubscription |
/v2/coupons | viewCoupon | manageCoupon |
/v2/invoices | viewInvoice | manageInvoice |
/v2/webhooks | viewWebhook | manageWebhook |
Separação recomendada para produção:
| Contexto | Permissões |
|---|---|
| Backend do checkout | createTransaction |
| Jobs de conciliação | viewBalance, viewTransaction, viewWithdraw |
| Ferramentas de estorno | createRefund, viewTransaction |
| Sistema de pagamentos | createWithdraw, viewWithdraw (com IP allowlist) |
| Integração de catálogo/cobrança | viewProduct, manageOffer, viewInvoice, manageSubscription, … (só o que usar) |
Chaves com permissões amplas são causa comum de incidentes. Vazamento de uma chave somente-leitura é chato. Vazamento de uma chave de cash-out sem allowlist é uma transferência direta pra carteira de outra pessoa.
Propagação de mudanças (cache)
Por performance, validamos as chaves de API com um cache. Isso afeta o timing de algumas mudanças:
- Criar uma chave nova: funciona já na primeira requisição — sem espera.
- Revogar uma chave ou alterar permissões/scopes: limpamos o cache automaticamente, e a mudança costuma valer em até ~1 minuto (há uma camada de cache local de curta duração que não dá pra limpar instantaneamente).
Isso vale também pra mudanças feitas pela nossa equipe na sua conta (bloqueios, módulos): propagam no mesmo intervalo de ~1 minuto.
Na prática: se você acabou de revogar uma chave ou mudar scopes e a API ainda responde com o comportamento antigo, aguarde cerca de 1 minuto e tente de novo. Não é necessário recriar a chave. Para segurança imediata em caso de vazamento, revogue a chave — a janela de exposição é de no máximo ~1 minuto, não horas.
IP allowlist (cash-out e estorno)
As rotas de cash-out (createWithdraw) e estorno (createRefund) respeitam um allowlist de IPs. Requisições vindas de qualquer IP fora da lista são rejeitadas com 400 Bad Request — IP unauthorized, mesmo que a chave em si seja válida e tenha a permissão.
Você mesmo gerencia esses IPs no dashboard, em Configurações → IPs whitelist — adicione ou remova endereços IPv4/IPv6 a qualquer momento (não precisa mais abrir chamado pro suporte).
Lista vazia = sem restrição. Se você não cadastrar nenhum IP, cash-out e estorno aceitam requisições de qualquer origem (desde que a chave tenha a permissão). Cadastre os IPs do seu servidor para travar. Recomendamos fortemente travar em produção.
Por que isso importa: uma chave de cash-out vazada sem allowlist significa que um atacante pode esvaziar seu saldo de uma cafeteria em cinco minutos. Com allowlist, ele ainda precisaria comprometer uma máquina em um IP autorizado — problema muito mais difícil.
Como o IP é detectado:
- O servidor lê o header
X-Forwarded-Fore confia na cadeia de proxies. - Se você usa CDN, load balancer ou API gateway, certifique-se de que o IP real do cliente é encaminhado corretamente.
- Para egress estático, roteie seu tráfego de saída por um NAT gateway com Elastic IP fixo e adicione esse IP no allowlist.
- Para ambientes dinâmicos (serverless, clusters com autoscaling), prefira um conjunto pequeno de IPs de egress fixos em vez de liberar uma faixa inteira.
Respostas de erro
401 Unauthorized — a chave está ausente, malformada ou foi revogada:
{
"statusCode": 401,
"message": "Unauthorized"
}
403 Forbidden — a chave é válida, mas não tem permissão para esse endpoint:
{
"statusCode": 403,
"message": "You do not have permission to access this resource"
}
400 Bad Request — IP unauthorized — a chave é válida e tem as permissões certas, mas a requisição veio de um IP que não está no allowlist:
{
"statusCode": 400,
"message": "IP unauthorized"
}
Quando você receber um desses em produção, capture o x-trace-id da resposta — veja a próxima seção para entender por quê.