Pagamentos
Split de pagamento
Divida o valor de um pagamento entre recebedores com parcelas fixas e percentuais, saiba para onde vão os centavos, como o adquirente executa a divisão e simule antes de cobrar.
Guia de integração · 26 min de leitura
Nesta página
O split divide o valor de um pagamento entre recebedores: o vendedor de um marketplace, um parceiro, um afiliado. Cada recebedor leva exatamente a parcela configurada para ele. O que nao foi dividido fica com a conta principal - a do estabelecimento que cobra - e nao gera linha de split.
Por isso nao e preciso cadastrar a plataforma como recebedor para ficar com a comissao: "90% para o vendedor" basta, e os outros 10% ficam com voce.
A divisao e executada no adquirente. O Minstrel calcula as parcelas, grava e as envia junto com a autorizacao; quem liquida cada parte no recebedor certo e o adquirente. Para isso o pagamento precisa ir para uma conta de conector com o split ligado e com todos os recebedores registrados nela - sem isso ele nao e autorizado, de proposito (veja Execucao no adquirente). Executam o split a Cielo (Split de Pagamento, com contrato) e o Minstrel Sandbox (simulado).
Cadastre os recebedores
curl -X POST http://localhost:3333/v1/recipients \
-H "Authorization: Bearer $MINSTREL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Loja do Vendedor ME",
"document": "12.345.678/0001-95",
"email": "financeiro@lojadovendedor.com.br",
"commissionRateBps": 500,
"commissionFixedAmount": 30,
"bankCode": "341",
"bankBranch": "1234",
"bankAccount": "56789-0",
"pixKey": "12345678000195",
"defaultSplitType": "percentage",
"defaultSplitValue": 9000,
"liableForChargeback": true
}'
| Campo | Para que serve |
|---|---|
document, documentType | CPF ou CNPJ (inclusive o alfanumerico), com digito verificador conferido. O tipo e deduzido pelo tamanho; para outros documentos, informe passport ou other. |
connectorAccountId | Conta de conector em que o recebedor esta registrado. Campo legado para importar um vínculo inicial. O recebedor pode ter vários cadastros em registrations, um por conta de conector. |
externalRecipientId | Id do recebedor no adquirente. E o que vai nas instrucoes de split. No cadastro por parceiro, é único por conta de conector; não é compartilhado entre adquirentes. Em conta Cielo e o SubordinateMerchantId do seller, um GUID (veja Split na Cielo); outro formato e recusado no cadastro, com 422. |
commissionRateBps, commissionFixedAmount | Comissao do marketplace sobre a parcela deste recebedor: percentual em basis points (550 e 5,5%, de 0 a 10000) e tarifa fixa em centavos. Cada um e opcional, 0 e valor (sem comissao) e null apaga. Veja Comissao do marketplace. |
bankCode, bankBranch, bankAccount | Conta para repasse: codigo COMPE do banco (3 digitos), agencia e conta com digito. Os tres vem juntos; bankAccountType e checking (padrao) ou savings. |
pixKey | CPF, CNPJ, e-mail, celular com +55 ou chave aleatoria. |
defaultSplitType, defaultSplitValue | Regra padrao do recebedor, usada pelo simulador e sugerida ao montar o no Split. Vem em par. |
liableForChargeback | O recebedor arca com o chargeback da parcela dele. Padrao false. Na Cielo nao tem efeito no adquirente: todo chargeback e do lojista principal. |
chargeProcessingFee | O recebedor paga parte da tarifa de processamento. Padrao false (veja Tarifa de processamento). Na Cielo tambem nao tem equivalente. |
- O recebedor pertence ao ambiente da credencial que o criou: um split de producao nunca paga um recebedor de sandbox, e vice-versa.
- O cadastro local não aprova o recebedor no parceiro. O split exige um cadastro
activena conta escolhida; enquanto houver pendências ou análise, a cobrança é bloqueada comsplit_not_supported. Vínculos antigos importados começamunverifiede também precisam de confirmação. - Celular sem o +55 e recusado:
11987654321seria indistinguivel de um CPF, e repasse para a chave errada nao tem estorno automatico. - A listagem e os eventos de webhook trazem documento, conta e chave Pix
mascarados (
masked: true). Os dados completos so voltam emGET /v1/recipients/:ide na resposta de quem acabou de envia-los.
Cadastro em cada parceiro
O mesmo recebedor pode acumular cadastros na Cielo e em outros parceiros, com identificadores e situações independentes. A aprovação vale para a conta de conector e o ambiente: duas contas Cielo não compartilham automaticamente o cadastro, e sandbox nunca habilita produção.
No painel, abra Split → recebedor → Cadastros por parceiro. Cada cartão mostra a conta, a aprovação e suas pendências. Clique em Cadastrar neste parceiro, complete os campos adicionais solicitados e envie. Dados básicos faltantes, como CPF/CNPJ ou banco, são corrigidos em Editar dados do recebedor. Um cadastro já existente pode ser importado pelo ID; esse ID não serve como aprovação manual, pois o Minstrel consulta o parceiro.
Pela API:
| Endpoint | Uso |
|---|---|
GET /v1/recipients/:id/registrations | Contas, campos exigidos, dados adicionais e pendências. Exige recipients:read; não exponha esta resposta publicamente. |
POST /v1/recipients/:id/registrations/:accountId | Salvar information e enfileirar cadastro. Opcionalmente importa externalRecipientId. Exige recipients:write. |
POST /v1/recipients/:id/registrations/:accountId/refresh | Solicitar consulta da aprovação; não cria outro cadastro. |
information aceita apenas os campos adicionais declarados pelo conector,
como responsável, telefone, endereço, razão social e, para pessoa física na
Cielo, nascimento e ramo de atividade. Os valores são cifrados no banco e não
acompanham os eventos. Campos de cartão são proibidos.
A resposta do cadastro é assíncrona (202). O worker envia uma única
solicitação e consulta a situação. Se o roteamento encontrar um recebedor sem
cadastro na conta candidata, prepara esse cadastro e suas pendências
automaticamente. A cobrança aguarda a aprovação; não se envia a venda sem
split como alternativa. Para evitar bloquear a primeira venda, antecipe o
cadastro dos recebedores.
| Estado | Significado |
|---|---|
needs_information | Dados faltantes, inválidos ou divergentes do parceiro. |
queued / submitting | Aguardando envio / envio em andamento. |
pending | Em análise no parceiro. |
active | Parceiro confirmou a aprovação; pode participar do split nesta conta. |
unverified | Cadastro importado ou alterado; exige confirmação. |
unknown | Envio sem resposta conclusiva; não reenviar. Consulte o parceiro e importe o ID existente. |
rejected | Não aprovado pelo parceiro. Resolva as pendências no portal. |
needs_configuration / unsupported | Integração precisa de configuração ou ainda não oferece onboarding. |
Na Cielo, o envio não significa aprovação. O Minstrel exige confirmação final de onboarding, recebedor desbloqueado e correspondência de documento, master e domicílio bancário. Alterar o banco local não altera o banco na Cielo: atualize o cadastro no parceiro e confirme a situação. Fluxo oficial de onboarding.
Hoje há implementação de cadastro para Cielo Split e Minstrel Sandbox (simulado). Os demais conectores precisam implementar seu próprio contrato; o Mercado Pago, por exemplo, exige conta de vendedor e autorização OAuth. Não marcamos um recebedor como cadastrado em um parceiro sem confirmação dessa integração. Pré-requisitos do Mercado Pago.
O evento recipient.registration_updated informa conta, situação e nomes dos
campos pendentes. Use-o para avisar seu cliente. A referência usada em cada
venda fica congelada para captura e estorno, mesmo que os cadastros do recebedor
sejam alterados depois.
Gerenciar recebedores
| Endpoint | O que faz |
|---|---|
GET /v1/recipients | Lista com filtros (active, search, document, splitType, destination, liableForChargeback) e o volume dividido no periodo (from e to, padrao 30 dias). |
GET /v1/recipients/summary | Recebedores ativos, volume dividido contra o periodo anterior, total a repassar e maiores recebedores. |
GET /v1/recipients/:id | Dados completos, totais e os fluxos publicados que usam o recebedor (usedByFlows). |
GET /v1/recipients/:id/splits | Parcelas do recebedor, pagamento a pagamento, da mais recente para a mais antiga. |
GET /v1/recipients/:id/ledger | Lancamentos da conta do recebedor no razao contabil, com o saldo. |
GET /v1/recipients/:id/payouts | Repasses do recebedor. |
PATCH /v1/recipients/:id | Edicao parcial: campo ausente fica como esta, null apaga. |
DELETE /v1/recipients/:id | Remocao logica. Os splits ja gravados continuam no historico (preservedSplits informa quantos). |
Leitura exige o escopo recipients:read; cadastro, edicao e remocao,
recipients:write.
Desativar (active: false) ou remover um recebedor que esta no split de um
fluxo publicado e recusado com 409, com os fluxos em meta.flows: os
pagamentos desse fluxo passariam a falhar. Retire o recebedor do no Split e
publique o fluxo antes. Com repasse em andamento, a remocao tambem e recusada.
Toda troca de banco ou chave Pix fica na auditoria como
recipient.payout_destination_changed - trocar a conta de repasse e a fraude
classica de marketplace.
Divida o pagamento
Envie splits na criacao do pagamento:
curl -X POST http://localhost:3333/v1/payments \
-H "Authorization: Bearer $MINSTREL_API_KEY" \
-H "Idempotency-Key: pedido-7781" \
-H "Content-Type: application/json" \
-d '{
"amount": 10003,
"customerId": "cus_01HQ...",
"paymentMethodId": "pm_01HQ...",
"splits": [
{ "recipientId": "rcp_vendedor", "type": "percentage", "value": 2500 },
{ "recipientId": "rcp_parceiro", "type": "percentage", "value": 2500 }
],
"splitRemainderRecipientId": "rcp_parceiro"
}'
Campo de splits[] | Obrigatorio | Significado |
|---|---|---|
recipientId | sim | Recebedor cadastrado, ativo e do mesmo ambiente da chave. |
type | sim | percentage ou fixed. |
value | sim | Inteiro. Em percentage, basis points: 1000 e 10%, 250 e 2,5%. Em fixed, centavos: 1500 e R$ 15,00. |
liableForChargeback | nao | Omitido, vale o padrao cadastrado no recebedor. |
chargeProcessingFee | nao | Omitido, vale o padrao cadastrado no recebedor. |
- No maximo 20 parcelas, uma por recebedor.
typeevaluesao obrigatorios na API. A regra padrao do recebedor (defaultSplitTypeedefaultSplitValue) so e usada pelo simulador.splitRemainderRecipientIde opcional. Precisa ser um dos recebedores desplitse fica com os centavos de arredondamento. Sem ele, os centavos ficam com a conta principal.
Como o valor e calculado
A conta segue quatro regras, nesta ordem:
- As parcelas fixas sao reservadas primeiro.
- Os percentuais valem sobre o que sobra (valor menos fixas), literalmente: 10% sao 10%. Cada parte e truncada no centavo, entao nenhum recebedor leva mais do que configurou.
- Centavos de arredondamento sao a diferenca entre o grupo percentual
truncado uma unica vez e a soma das partes truncadas uma a uma. Vao para
splitRemainderRecipientIdou ficam com a conta principal. - O que nao foi dividido fica com a conta principal, sem linha de split.
A soma sempre fecha ao centavo: parcelas mais conta principal da exatamente o valor do pagamento. O banco reforca a regra com um trigger que impede gravar splits que somem mais do que o pagamento.
10% sozinho
R$ 100,00 com uma unica parcela de 10% (value: 1000):
| Quem | Valor |
|---|---|
| Recebedor | R$ 10,00 |
| Conta principal | R$ 90,00 |
Dois de 50% com centavo impar
R$ 100,01 em duas parcelas de 50% (value: 5000). Cada metade, truncada, da
R$ 50,00; o grupo de 100% vale R$ 100,01. Sobra 1 centavo:
| Quem | Sem recebedor dos centavos | Centavos para A |
|---|---|---|
| Recebedor A | R$ 50,00 | R$ 50,01 |
| Recebedor B | R$ 50,00 | R$ 50,00 |
| Conta principal | R$ 0,01 | R$ 0,00 |
"Centavos para A" e splitRemainderRecipientId apontando para o recebedor A.
25% mais 25% com os centavos para B
E o pagamento do exemplo acima: R$ 100,03 com duas parcelas de 25% e
splitRemainderRecipientId apontando para B. As partes truncadas dao R$ 25,00
cada; o grupo de 50%, truncado uma vez, da R$ 50,01:
| Quem | Valor |
|---|---|
| Recebedor A | R$ 25,00 |
| Recebedor B | R$ 25,01 (R$ 25,00 mais 1 centavo) |
| Conta principal | R$ 50,02 |
Sem splitRemainderRecipientId, B ficaria com R$ 25,00 e a conta principal com
R$ 50,03.
Fixo mais percentual
R$ 100,00 com R$ 15,00 fixos para A (type: fixed, value: 1500) e 20% para
B. A parcela fixa sai primeiro, e os 20% valem sobre os R$ 85,00 restantes:
| Quem | Valor |
|---|---|
| Recebedor A | R$ 15,00 |
| Recebedor B | R$ 17,00 (20% de R$ 85,00) |
| Conta principal | R$ 68,00 |
Parcela zerada
0,5% (value: 50) de uma venda de R$ 1,50 da R$ 0,0075, truncado para zero. A
parcela e gravada com valor zero, mas nao vai ao parceiro.
Erros de validacao
O split da requisicao e validado antes de o pagamento ser criado:
configuracao invalida recusa a chamada inteira e nao deixa pagamento pela
metade. Todos os casos respondem 422, com type: invalid_request_error,
code: validation_failed e param: splits - menos o ultimo, em que param e
o proprio splitRemainderRecipientId:
| Situacao | Em meta |
|---|---|
| Parcelas fixas somam mais que o valor do pagamento | reason: fixed_exceeds_amount |
Percentuais somam mais de 100% (10000) | reason: percentage_over_100 |
| O mesmo recebedor em duas parcelas | recipientId |
| Recebedor inexistente, inativo ou de outro ambiente | missingRecipientIds |
| Recebedor dos centavos fora das parcelas | - |
{
"error": {
"type": "invalid_request_error",
"code": "validation_failed",
"message": "A soma dos percentuais do split e 110.00%, acima de 100%.",
"param": "splits",
"requestId": "req_01HQ...",
"meta": { "reason": "percentage_over_100" }
}
}
Mais de 20 parcelas, type desconhecido e value negativo ou fracionado sao
barrados antes, na validacao do corpo, tambem com 422.
Uma configuracao valida pode ainda assim nao ser executavel: conta sem o split
ligado ou recebedor que nao esta registrado nela. Isso nao e erro de validacao
do corpo; o pagamento e criado e recusado com split_not_supported, descrito em
Quando o pagamento nao e autorizado.
Na resposta do pagamento
O pagamento devolvido traz as parcelas. Os campos do adquirente (netAmount,
feeAmount, capturedAmount) vao sendo preenchidos ao longo da vida do
pagamento:
{
"object": "payment",
"id": "pay_01HQ...",
"amount": 10003,
"splits": [
{
"recipientId": "rcp_vendedor",
"amount": 2500,
"type": "percentage",
"liableForChargeback": true,
"commissionRateBps": 500,
"commissionFixedAmount": 30,
"netAmount": 2345,
"feeAmount": 155,
"capturedAmount": 2500,
"refundedAmount": 0
},
{
"recipientId": "rcp_parceiro",
"amount": 2501,
"type": "percentage",
"liableForChargeback": false,
"commissionRateBps": null,
"commissionFixedAmount": null,
"netAmount": 2501,
"feeAmount": 0,
"capturedAmount": 2501,
"refundedAmount": 0
}
]
}
Logo apos a autorizacao com captura manual, capturedAmount e null e, se o
adquirente ainda nao informou a divisao, netAmount tambem.
| Campo | O que e |
|---|---|
amount | Parcela bruta do recebedor, calculada sobre o valor autorizado. |
commissionRateBps, commissionFixedAmount | Comissao gravada no momento do pagamento (copia do cadastro). null: vale o acordo do recebedor no adquirente. |
netAmount | O que o recebedor recebe, como o adquirente informou. null ate o adquirente liquidar a divisao: nunca e um valor inventado. |
feeAmount | Bruto menos liquido: o que o adquirente descontou do recebedor (comissao e tarifas da divisao). 0 ate a liquidacao. |
capturedAmount | Quanto desta parcela foi capturado. null ate a captura; na captura parcial, a proporcao do valor capturado. |
refundedAmount | Quanto desta parcela ja foi devolvido em cancelamentos e estornos. 0 se nada foi devolvido. |
Em GET /v1/payments/:id, cada parcela tambem traz id, o nome do recebedor
em recipient, o valor configurado em configuredValue (basis points ou
centavos) e chargeProcessingFee. Veja Transacoes.
As mesmas parcelas, com esses campos, vao no data.object dos eventos
payment.captured, payment.voided, payment.refunded e
payment.partially_refunded (veja Webhooks).
Precedencia
- O split da requisicao vence o do fluxo. Com split gravado, o no Split nao recalcula; a etapa registra "O pagamento ja tem split gravado (da requisicao ou de uma execucao anterior); as regras deste no nao foram reaplicadas.". O mesmo vale quando o fluxo do pagamento e retomado (revisao manual, espera): a divisao de um pagamento e decidida uma unica vez.
- Sem no Split no fluxo, o split da requisicao segue para o conector do mesmo jeito - inclusive no roteamento direto, sem fluxo publicado.
- Parcela de valor zero fica gravada, mas nao vai ao adquirente e nao exige recebedor registrado.
Execucao no adquirente
Quem liquida o dinheiro de cada recebedor e o adquirente, na venda. Para cada
parcela, o conector recebe o externalRecipientId do recebedor, o valor bruto,
a comissao (quando ha) e as marcas liableForChargeback e
chargeProcessingFee. As instrucoes viajam na autorizacao, na captura e, no
estorno parcial, com a devolucao de cada parte (veja
Captura e estorno).
| Conta | Executa o split quando |
|---|---|
| Cielo | O recurso Split de pagamento (splitEnabled) esta ligado na conta, o Split esta contratado com a Cielo e o Client Secret do Split esta nas credenciais. Veja Split na Cielo. |
| Minstrel Sandbox | Sempre: nao ha interruptor nem contrato. A divisao e simulada (veja No Sandbox). |
O catalogo (GET /v1/connectors) indica a capacidade split em
capabilities, e a conta so a tem de fato quando o recurso esta ligado nela
(effectiveCapabilities, veja
Recursos por conta). Os demais parceiros
do catalogo ainda aparecem como EM BREVE.
Quando o pagamento nao e autorizado
Um pagamento com parcelas so e autorizado numa conta que executa o split, e isso exige duas coisas ao mesmo tempo:
- a conta tem a capacidade
splitefetiva (na Cielo,splitEnabledligado; no Sandbox, sempre); - todos os recebedores com parcela maior que zero têm um cadastro
activeemregistrationsnessa conta, comexternalRecipientIdconfirmado pelo parceiro.
A conta que nao cumpre as duas e pulada do roteamento, e o motivo fica no rastro. Se nenhuma conta candidata serve, o pagamento nao e autorizado. No roteamento direto (sem fluxo publicado), a chamada responde assim:
{
"error": {
"type": "connector_error",
"code": "split_not_supported",
"message": "Este pagamento tem split, mas nenhuma conta candidata consegue executa-lo no adquirente. Cielo - principal (cielo): o recebedor \"Loja do Vendedor ME\" (rcp_01HQ...) ainda nao foi liberado nesta conta: cadastro pending. Confira as pendencias em Recebedores. Autorizar sem dividir liquidaria o valor inteiro para o lojista principal, por isso o pagamento nao foi autorizado. Ligue o split na conta e registre cada recebedor nela (connectorAccountId e externalRecipientId).",
"requestId": "req_01HQ...",
"meta": {
"blocked": [
{
"connectorAccountId": "ca_01HQ...",
"name": "Cielo - principal",
"connectorSlug": "cielo",
"gaps": [{ "code": "recipient_not_registered", "recipientId": "rcp_01HQ..." }]
}
]
}
}
}
Por que recusar, e nao autorizar sem dividir: a venda sem a divisao liquida o valor inteiro para o lojista principal, e o dinheiro dos recebedores so voltaria a eles por acerto manual. Uma venda recusada com o motivo escrito custa menos do que uma aprovada que paga a pessoa errada.
502,connector_error, nao retentavel. Repetir a chamada sem mexer no cadastro cai no mesmo lugar.- O pagamento fica
failed. Ele ja foi criado, entao fecha com o eventopayment.failed(data.object.error.code = "split_not_supported") e as parcelas continuam gravadas. - Com fluxo publicado, o erro sai pela porta
errordo no Rotear, como qualquer falha tecnica da rota: o fluxo segue por ela, e o pagamento termina conforme o que a porta liga (em geral Recusar, ou uma revisao manual). O motivo completo fica no passo da rota, na explicacao e emoutput.error. Por isso a portaerrordo no precisa estar ligada a algo que voce acompanhe. meta.blocked[].gaps[].codediz o que falta em cada conta:
code | O que falta |
|---|---|
account_without_split | A conta nao tem o split ligado. Ligue o recurso em Plugins, conta, Recursos. |
recipient_not_registered | Cadastro ausente, ainda não aprovado ou sem identificador confirmado nesta conta. |
recipient_in_other_account | Referência legada ou histórica pertence a outra conta; não pode ser usada nesta. |
- Mais de uma conta pode executar o split se todas as parcelas tiverem recebedores aprovados em cada conta candidata. O token do cartão e as regras de retentativa continuam limitando o fallback. A escolha explícita de conta na assinatura impede trocar a cobrança para outra conta.
- O rastro da rota registra, na explicacao e em
skipped(comreason: "split_not_supported"edetail), quais candidatas foram puladas e por que. O mesmo vale para o cartao salvo numa conta sem split: a mensagem aponta o split, e nao a rota. - Captura e estorno parcial usam a conta e o identificador congelados na autorização. Alterações posteriores no cadastro não redirecionam o dinheiro de uma venda já autorizada para outro recebedor.
Comissao do marketplace
O marketplace pode reter uma comissao sobre a parcela de cada recebedor. Ela e
cadastrada no recebedor (commissionRateBps e commissionFixedAmount) e
copiada para a parcela no momento do pagamento: mudar o cadastro depois nao
altera vendas ja feitas, nem as capturas e estornos delas.
| Cadastro | O que o adquirente recebe |
|---|---|
| Percentual e tarifa fixa | Os dois valores. Na Cielo: Fares com Mdr (percentual) e Fee (centavos). |
| So um dos dois | O informado. Na Cielo, o outro vai zero: o Fares enviado vale mais que o acordo cadastrado, e omitir um componente deixaria a Cielo completa-lo com a tarifa do acordo. |
0 nos dois | Comissao zero: o lojista nao cobra nada deste recebedor. |
Nenhum (null) | Nada: vale o acordo cadastrado no adquirente para aquele recebedor. |
A comissao sai da parcela do recebedor. Nao confunda com a parte que fica na conta principal: essa e o que nao foi dividido; a comissao e o desconto sobre o que foi. Exemplo da Cielo: parcela de R$ 60,00 com 5% e R$ 0,30 fixos deixa R$ 56,70 para o recebedor e R$ 3,30 para o lojista principal.
Liquido e tarifa
Cada parcela tem netAmount e feeAmount. Os dois sao a palavra do
adquirente: o Minstrel grava o que ele devolve ao liquidar a divisao, na
autorizacao e de novo na captura, e feeAmount = amount - netAmount (nunca
negativo). Antes disso, netAmount e null e feeAmount e 0.
O Minstrel nunca recalcula o liquido para gravar: o adquirente arredonda a comissao do jeito dele, e prometer a um recebedor um valor que o adquirente nao confirmou seria pior do que mostrar que ainda nao ha. O que o simulador mostra e so estimativa.
Captura e estorno com split
| Operacao | O que acontece com a divisao |
|---|---|
| Autorizacao com captura automatica | Cada parcela e capturada por inteiro (capturedAmount igual a amount). |
| Captura total | Envia as parcelas gravadas na autorizacao, sem recalcular. |
| Captura parcial | O valor capturado e dividido na mesma proporcao do autorizado, com a parte da conta principal como mais um peso. A soma das partes e exatamente o valor capturado, ao centavo. |
| Cancelamento da autorizacao | Desfaz a venda inteira. O adquirente nao recebe divisao: ele devolve cada parte sozinho. |
| Estorno total | Nada devolvido antes e valor igual ao capturado: sem divisao, o adquirente desfaz tudo. |
| Estorno parcial | O valor sai de cada parcela na proporcao do que ainda resta nela; o adquirente recebe so a parte dos recebedores e o resto sai da parte do lojista principal. |
Exemplo: R$ 100,00 autorizados com R$ 60,00 para A, R$ 20,00 para B e R$ 20,00 na conta principal.
- Captura de R$ 50,00: A leva R$ 30,00, B R$ 10,00 e a conta principal R$
10,00.
capturedAmountde A e B fica em 3000 e 1000. - Depois da captura total, estorno parcial de R$ 25,00: A devolve R$ 15,00, B
R$ 5,00 e a conta principal R$ 5,00.
refundedAmountde A e B soma 1500 e 500, e um segundo estorno divide pelo saldo que sobrou.
capturedAmount e refundedAmount de cada parcela acompanham o pagamento nas
respostas e nos eventos. Nenhuma parcela e debitada alem do que ainda tem.
Na Cielo, o cancelamento parcial tem uma trava propria: um por transacao a
cada 24 horas, e so ocorre se houver saldo na agenda. O Minstrel nao a aplica
por conta propria; o segundo estorno parcial dentro do prazo e recusado pela
Cielo e fica registrado como failed em refunds.
Split na Cielo
O Split de Pagamento da Cielo executa a divisao no proprio adquirente. O passo a passo da conta, com onde gerar o Client Secret, esta em Conectores. O que muda para quem integra:
- Toda operacao da conta e uma operacao de Split. Com
splitEnabled, a autorizacao, a captura, o cancelamento, o estorno e a consulta usam o tipoSplittedCreditCardouSplittedDebitCarde autenticam por OAuth2 Bearer (Merchant ID mais o Client Secret do Split), em vez de so Merchant ID e Merchant Key. Uma venda sem parcelas nessa conta tambem vai como Split, sem divisao: o valor inteiro fica com o lojista principal. - A lista da Cielo inclui o lojista principal. Cada recebedor entra com o
valor bruto e os
Faresda comissao; o que sobra da venda entra como a parte do lojista principal, para a soma fechar exatamente o valor da operacao. - O recebedor é um seller da Cielo. O
externalRecipientIdprecisa ser oSubordinateMerchantIddele, um GUID. O Minstrel envia o cadastro pela API de onboarding e consulta sua aprovação final, incluindo a validação bancária. Também é possível importar um ID existente, sujeito à mesma consulta. Veja Cadastro em cada parceiro. Seller não aprovado permanece bloqueado para split; uma recusa da Cielo pode retornar erro 326. liableForChargebackechargeProcessingFeenao tem equivalente. Na Cielo todo chargeback e do lojista principal, e as tarifas do Split saem sempre da agenda dele, nunca do seller.- Erros do Split nunca sao recusa do emissor. Os codigos 326, 298, 193 e 194
e os
ReasonCode37 a 41 e 104 viram erro tecnico nao retentavel, com a explicacao em portugues, porque repetir a venda ou tentar outra conta nao os resolve (veja Catalogo de erros).
No Sandbox
O Minstrel Sandbox executa o split sempre, sem contrato e sem interruptor na conta, para testar o fluxo inteiro. O recebedor pode ter qualquer id de texto: o formato GUID e exigencia da Cielo, nao do Sandbox.
- O liquido de cada recebedor e o bruto menos o percentual da comissao
(arredondado, com meio centavo para cima) menos a tarifa fixa, sem passar de
zero:
bruto - round(bruto x basis points / 10000) - tarifa fixa. Sem comissao, o liquido e o proprio bruto. - Parcela fora do contrato (valor zero ou negativo, soma acima do valor da
operacao) e falha tecnica nao retentavel (
connector_contract_violation), como o adquirente real faria. - Cancelamento e estorno aceitam a divisao por recebedor e so a validam.
No construtor de fluxos
O no Split divide o valor com as mesmas regras e o mesmo calculo. Ele
precisa vir antes da rota, porque as instrucoes viajam com a autorizacao.
Um Split depois da rota grava a divisao, mas a autorizacao ja saiu sem ela: a
validacao avisa com split_after_route. E um aviso, nao um erro - a
publicacao segue e devolve o aviso em warnings.
A rota que vem depois do Split tambem precisa levar a uma conta que executa
o split. Se nenhuma conta candidata de uma rota a jusante do Split executa a
divisao (split desligado na conta, ou recebedor nao registrado nela), a
publicacao segue e devolve em warnings um aviso invalid_node_config, com
severity: "warning", o id da rota em nodeId e field: "candidates". A
mensagem diz o que falta em cada conta e que os pagamentos que passarem ali
serao recusados com split_not_supported, em vez de autorizados sem a divisao.
Basta uma conta capaz na rota para o aviso sumir: o roteador a escolhe. Veja
Fluxos.
A publicacao recusa com 422 (flow_error, codigo flow_invalid_graph):
- recebedor repetido no mesmo no;
- percentuais acima de 100%;
- recebedor dos centavos (
remainderRecipientId) fora das regras; - recebedor inexistente no ambiente ou removido;
- recebedor inativo.
Os tres primeiros vem em meta.issues, com o no e o campo de cada problema; os
dois ultimos, com os ids em meta.missingRecipientIds e
meta.inactiveRecipientIds.
So uma coisa aparece apenas na execucao: parcelas fixas acima do valor, que so
e conhecido no pagamento. Nesse caso a requisicao falha com o mesmo 422 da
tabela de erros e o pagamento fecha como failed, com o evento
payment.failed - nunca fica preso em processing. Confira as regras no
simulador antes de publicar.
No editor do painel, ao escolher o recebedor, a regra padrao, o chargeback e a
taxa vem do cadastro dele. No grafo salvo os valores ficam explicitos: um no
criado pela API sem liableForChargeback e chargeProcessingFee usa false.
O modelo Marketplace com split ("template": "marketplace-split" em
POST /v1/flows) ja vem na ordem certa: gatilho, Split, rota e captura. Ele
divide 10% para a plataforma e 90% para o vendedor, com os centavos para a
plataforma. Troque os ids de exemplo (rcp_plataforma, rcp_vendedor e
ca_subadquirente_split) pelos seus antes de publicar; a conta tem de ser uma
que executa o split. Como o que nao e dividido fica com a conta principal, voce
tambem pode manter so a parcela do vendedor e deixar a comissao com a conta
principal.
Tarifa de processamento
chargeProcessingFee e gravado em cada parcela e enviado ao conector, mas o
rateio da tarifa de processamento da venda entre os recebedores ainda nao e
calculado. O feeAmount de cada parcela e outra coisa: e o que o adquirente
descontou do recebedor na divisao (comissao e tarifas do Split), como descrito em
Liquido e tarifa. O simulador avisa com
fees_not_calculated quando alguma regra marca o campo.
Simule antes de cobrar
POST /v1/recipients/split-preview calcula com a mesma funcao do motor de
pagamentos, sem gravar nada (escopo recipients:read):
curl -X POST http://localhost:3333/v1/recipients/split-preview \
-H "Authorization: Bearer $MINSTREL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 10003,
"rules": [
{ "recipientId": "rcp_vendedor", "type": "percentage", "value": 2500 },
{ "recipientId": "rcp_parceiro", "type": "percentage", "value": 2500 }
],
"remainderRecipientId": "rcp_parceiro"
}'
Resposta (resumida):
{
"object": "split_preview",
"amount": 10003,
"currency": "BRL",
"valid": true,
"parts": [
{
"recipientId": "rcp_vendedor",
"name": "Loja do Vendedor ME",
"source": "request",
"amount": 2500,
"effectiveBps": 2499,
"roundingCents": 0
},
{
"recipientId": "rcp_parceiro",
"name": "Parceiro Exemplo",
"source": "request",
"amount": 2501,
"effectiveBps": 2500,
"roundingCents": 1
}
],
"total": 5001,
"fixedTotal": 0,
"percentageTotalBps": 5000,
"remainingForPercentages": 10003,
"mainAccountAmount": 5002,
"roundingCents": 1,
"issues": [
{
"severity": "info",
"code": "main_account_share",
"message": "A conta principal fica com 5002 centavos: a parte que nao foi dividida."
},
{
"severity": "info",
"code": "rounding_cents",
"ruleIndex": 1,
"message": "Os percentuais nao dividem a venda em centavos exatos: 1 centavo(s) de arredondamento vao para Parceiro Exemplo."
}
]
}
Diferencas em relacao ao pagamento, pensadas para a tela de simulacao:
- regra sem
typeevalueusa a regra padrao do recebedor (source: "default"); - regra com
labele semrecipientIdvale so para simular ("Plataforma", por exemplo); - configuracao invalida nao vira erro HTTP: a resposta e
200comvalid: false, os valores nulos e os problemas emissues. So o corpo mal formado (mais de 20 regras,typesemvalue) responde422; - recebedor com comissao cadastrada traz
commission,estimatedCommissioneestimatedNetAmountna parcela. A estimativa arredonda o percentual no centavo (meio centavo para cima, como o Sandbox liquida), soma a tarifa fixa e nunca passa da parcela. Sem comissao cadastrada, as duas estimativas vemnull: o liquido depende do acordo no adquirente, que o Minstrel nao conhece. O simulador nao consulta o adquirente nem verifica se a conta executa o split.
code | Severidade | Significado |
|---|---|---|
recipient_not_found | error | Recebedor inexistente no ambiente ou removido. |
recipient_inactive | error | Recebedor inativo: o pagamento seria recusado. |
rule_incomplete | error | Regra sem type e value, e o recebedor nao tem regra padrao. |
duplicate_recipient | error | Recebedor em mais de uma parcela. |
remainder_not_in_rules | error | Recebedor dos centavos fora das parcelas. |
fixed_exceeds_amount | error | Parcelas fixas acima do valor. |
percentage_over_100 | error | Percentuais acima de 100%. |
fixed_first | info | Ha fixas e percentuais: as fixas saem primeiro e os percentuais valem sobre o resto. |
main_account_share | info | Quanto fica com a conta principal (meta.amount e meta.bps). |
rounding_cents | info | Centavos de arredondamento e quem fica com eles. |
unregistered_rules | info | Ha regra sem recebedor cadastrado: serve para simular, nao para cobrar. |
net_is_estimate | info | Algum recebedor tem comissao cadastrada: o liquido mostrado e estimativa, e vale o que o adquirente informar na liquidacao. |
fees_not_calculated | info | Alguma regra marca chargeProcessingFee, cujo rateio entre recebedores ainda nao e calculado. |
effectiveBps e a participacao efetiva de cada parcela na venda, em basis
points, so para exibicao.
Saldo do recebedor
GET /v1/recipients e GET /v1/recipients/:id trazem o valor a receber em
stats.toReceive, com a origem do numero em source:
ledger: saldo do razao contabil (creditos menos debitos da conta do recebedor);estimate: estimativa - parcelas de pagamentos capturados, menos as revertidas, as tarifas e os repasses registrados.
Hoje nenhum processo grava lancamentos de recebedor no razao nem repasses, entao
o numero vem como estimate. Na estimativa, estorno total reverte a parcela
inteira; chargeback reverte so a parcela de quem tem liableForChargeback; e
estorno parcial e captura parcial ainda nao entram na estimativa, embora cada
parcela do pagamento ja traga capturedAmount e refundedAmount. Em
GET /v1/recipients/:id/splits, cada parcela diz como entrou na conta em
effect: counted, reversed, awaiting_capture, in_progress ou
not_captured.
Eventos
| Evento | Quando acontece |
|---|---|
recipient.created | Recebedor cadastrado. |
recipient.updated | Dados alterados. previousAttributes traz os valores anteriores, com documento, conta e chave Pix mascarados. |
recipient.deleted | Recebedor removido. Os splits gravados continuam no historico; pagamentos novos nao podem usa-lo. |
recipient.registration_updated | Cadastro por parceiro criado, enviado ou com situação alterada; informa conta, estado e campos pendentes, sem dados adicionais de KYC. |
Nos eventos de criação, edição e remoção, data.object traz o recebedor na versão mascarada: webhook
sai da nossa infraestrutura e nao precisa do numero da conta para cumprir o seu
papel. Veja Webhooks.