POST /v1/indirects.
Esta página descreve o que uma participação hospedada é e como ela se comporta. O provisionamento — a chave de criptografia do segredo de entrega, a postura de hospedagem e a própria chamada de cadastro — é Hospedar participantes indiretos, que dá continuidade à numeração da página de configuração. Desses, apenas a chave de criptografia recusa todo cadastro sozinha — provisione-a primeiro. A postura de hospedagem controla os caminhos do dinheiro, não o registro, então você pode cadastrar participantes antes de ativá-la.
Quem é responsável pelo quê
Quase todo mal-entendido operacional aqui é alguém procurando a resposta na coluna errada.
Na prática: quando chega um Pix para um cliente de um participante indireto, o dinheiro para com você, em uma conta que representa a posição daquela instituição. Você não sabe — e não pode saber — qual dos clientes dela é o dono. O participante indireto credita o cliente dele no próprio core, depois de receber o seu aviso.
O que cadastrar um indireto cria
Cadastrar um participante indireto faz mais do que gravar uma linha. O plugin também cria a posição de liquidação dessa instituição no Midaz: uma conta do ledger cujo alias é
@pi_ seguido do ISPB da instituição, o código de oito dígitos que o BACEN atribui a cada participante. Um indireto no ISPB 12345678 liquida em @pi_12345678.
É nessa posição que o dinheiro dessa instituição fica. A resposta a retorna como piAccountAlias, e o alias deriva de ispb — você nunca o escolhe, e um cliente nunca cria a conta.
Uma posição por instituição é todo o propósito disso. Um crédito que chega para um indireto cai apenas na conta desse indireto, então o dinheiro de uma instituição nunca se mistura com o de outra, nem com o seu. Essa segregação é a propriedade que o registro existe para garantir.
O alias usa underscore, não barra:
@pi_12345678. O Midaz rejeita barra em um alias de usuário, então um nome no formato de caminho não resolve a nada.Antes de cadastrar alguém
A participação indireta vem desligada por padrão. A flag do systemplane por tenant
plugin-br-pix-jd.indirects/enabled deve estar ligada, e o valor padrão dela é false.
Vale saber o que a flag realmente controla, porque as duas metades se comportam de formas diferentes:
- A API de gerenciamento funciona com a flag desligada. Você pode cadastrar participantes, listá-los e ler um deles antes da habilitação. O onboarding antes do go-live é proposital.
- Nenhum dinheiro se move com a flag desligada. A resolução — a etapa que decide a qual indireto um crédito recebido pertence — reporta a funcionalidade como desabilitada, então um crédito recebido nunca é roteado para uma conta
@pi, e nenhum indireto pode originar uma ordem de saída.
422 PIX-0111: a escrita de certificado de QR próprio em PATCH /v1/indirects/{indirectId}, e GET /v1/indirects/{indirectId}/jwks.
Uma coisa continua funcionando com a flag desligada que você poderia esperar que estivesse controlada: a fila de exceções, para que um crédito já retido para triagem nunca fique preso atrás de uma chave.
A leitura falha fechada. Se o systemplane não responde, se o valor não resolve, ou se ele volta com o tipo errado, o plugin lê a flag como desligada — nunca ligada por acidente. Um caminho do dinheiro que “voltou a se comportar como um direto” sem que ninguém tenha tocado na chave é esse mecanismo. Olhe o systemplane.
Cadastrando um indireto
1
Ative a funcionalidade para o tenant
Defina
plugin-br-pix-jd.indirects/enabled como true. O cadastro funciona sem isso, mas nada liquida até que esteja ligada.2
POST /v1/indirects
Envie o
name da instituição, o ispb dela, e um bloco delivery contendo endpointUrl (uma URL HTTPS) e secret. A resposta é 201 e traz indirectId — o identificador pelo qual toda chamada posterior é roteada — e piAccountAlias.3
Nada para consultar em loop — um 201 significa pronto
Toda etapa roda antes que a linha do registro seja gravada: a verificação de unicidade do ISPB, a verificação opcional no diretório da JD, depois a criação da conta
@pi_{ispb} no Midaz. Apenas então a linha é gravada, e ela é gravada como ACTIVE. Não há estado intermediário nem nada a esperar.4
Em caso de falha, corrija a causa e envie o POST de novo
Uma etapa que falha responde com um erro codificado que nomeia a etapa, e nenhuma linha do registro é gravada, então o ISPB continua livre. Corrija a causa e envie o POST de novo — reenviar é a recuperação, e não há uma rota de nova tentativa separada porque nada ficou parcialmente escrito para retomar.
201 significa pronto, e uma falha não deixa nenhuma linha no registro. O status em um 201 é sempre ACTIVE. Se você está escrevendo um cliente que fica consultando em loop até o participante ficar roteável, apague esse loop — ele está esperando por uma transição que não pode acontecer.
A única coisa que uma falha pode deixar para trás é a conta de liquidação, quando essa etapa teve sucesso e uma posterior não. Ela não é desfeita, e é inofensiva: nada é roteado para uma conta @pi sem uma linha ACTIVE no registro apontando para ela, e criar a conta é idempotente por alias, então a próxima tentativa adota a mesma conta em vez de criar uma segunda. O que uma falha nunca deixa é uma linha no registro ou um ISPB retido.
A resposta ainda traz um objeto provisioning com um campo failedStep. Ele é legado e sempre null para tudo o que este serviço cadastra, porque um cadastro malsucedido não deixa nenhuma linha para carregar um marcador.
Os estados do ciclo de vida são ACTIVE, SUSPENDED e CLOSED.
Como o dinheiro chega a um participante indireto
Acompanhe um Pix recebido. Nada nesse caminho é um endpoint que o indireto chama; é o seu plugin que faz o trabalho.
- “Esta conta pode receber?” Antes de mover o dinheiro, o Banco Central pergunta se a conta de destino aceita o crédito. A pergunta chega até você, porque o participante indireto não tem linha própria com o SPI.
- Um Pix chega para uma conta mantida na instituição indireta e alcança sua participação direta, entregue ao webhook de cash-in do plugin.
-
A resolução encontra o indireto pelo ISPB no bloco do recebedor, consultado no registro de participação. Quatro desfechos, e apenas o primeiro credita um indireto:
- corresponde a uma participação
ACTIVE, então o crédito é lançado no alias@pi_{ispb}dessa participação; - é o seu próprio ISPB, então é o seu livro, e o CRM resolve a conta como de costume;
- não corresponde a nada, ou corresponde a uma participação suspensa ou encerrada, então o crédito fica retido para um operador fazer a triagem;
- a resolução falha por infraestrutura, então o plugin nem credita nem retém. Ela falha fechada de propósito: nada relacionado a dinheiro é adivinhado.
- corresponde a uma participação
-
O crédito é lançado em
@pi_{ispb}. O plugin registra a movimentação contra essa posição de liquidação e vincula seu próprio registro de transação ao indireto. O aviso é gravado na mesma transação de banco de dados que o crédito — ou os dois existem, ou nenhum existe. -
Um aviso assinado é enviado ao
delivery.endpointUrlque você cadastrou, carregando o payload da JD byte a byte. Aqui é o plugin chamando a instituição, não o contrário. - O participante indireto credita o próprio cliente, no próprio core.
A entrega é pelo menos uma vez. O mesmo aviso pode ser reenviado após uma falha que permite nova tentativa, ou uma queda entre o envio e o lançamento contábil, e o
endToEndId é estável entre as tentativas — então um receptor deve deduplicar pelo endToEndId e tratar um payload repetido como já processado.
O
secret armazenado é apenas-escrita. Toda leitura de um indireto retorna delivery.secret como ***, então um secret perdido é substituído com um PATCH, nunca recuperado.Quando o aviso nunca chega
O envio pode falhar de forma permanente — as tentativas se esgotam, ou o endpoint responde
4xx, depois do que o aviso é marcado como inválido e nunca mais tentado. O dinheiro é lançado corretamente de qualquer forma. A consequência é mais restrita e pior do que parece: a movimentação é real, e a instituição não sabe dela.
GET /v1/indirects/{indirectId}/transactions é o que fecha essa lacuna. Ele retorna as movimentações que realmente se liquidaram na conta @pi_{ispb} de um indireto, o que faz dele o registro definitivo, não o aviso. Varrer esse endpoint em um agendamento é como uma instituição para de depender de a entrega ter funcionado, e é também a única forma de reler uma janela depois de uma indisponibilidade própria.
As regras de janela, paginação e unidade que decidem se uma conciliação está correta — a janela since semiaberta obrigatória, centavos inteiros, paginação por cursor do mais antigo para o mais novo, o limit limitado silenciosamente — são o contrato de Listar as transações de um participante indireto. Ler o feed não muda nada e não reenvia nenhum aviso.
Hospedando o QR code sob o certificado próprio da instituição
Por padrão, um QR code dinâmico emitido para um indireto é assinado e publicado sob a sua participação direta. Um indireto pode publicar o próprio em vez disso: defina
qrCertificate.ownCertificate com um publicBaseUrl em PATCH /v1/indirects/{indirectId}, e o documento assinado passa a ser servido a partir do próprio host da instituição.
A instituição não pode produzir as chaves de validação sozinha, porque a JDPI mantém o certificado e faz a assinatura. GET /v1/indirects/{indirectId}/jwks retorna o JWK Set desse indireto para que a instituição possa publicá-lo no próprio host, para que PSPs pagadores validem contra ele. Busque-o quando configurar o certificado e de novo sempre que ele rotacionar.
O status do ciclo de vida deliberadamente não controla essa leitura: um indireto suspenso ou encerrado ainda tem QR codes ativos em circulação, e reter a chave quebraria a validação deles.
Lendo o registro
status e ispb (8 dígitos, exato); as regras de paginação por cursor e o limit limitado silenciosamente são o contrato de Listar participantes indiretos.
Um GET por id, e a lista, são sempre a verdade atual. Os caminhos do dinheiro leem uma projeção em cache, então uma suspensão pode levar até o TTL do cache de resolução — 30 segundos por padrão — para ser vista por todas as réplicas. O bloqueio do ledger vindo de suspend já se aplica no momento da chamada.
Suspendendo, reativando e encerrando
PATCH /v1/indirects/{indirectId} carrega no máximo uma action de ciclo de vida — suspend, reactivate ou close — e cada uma escreve tanto no ledger quanto no registro.
suspenddesabilita tanto o envio quanto o recebimento na conta@pido indireto. O próprio ledger recusa o dinheiro desse participante, por isso uma suspensão vale mesmo em uma réplica cujo cache de resolução ainda está desatualizado.reactivatereabilita os dois.closeé irreversível.CLOSEDé terminal, e depois disso toda mudança de campo na linha também é recusada.
@pi fica permanentemente bloqueada, mas é mantida, então um novo cadastro posterior do mesmo ISPB reaproveita a conta histórica — desbloqueada, reativada, e com o histórico contábil intacto.
Um PATCH que carrega apenas campos, sem action, muda esses campos. Um PATCH que não carrega nada é um no-op que retorna a linha atual, não um erro.
O que dá errado
Toda recusa que esse registro pode responder — seu status, sua condição exata, e o que foi ou não gravado quando ela disparou — está nas páginas de operação: Cadastrar um participante indireto, Atualizar um participante indireto, Consultar um participante indireto, Listar participantes indiretos, Consultar o JWK Set de um participante indireto, e Listar as transações de um participante indireto. O catálogo completo, com o
detail exato que cada código carrega, é a Lista de erros do Pix JD.
Se deve repetir é decidido pelo status, não pela família do código.
PIX-0107 e PIX-0123 são a mesma condição vista duas vezes: um 409 significa que o trilho leu a configuração e constatou que a chave está ausente — apenas um operador muda isso, então repetir entra em loop para sempre. Um 503 significa que a própria leitura não terminou, então a chave não é sabidamente ausente, e repetir é correto. Nenhum dos dois grava nada.Para onde ir agora
- Hospedar participantes indiretos — o provisionamento: a chave de criptografia, a postura, e a chamada de cadastro.
- Cadastrar um participante indireto — o contrato completo da requisição e cada recusa.
- Listar as transações de um participante indireto — o feed de conciliação, com as regras de paginação por completo.
- Atualizar um participante indireto — mudanças de campo, ações de ciclo de vida e a configuração de certificado próprio.
- Pix Direto via JD — a participação direta sobre a qual tudo isso roda, e como as movimentações liquidadas chegam ao Midaz.

