Pular para o conteúdo principal

Políticas e Regras

As políticas permitem configurar regras preventivas para operações PIX. Elas são configuradas no painel (Backoffice) e avaliadas automaticamente pela API. Tudo que a tela oferece é avaliado em runtime: PIX Out, PIX In, QR Code, chaves, estorno, horário de operação e limites de DICT.

Hierarquia de Configuração

As políticas têm dois níveis:

Tenant (base) -> Account (sobrescreve o tenant)

A resolução é por seção: se a conta define pixOut, a seção pixOut da conta é usada inteira, e a do tenant é ignorada. Seções não definidas na conta são herdadas do tenant. Uma seção que não existe em nenhum dos dois níveis simplesmente não é avaliada — não há um nível "default" por trás com valores implícitos.

A única exceção são os limites de DICT, que têm defaults globais da plataforma quando a policy não os define — ver Limites de DICT Lookup.

Regras de PIX Out

As regras são avaliadas nesta ordem:

OrdemRegraruleDescrição
1Kill SwitchpixOutDisabledenabled: false recusa toda saída. É absoluto — vence inclusive a whitelist
2WhitelistDocumento do destinatário na whitelist: permite e pula todas as regras abaixo
3BlacklistcpfCnpjBlacklistRecusa se o documento do destinatário está na blacklist
4Mesma TitularidadesameOwnershipOnlyPermite apenas transferências para o CPF/CNPJ do titular da conta
5Horário de OperaçãooperatingHoursRecusa fora da janela configurada
6Limite por TransaçãomaxAmountValor máximo por transferência
7Limite NoturnonightMaxAmountValor máximo entre 20:00 e 06:00 (BRT)
8Tipo de PessoaallowedPersonTypesRestringe o destinatário a PF ou PJ (pelo tamanho do documento)

Ao contrário da whitelist, que curto-circuita, as demais regras são todas avaliadas: uma transação pode violar mais de uma, e o violations da resposta traz todas.

Duas fases de avaliação

O documento do destinatário nem sempre existe no momento do POST:

  • No POST (borda): kill switch, horário e limites de valor. As regras de documento também, quando o modo é BANK_ACCOUNT, o único que traz documentNumber no corpo.
  • Depois de resolver o destinatário: nos modos KEY e QRCODE, o documento só aparece quando a chave é consultada no DICT ou o BR Code é decodificado. As regras de documento são avaliadas nesse ponto, antes de o pagamento ser submetido ao parceiro. O mesmo vale para os limites de valor quando um QR Code é pago sem amount no corpo: o montante vem do BR Code, e o limite é aplicado assim que ele é conhecido.

Na prática isso significa que uma violação de blacklist no modo chave não devolve 422 na resposta do POST: o pagamento é aceito, o paymentId é criado, e o desfecho é FAILED com errorCode: policy_denied. O webhook policy.violation e o pix.out.failed avisam do resultado.

Resposta a uma violação (fase de POST)

HTTP/1.1 422 Unprocessable Entity
{
"errorCode": "policy_denied",
"message": "amount R$ 5000.00 exceeds the per-transaction limit of R$ 1000.00",
"violations": [
{ "rule": "maxAmount", "message": "amount R$ 5000.00 exceeds the per-transaction limit of R$ 1000.00" }
]
}

Não é 403 (que significa falta de permissão) nem 400 (o payload é válido): a requisição está correta e foi recusada por uma regra que o próprio tenant configurou.

Modo monitor (NOTIFY_ONLY)

O campo violationAction da seção pixOut define o que fazer com as violações:

ValorEfeito
BLOCK (padrão)Recusa o pagamento
NOTIFY_ONLYRegistra a violação e envia o webhook policy.violation, mas o pagamento segue

NOTIFY_ONLY é o ensaio antes do bloqueio: salve a regra em modo monitor, acompanhe os avisos por alguns dias no painel e no webhook, e promova para BLOCK quando estiver convencido de que a regra não pega tráfego legítimo.

Em modo monitor a violação não aparece na timeline da transação — o pagamento seguiu e vai ter o desfecho normal (pix_out.completed). A violação vive no webhook e no painel.

Regras de PIX In

Um PIX recebido não pode ser recusado

O liquidante credita a conta e só depois nos avisa. Quando a política é avaliada, o dinheiro já entrou — não existe momento em que dava para recusar. Por isso a seção não tem kill switch, e a escolha é sobre o que fazer depois: avisar, ou devolver.

OrdemRegraruleDescrição
1WhitelistDocumento do pagador na whitelist: aceita e pula todas as regras abaixo
2Blacklist (documento)pixIn.cpfCnpjBlacklistPagador com documento na blacklist
3Mesma TitularidadepixIn.sameOwnershipOnlyAceita apenas PIX do CPF/CNPJ do titular da conta
4Limite por TransaçãopixIn.maxAmountValor máximo recebido por transação
5Tipo de PessoapixIn.allowedPersonTypesRestringe o pagador a PF ou PJ
6Bancos PermitidospixIn.allowedBankCodesAceita apenas PIX dos bancos listados
7Bancos BloqueadospixIn.blacklistedBankCodesRecusa PIX dos bancos listados

As listas de banco aceitam código COMPE (3 dígitos) ou ISPB (8 dígitos) — o que você tiver em mãos. Quando o webhook do liquidante não identifica o banco do pagador, as regras de banco são puladas em vez de acusar violação. Vale o mesmo para as regras de documento quando o pagador vem sem CPF/CNPJ.

Ações de PIX In

violationActionEfeito
ALLOW_AND_NOTIFY (padrão)Registra a violação e envia policy.violation. O crédito permanece
AUTO_REFUNDAlém de avisar, devolve o valor integral ao pagador

AUTO_REFUND inicia uma devolução PIX comum logo após o crédito, com motivo unauthorized-transaction. Ela aparece no extrato do seu cliente como uma devolução e não tem como ser desfeita — comece com ALLOW_AND_NOTIFY para ver quais regras pegariam antes de devolver dinheiro de verdade.

O webhook pix.in.completed é entregue nos dois casos, e antes do policy.violation: o crédito aconteceu, e esconder isso criaria divergência entre o seu saldo e o nosso. Quando há devolução, ela gera os eventos normais de PIX out (pix.out.completed ou pix.out.failed).

Regras de QR Code

Avaliadas na criação do QR Code (estático e dinâmico), antes de o QR existir no parceiro.

RegraruleDescrição
Criação de estáticoqrCode.canCreateStaticfalse recusa a criação de QR estático
Criação de dinâmicoqrCode.canCreateDynamicfalse recusa a criação de QR dinâmico
Valor mínimoqrCode.minAmountValor mínimo do QR
Valor máximoqrCode.maxAmountValor máximo do QR

Os limites de valor só se aplicam a QR criado com valor. Um QR estático aberto, em que o pagador digita o valor no app do banco dele, não tem montante para comparar na criação — as duas regras de valor são puladas.

Regras de Chaves PIX

Avaliadas na criação de chave (POST /v1/accounts/{accountId}/pix/keys).

RegraruleDescrição
Criaçãokeys.canCreatefalse recusa a criação de novas chaves
Máximo de chaveskeys.maxKeysRecusa quando a conta já tem esse número de chaves

A contagem de chaves é consultada no parceiro no momento da criação. Se essa consulta falhar, a criação segue: indisponibilidade nossa não deve virar violação de política. Chaves que já existem nunca são removidas por uma mudança de política.

Regras de Estorno

Avaliadas nas devoluções que você pede em POST /v1/accounts/{accountId}/pix/out/refund, sejam elas integrais ou parciais.

RegraruleDescrição
Kill switchrefund.disabledenabled: false recusa toda devolução pedida pela API
Valor máximorefund.maxAmountValor máximo por devolução

Devoluções que não são sua escolha ficam fora desta seção: um MED aceito e o AUTO_REFUND da seção PIX In são obrigações, e regra de tenant não sobrepõe obrigação. Pelo mesmo motivo, as regras de documento de PIX Out (blacklist, whitelist, titularidade, tipo de pessoa) não se aplicam a devoluções — o destinatário de uma devolução é quem pagou, não uma escolha sua.

Recusa nas três seções acima

QR Code, chaves e estorno sempre barram: não há modo monitor. As três são operações síncronas que ainda não moveram dinheiro quando a regra é avaliada, então a recusa cabe na resposta — 422 com errorCode: policy_denied, no mesmo formato do PIX Out. Avisar depois de devolver um BR Code, publicar uma chave no DICT ou submeter uma devolução seria avisar sobre fato consumado.

Horário de Operação

Janela em que as saídas são permitidas. Suporta janelas que cruzam a meia-noite (ex.: 22:00-06:00).

CampoDescriçãoExemplo
startHora de início06:00
endHora de fim22:00
timezoneFuso horário (padrão America/Sao_Paulo)America/Sao_Paulo

Uma janela pela metade (só start ou só end) é tratada como ausente e não barra ninguém.

Limites de DICT Lookup

Consultar uma chave PIX tem limites próprios, avaliados a cada consulta. Ao exceder, a resposta é 429 com errorCode: dict_lookup_limit_exceeded, e um webhook policy.violation com phase: "dict_lookup" é enviado.

Nem todo 429 é a sua cota

A mesma rota também responde 429 com errorCode: partner_rate_limited, que é throttling do liquidante sobre o tráfego da CorpX e não tem relação com os limites desta página — nenhum contador da sua conta fechou. Confira o errorCode antes de concluir que a cota acabou.

Contam como consulta as duas formas de perguntar ao DICT quem é o dono de uma chave:

  • A consulta explícitaGET /v1/accounts/{accountId}/pix/key/{pixKey}.
  • O PIX Out no modo KEY (em implantação) — POST /v1/accounts/{accountId}/pix/out, /async e /bigpix. A chave precisa ser resolvida antes de o dinheiro sair, e essa pergunta vai para o mesmo DICT. Ver "Pagamento por chave também consome cota", abaixo.

São três limites de contagem absoluta, todos medidos por conta (ver "Todo limite é por conta", abaixo), e vale o mais restritivo — qualquer um que estoure devolve 429:

LimiteJanelaDefault globalO que protege
maxLookupsPerDaydia-calendário BRT (a partir de 00:00)50Teto absoluto de consultas por dia
maxLookupsPerMinute60s rolantes15Rajada: cabe no teto diário, mas chega tudo de uma vez
maxNotFoundPer5min5 min rolantes10Enumeração de chaves: scan cego gera muito NOT_FOUND antes de o teto diário estourar

Além deles existem os tetos de taxa por janela de tempo, descritos a seguir. Esses valem sempre: quem não declara números próprios herda a linha de base da frota.

maxLookupRatio foi descontinuado

Havia um quarto limite, maxLookupRatio — consultas permitidas por transferência concluída nas últimas 24h. Ele saiu na v2.53.0. Era o mesmo cálculo da taxa de uso da janela de 24h, com resolução pior: uma janela só, sem piso de amostra próprio, dependendo de um piso global de 50 consultas para não travar conta sem transferência. As janelas fazem o mesmo em doze faixas. O campo continua sendo aceito no corpo da policy e é ignorado; o motivo de negação ratio não aparece mais nas respostas 429.

Tetos de taxa por janela de tempo

Os três limites acima respondem quanto e quão rápido. Nenhum responde a pergunta que o balde do DICT de fato mede: quantas consultas você gasta por pagamento que efetiva, e que fração das suas consultas não resolve chave nenhuma. Uma conta pode caber folgado em 500 consultas por dia e ainda assim gastar 40 consultas por PIX — perfil de quem varre chave, não de quem paga.

Cada janela de tempo pode ter teto para as duas taxas:

CampoO que mede
maxUsageRatioConsultas ÷ PIX Out concluídos na janela
maxFailureRatio(NOT_FOUND + recusadas) ÷ consultas na janela. É fração, não percentual: 0.4 = 40%
minLookupsPiso de amostra. Abaixo desse número de consultas na janela, nenhuma das duas regras pode recusar

As janelas disponíveis são 5m, 15m, 30m, 1h, 3h, 6h, 12h, 24h, 3d, 7d, 14d e 30d.

{
"dictLookup": {
"windows": {
"5m": { "maxFailureRatio": 0.6, "minLookups": 10 },
"1h": { "maxUsageRatio": 6, "maxFailureRatio": 0.4, "minLookups": 50 },
"30d": { "maxUsageRatio": 4, "minLookups": 500 }
}
}
}

O minLookups existe para o rate não travar quem mal começou: uma conta com duas consultas e nenhum pagamento tem taxa de uso infinita, e sem o piso ficaria bloqueada para sempre.

Janela sem teto declarado não é janela desligada. Ela herda a linha de base da frota, que hoje é maxUsageRatio 2.2 e maxFailureRatio 0.3 em todas as faixas, com piso de amostra de 20 nas janelas de até 30 minutos, 50 de 1h a 12h e 500 por dia de janela a partir de 24h (500 em 24h, 1500 em 3d, e assim por diante). Esses números saíram da medição de 14 dias de tráfego real e não barravam nenhuma conta no histórico. Declarar valores próprios na policy especializa a conta ou o tenant; não é o que liga a proteção.

Quando mais de uma janela está acima do teto, a resposta cita a mais curta — é a causa imediata e a primeira a liberar. A mensagem do 429 diz qual janela, o que foi medido e qual era o teto:

DICT lookup usage too high for this account in the last 1h:
120 lookups for 10 successful transfers (12.0 per transfer); max 6.0
DICT lookup failure rate too high for this account in the last 5m:
18 of 24 lookups did not resolve a key (75%); max 40%

O errorCode continua sendo dict_lookup_limit_exceeded — nada muda para quem já trata esse código.

Todo limite é por conta

Todos os limites são medidos conta a conta, sempre. Não existe teto agregado por tenant: as consultas de uma conta nunca entram na contagem de outra, mesmo que as duas pertençam ao mesmo tenant.

Isso vale inclusive quando o limite foi configurado no nível do tenant. Uma policy de tenant é um molde aplicado a cada conta individualmente, não um balde compartilhado:

ConfiguraçãoLeitura corretaLeitura errada
Policy do tenant com maxLookupsPerDay: 50Cada conta do tenant pode fazer 50 consultas por diaO tenant todo pode fazer 50 por dia, divididas entre as contas
Policy do tenant com windows.24h.maxUsageRatio: 2.2A taxa de cada conta é medida contra as transferências daquela contaA taxa é medida contra o total de transferências do tenant

A policy de conta continua vencendo a do tenant quando existir — o que muda entre as duas não é a unidade de contagem, apenas de onde saem os números.

A conta é a unidade porque é ela que o BACEN mede no bucket de rate limit do DICT: é nela que a rajada acontece e é nela que a punição chega. Somar as contas de um tenant produzia os dois erros ao mesmo tempo — uma conta parada herdava o consumo da vizinha, e num tenant grande o excesso de uma conta se diluía no total até nenhum limite fechar.

Pagamento por chave também consome cota

Em implantação

Esta seção descreve o comportamento que entrará em vigor. Hoje o pagamento por chave ainda não consome cota e não recebe 429 por esse motivo. Avisaremos com antecedência antes de ligar.

Um PIX Out no modo KEY precisa saber quem é o dono da chave antes de enviar o dinheiro. Essa resolução conta na mesma cota da consulta explícita, e por isso um pagamento pode receber 429 com errorCode: dict_lookup_limit_exceeded. Quando isso acontece, nenhum pagamento é criado: não há paymentId, não há transação, e reenviar com a mesma Idempotency-Key continua sendo seguro.

O cache de 24h é o que evita a dupla contagem. O fluxo mais comum — consultar a chave para exibir o destinatário e, confirmado pelo usuário, pagar — gasta uma consulta, não duas: a segunda é servida pelo cache. Quem paga direto, sem consultar antes, também gasta uma. Nos dois casos, 100 pagamentos por chave consomem cerca de 100 da cota, o que deixa o resto do orçamento para consultas avulsas.

O BigPix resolve a chave uma vez para o lote inteiro, independente de em quantas parcelas o valor é dividido.

Dois desfechos merecem atenção no POST de pagamento:

  • Chave inválida ou inexistente devolve o erro na resposta, sem criar pagamento. É preferível a um pagamento que nasce e falha segundos depois.
  • DICT indisponível (erro ou timeout do liquidante) não recusa nada: o pagamento segue e a chave é resolvida pelo liquidante, como antes. Indisponibilidade nossa ou dele não vira pagamento recusado nem consome cota.

O denominador da taxa de uso

A taxa de uso de uma janela é consultas ÷ transferências concluídas na mesma janela. Do lado do denominador entram só as transferências que de fato aconteceram, e só as daquela conta: COMPLETED e REFUNDED (que liquidaram e só depois foram devolvidas). Pagamento que falhou, foi recusado ou ficou indeterminado não amplia o teto — do contrário, quem estivesse repetindo uma tentativa com erro ganharia mais cota de consulta a cada falha.

Conta nova ou ociosa tem denominador zero, o que daria taxa infinita. Quem protege esse caso é o minLookups da janela: abaixo do piso de amostra nenhuma das duas regras pode recusar, então a conta faz suas primeiras consultas sem ser barrada por uma taxa que ainda não significa nada.

Até a v2.52.0 esse papel cabia a um piso global de 50 consultas/24h, ligado ao maxLookupRatio. Ele saiu junto com o limite; a mensagem (bootstrap floor of 50 lookups/24h applied) não aparece mais.

Ausente não é ilimitado

Um limite ausente na policy não significa ilimitado: vale o default global da tabela acima. Para remover o teto é preciso declarar isso explicitamente (opção No limit no Backoffice, que grava um valor negativo). Os limites de burst continuam ativos mesmo assim — remover o teto diário não libera rajada.

O que consome cota

Cota diária (maxLookupsPerDay) e ratio contam as consultas que chegaram ao DICT por vontade do integrador: chave encontrada, chave inexistente e chave recusada pelo DICT (requisição inválida, ou o limite do próprio DICT para aquele consultante). Falha técnica do liquidante e tentativa já recusada com 429 ficam de fora — não se deve queimar cota por indisponibilidade nossa, nem afundar mais fundo depois de já ter sido bloqueado. Vale igual para a consulta explícita e para a resolução feita dentro de um PIX Out.

Os limites de burst são o oposto: maxLookupsPerMinute conta todos os resultados, inclusive os recusados, porque a métrica ali é a pressão que o cliente está fazendo, não o proveito que tirou. maxNotFoundPer5min conta só as chaves inexistentes.

Cache de 24h

Consultas repetidas da mesma chave são servidas de um cache de 24h, e cache hit não consome cota. O cache é o mesmo para os dois caminhos: uma consulta explícita serve o pagamento seguinte, e a resolução feita dentro de um pagamento serve a consulta seguinte. Para forçar uma ida ao DICT — dados desatualizados, titularidade que pode ter mudado — use ?noCache=true na consulta explícita, lembrando que aí a consulta conta normalmente.

Webhook policy.violation

Toda violação — recusada ou apenas avisada — dispara o evento policy.violation para quem o assinou.

{
"phase": "edge",
"action": "BLOCK",
"blocked": true,
"accountId": "acc_...",
"identifier": "PEDIDO-1234",
"mode": "KEY",
"amount": 5000.00,
"violations": [
{ "rule": "maxAmount", "message": "amount R$ 5000.00 exceeds the per-transaction limit of R$ 1000.00" }
],
"counterparty": { "document": "12345678900", "name": "FULANO DE TAL" }
}

Em phase: "edge" não há paymentId: o gate roda antes de o pagamento ser criado, e é justamente por isso que a recusa cabe na resposta HTTP. Use o identifier para correlacionar. Na fase counterparty, que roda dentro do workflow, o paymentId já existe e vem no payload.

CampoDescrição
phaseedge (na requisição), counterparty (após resolver o destinatário), pix_in (após o crédito) ou dict_lookup
actionBLOCK, NOTIFY_ONLY, ALLOW_AND_NOTIFY ou AUTO_REFUND, conforme a configuração
blockedtrue quando a operação foi de fato recusada. Sempre false em pix_in
violationsTodas as regras violadas, com o identificador em rule
counterpartyO destinatário (PIX Out) ou o pagador (PIX In), quando conhecido

Em phase: "pix_in" o payload troca paymentId por transactionId e endToEnd, e traz refunded indicando se o valor foi devolvido.

Detalhes de entrega, retentativas e assinatura no guia de Webhooks.

Visibilidade de Violações

  • Webhook policy.violation — em toda violação, em qualquer seção.
  • Timeline da transação (GET /v1/transactions/{id}/timeline) — quando a violação recusa um PIX Out, o evento pix_out.failed traz errorCode: policy_denied e as regras violadas em policyViolations. Numa recusa na borda, em que ainda não existe paymentId, a âncora do evento é o workflowId determinístico da operação, que é o mesmo id devolvido nas respostas de PIX out. O endpoint aceita os dois, além de endToEndId, txid e o id do parceiro.
  • Painel — a aba Violations lista o histórico, separando o que foi barrado, o que foi só avisado e o que foi devolvido, com o total por regra.
O extrato não mostra violações

Uma operação recusada por política nunca chega ao banco parceiro, e o extrato (GET /v1/accounts/{accountId}/statement) reflete o que aconteceu na conta. Violações não aparecem lá. Use o webhook, a timeline ou o painel. A exceção é a devolução de um PIX In por AUTO_REFUND: ela é uma movimentação de verdade e aparece no extrato como devolução.

Allowlist de IP e MED

A allowlist de IP que de fato bloqueia tráfego é a do WAF, configurada na tela de Security — não é uma política. Controles de MED têm guia próprio em Disputas (MED).