Webhooks
Os webhooks notificam a sua aplicação, em tempo real, sobre o desfecho das operações. Você registra uma URL, escolhe os eventos e recebe um POST assinado a cada ocorrência. Todos os endpoints são escopados às credenciais do parceiro, e cada entrega carrega o accountId da conta envolvida, para você rotear internamente.
Eventos disponíveis
Todos os eventos abaixo são de fato emitidos pela plataforma. O catálogo em GET /webhooks/events devolve exatamente esta lista.
PIX
| Evento | Quando dispara |
|---|---|
pix.charge.created | Cobrança ou QR criado |
pix.charge.paid | Cobrança paga, PIX de entrada creditado |
pix.charge.expired | Cobrança ou QR expirou sem pagamento |
pix.charge.cancelled | Cobrança ou QR foi cancelado antes do pagamento |
pix.payout.queued | PIX de saída enfileirado para processamento |
pix.payout.processing | PIX de saída em processamento (aceite intermediário) |
pix.payout.held | PIX de saída aceito pelo trilho e ainda sem desfecho; não reenvie |
pix.payout.confirmed | PIX de saída liquidado |
pix.payout.failed | PIX de saída rejeitado ou expirado |
pix.payout.returned | PIX de saída devolvido |
pix.payout.return.failed | Tentativa de devolução do PIX de saída rejeitada; nenhum saldo foi devolvido |
pix.refund.requested | Devolução de PIX solicitada |
pix.refund.completed | Devolução de PIX concluída |
pix.refund.failed | Devolução de PIX rejeitada |
pix.return.received | Devolução recebida |
pix.received | PIX recebido na conta, sem cobrança emitida |
Chaves PIX
| Evento | Quando dispara |
|---|---|
pix.key.registered | Chave PIX registrada |
pix.key.deleted | Chave PIX excluída |
pix.key.blocked | Chave PIX bloqueada |
pix.key.unblocked | Chave PIX desbloqueada |
Portabilidade
| Evento | Quando dispara |
|---|---|
pix.claim.created | Reivindicação de portabilidade criada |
pix.claim.acknowledged | Reivindicação reconhecida |
pix.claim.confirmed | Reivindicação confirmada |
pix.claim.cancelled | Reivindicação cancelada |
pix.claim.completed | Reivindicação concluída |
TED e transferências
| Evento | Quando dispara |
|---|---|
ted.confirmed | TED liquidada |
ted.failed | TED rejeitada ou expirada |
ted.received | TED recebida na conta |
ted.refund.requested | Devolução de TED recebida solicitada |
ted.refund.completed | Devolução de TED recebida liquidada |
ted.refund.failed | Devolução de TED recebida rejeitada |
transfer.confirmed | Transferência interna concluída |
transfer.failed | Transferência interna falhou |
transfer.received | Transferência interna recebida |
tef.transfer.sent | Alias público da transferência interna liquidada na origem |
tef.transfer.received | Alias público da transferência interna liquidada no destino |
tef.transfer.failed | Alias público da transferência interna que falhou |
Infrações (MED)
| Evento | Quando dispara |
|---|---|
pix.infraction.created | Infração/MED aberta sobre uma conta |
pix.infraction.resolved | Infração analisada e resolvida |
pix.infraction.updated | Relato de infração atualizado (reconhecimento, análise ou detalhes) |
pix.infraction.defense_submitted | Defesa da infração enviada pelo cliente |
pix.med.created | Intervenção MED aberta pela Partner API |
pix.med.completed | Recuperação MED concluída, fundos devolvidos |
pix.med.cancelled | Intervenção MED cancelada |
pix.med.updated | Intervenção MED com estado atualizado (rastreamento, análise, devolução em curso) |
pix.med.refund.created | Pedido de devolução (refund) aberto dentro de uma recuperação MED |
pix.med.refund.updated | Pedido de devolução MED com estado atualizado |
pix.med.refund.closed | Pedido de devolução MED encerrado com análise |
pix.med.refund.cancelled | Pedido de devolução MED cancelado |
Tarifas
| Evento | Quando dispara |
|---|---|
fee.charged | Tarifa cobrada de uma conta |
Contas
| Evento | Quando dispara |
|---|---|
account.created | Conta criada |
account.blocked | Conta bloqueada |
account.unblocked | Conta desbloqueada |
account.closed | Conta encerrada |
Teste
| Evento | Quando dispara |
|---|---|
webhook.test | Entrega de teste manual |
Os eventos de sucesso (pix.charge.paid, pix.payout.confirmed, pix.refund.completed, pix.return.received) só são entregues depois que a operação está liquidada.
Registrar um webhook
http
POST /api/partner/v1/webhooks
Authorization: Bearer {{access_token}}
Content-Type: application/json
{
"url": "https://sua-aplicacao.com.br/webhooks/vulci",
"events": ["pix.payout.confirmed", "pix.payout.failed", "pix.charge.paid"],
"description": "Integração principal",
"is_active": true
}- Escopo:
webhook:write· Obrigatórios:url,events
Resposta 201:
json
{
"data": {
"id": "0f7f279c-217b-4ba2-9a96-27d7401dfe2f",
"url": "https://sua-aplicacao.com.br/webhooks/vulci",
"events": ["pix.payout.confirmed", "pix.payout.failed", "pix.charge.paid"],
"description": "Integração principal",
"is_active": true,
"created_at": "2026-07-10T13:00:00Z",
"updated_at": "2026-07-10T13:00:00Z"
}
}Segredo de assinatura
O cadastro não devolve o segredo de assinatura. Para obter (ou trocar) o segredo, chame POST /webhooks/:id/rotate-secret, que devolve o segredo em texto puro uma única vez. Guarde-o com segurança.
A URL precisa ser pública, http ou https, e não pode apontar para endereços privados ou internos.
Obter e rotacionar o segredo
http
POST /api/partner/v1/webhooks/{id}/rotate-secret
Authorization: Bearer {{access_token}}- Escopo:
webhook:write
json
{ "message": "Secret rotacionado com sucesso", "webhook_id": "0f7f...", "new_secret": "3e071f7ee1ef00db1178a96b65476db0..." }O new_secret é exibido só nesta resposta. Uma nova rotação invalida o anterior.
Gerenciar webhooks
http
GET /api/partner/v1/webhooks # listar (webhook:read)
GET /api/partner/v1/webhooks/{id} # detalhar (webhook:read)
PUT /api/partner/v1/webhooks/{id} # atualizar url/events/description/is_active (webhook:write)
DELETE /api/partner/v1/webhooks/{id} # remover, responde 204 (webhook:write)
POST /api/partner/v1/webhooks/{id}/test # enviar entrega de teste (webhook:write)
POST /api/partner/v1/webhooks/{id}/replay # reenviar a última entrega (webhook:write)
GET /api/partner/v1/webhooks/events # catálogo de eventos (webhook:read)replay responde 404 quando ainda não há nenhuma entrega para reenviar.
Formato da entrega
Cada evento chega como um POST na URL configurada. O corpo é o JSON do evento, plano (sem envelope) e com as chaves em camelCase, e os metadados vão nos headers:
| Header | Descrição |
|---|---|
X-Monetarie-Event-Type | Tipo do evento, por exemplo pix.payout.confirmed |
X-Monetarie-Event-Id | Identificador da entrega, para deduplicação |
X-Monetarie-Timestamp | Instante da assinatura, em segundos Unix |
X-Monetarie-Signature | Assinatura sha256=<hex> |
User-Agent | VULCI Banco-Webhook/1.0 |
Identifique o evento pelo header X-Monetarie-Event-Type; o corpo não repete o tipo. Deduplique pelo X-Monetarie-Event-Id, porque a mesma entrega pode chegar mais de uma vez.
Payload de cada evento
Todos os corpos usam chaves em camelCase e todos os valores monetários estão em unidades-base (1 BRL = 10.000 unidades-base). Divida por 10.000 para exibir em reais: 505500 equivale a R$ 50,55. Essa regra vale somente para a saída dos webhooks; os valores de entrada aceitos pelos endpoints da Partner API continuam em centavos. Os campos abaixo são os que a sua integração precisa; um evento pode trazer campos informativos adicionais, então localize sempre pela chave, nunca pela posição.
PIX de saída
Vale para pix.payout.queued, pix.payout.processing, pix.payout.confirmed e pix.payout.failed. O que muda entre eles é o status.
json
{
"accountId": 1042,
"transactionId": "PIX20260711a1b2c3d4e5f6",
"endToEndId": "E9999900820260711100000abcdef123",
"amount": 25000,
"status": "settled",
"errorReason": null
}| Evento | status |
|---|---|
pix.payout.queued | queued |
pix.payout.processing | processing |
pix.payout.confirmed | settled |
pix.payout.failed | rejected, com o motivo em errorReason |
pix.payout.held é um estado intermediário: o trilho aceitou o envio, mas a liquidação ainda não terminou. Não crie outra transferência; aguarde pix.payout.confirmed ou pix.payout.failed.
json
{
"accountId": 1042,
"transactionId": "PIX20260711a1b2c3d4e5f6",
"endToEndId": "E9999900820260711100000abcdef123",
"amount": 25000,
"status": "processing",
"reason": "awaiting_settlement",
"spiStatus": "ACSP",
"heldSince": "2026-07-11T10:01:00Z"
}Devolução de PIX de saída
pix.payout.returned avisa que um PIX que você enviou foi devolvido pelo recebedor. Traz o valor devolvido em amount (pode ser parcial) e status: "returned". transactionId, endToEndId, originalTransactionId, originalEndToEndId e externalId identificam a operação original; returnId identifica a devolução no arranjo PIX.
json
{
"accountId": 1042,
"transactionId": "PIXOUT20260718a1b2c3d4e5f6a7b8c9d0",
"endToEndId": "E9999900820260711100000abcdef123",
"originalTransactionId": "PIXOUT20260718a1b2c3d4e5f6a7b8c9d0",
"originalEndToEndId": "E9999900820260711100000abcdef123",
"externalId": "order-456",
"returnId": "D99999008202607181015aabbccddeef",
"amount": 25000,
"reason": "Devolução solicitada pelo pagador",
"status": "returned"
}pix.payout.return.failed avisa que uma tentativa da contraparte de devolver o PIX foi rejeitada antes da liquidação. Esse evento é operacional e não financeiro: refundedAmount é sempre 0, o PIX original continua liquidado e o saldo não muda. Correlacione por externalId, originalTransactionId, originalEndToEndId e returnId.
Por compatibilidade, webhooks já assinados em pix.payout.returned também recebem esse desfecho negativo, mas com o tipo verdadeiro pix.payout.return.failed. Recomendamos adicionar o evento explicitamente à assinatura; assiná-lo pelos dois nomes não duplica a entrega lógica.
json
{
"accountId": 1042,
"transactionId": "PIXOUT20260718a1b2c3d4e5f6a7b8c9d0",
"endToEndId": "E9999900820260711100000abcdef123",
"originalTransactionId": "PIXOUT20260718a1b2c3d4e5f6a7b8c9d0",
"originalEndToEndId": "E9999900820260711100000abcdef123",
"externalId": "order-456",
"returnId": "D99999008202607181015aabbccddeef",
"amount": 25000,
"status": "rejected",
"reasonCode": "AB03",
"reasonDescription": "Pagamento expirado por timeout",
"refundedAmount": 0
}Devolução solicitada, concluída e rejeitada
pix.refund.requested é emitido quando você solicita a devolução de um PIX recebido. O campo endToEndId carrega o identificador da transação original que está sendo devolvida.
json
{
"accountId": 1042,
"transactionId": "PIXRET20260711aa11bb22",
"endToEndId": "PIXIN20260710090000ffee00112",
"amount": 25000,
"status": "requested"
}pix.refund.completed confirma a liquidação de uma devolução iniciada por você. pix.refund.failed informa a rejeição: o valor permanece na conta e volta a compor o restante devolvível. Os campos transactionId/endToEndId continuam identificando a devolução para preservar o contrato existente; os campos refundTransactionId/refundEndToEndId tornam essa identidade explícita. Correlacione a ordem original por originalTransactionId, originalEndToEndId, originalExternalId e externalId.
json
{
"accountId": 1042,
"transactionId": "PIXRET20260711aa11bb22",
"endToEndId": "D99999008202607111000aabbccddeef",
"refundTransactionId": "PIXRET20260711aa11bb22",
"refundEndToEndId": "D99999008202607111000aabbccddeef",
"returnId": "D99999008202607111000aabbccddeef",
"originalTransactionId": "PIXIN20260710090000ffee00112",
"originalEndToEndId": "E9999900820260710090000ffee00112",
"externalId": "charge-123",
"originalExternalId": "charge-123",
"amount": 25000,
"status": "rejected",
"errorReason": "Devolução rejeitada pela instituição do pagador original",
"recipient": null
}Cobrança criada
pix.charge.created confirma a criação de uma cobrança ou QR. Traz o BR Code pronto para pagamento em brcode.
json
{
"accountId": 1042,
"txId": "vulci-7f3a1c9e4b",
"amount": 15000,
"status": "active",
"brcode": "00020101021226880014br.gov.bcb.pix...6304AB12",
"expiresAt": "2026-07-11T11:00:00Z"
}Cobrança expirada ou cancelada
pix.charge.expired é automático quando o prazo do QR termina sem pagamento; pix.charge.cancelled é emitido quando o merchant cancela o QR antes do pagamento. Em ambos, amount está em unidades-base.
json
{
"accountId": 1042,
"entityId": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"txId": "vulci-7f3a1c9e4b",
"externalId": "pedido-4210",
"amount": 15000,
"status": "expired",
"expiredAt": "2026-07-11T11:00:00Z"
}No cancelamento, o status é cancelled e o instante vem em cancelledAt.
PIX recebido
pix.charge.paid confirma o pagamento de uma cobrança sua. Correlacione pelo txId da cobrança e pelo externalId, quando informado na criação.
json
{
"accountId": 1042,
"entityId": 987,
"txId": "vulci-7f3a1c9e4b",
"externalId": "pedido-4210",
"endToEndId": "E9999900820260711100500aa00bb11c",
"amount": 15000,
"description": "Pedido 4210",
"paidAt": "2026-07-11T10:05:00Z"
}Devolução recebida
pix.return.received avisa que uma devolução caiu na conta. Pode ser parcial, sinalizado por isPartial.
json
{
"accountId": 1042,
"endToEndId": "E9999900820260710090000ffee00112",
"amount": 12000,
"originalAmount": 25000,
"refundedAmount": 12000,
"isPartial": true,
"returnReason": "MD06",
"status": "settled"
}PIX recebido sem cobrança
pix.received avisa um PIX que caiu na conta sem uma cobrança emitida, como uma transferência direta para uma chave da conta. Quando o crédito vem de uma cobrança sua, o evento é pix.charge.paid.
json
{
"accountId": 10024270,
"amount": 454,
"endToEndId": "E9999900820260714210000aabbccdd0",
"payerName": "MARIA DA SILVA",
"payerIspb": "00416968",
"payerDocument": "12345678901",
"receivedAt": "2026-07-14T21:00:00Z"
}Ciclo de vida da chave PIX
pix.key.registered, pix.key.deleted, pix.key.blocked e pix.key.unblocked acompanham as chaves da conta e compartilham o mesmo formato; o pix.key.blocked inclui também o campo reason.
json
{
"accountId": 10024270,
"keyType": "CPF",
"keyValue": "12345678901",
"occurredAt": "2026-07-14T22:00:00Z"
}Reivindicação de portabilidade
pix.claim.created avisa a criação de uma reivindicação de portabilidade de chave. pix.claim.acknowledged, pix.claim.confirmed, pix.claim.cancelled e pix.claim.completed têm o mesmo formato e acompanham as etapas seguintes.
json
{
"accountId": 10024270,
"claimId": "CLAIM-...",
"claimType": "PORTABILITY",
"keyType": "CPF",
"keyValue": "12345678901",
"donorIspb": "99999008",
"claimerIspb": "60746948",
"donorDeadline": "2026-07-21T22:00:00Z",
"claimerDeadline": "2026-08-13T22:00:00Z",
"occurredAt": "2026-07-14T22:00:00Z"
}TED
ted.confirmed e ted.failed acompanham o desfecho de uma TED enviada.
json
{
"accountId": 1042,
"transactionId": "TED20260711d8a3695bc594e2577c23",
"type": "ted",
"amount": 25000,
"status": "settled",
"errorReason": null
}O status é settled no ted.confirmed, e rejected ou timeout no ted.failed, com o motivo em errorReason.
TED recebida
ted.received avisa que uma TED de outra instituição foi creditada na conta.
json
{
"accountId": 10024270,
"amount": 150075,
"numCtrlStr": "STR20260714000000123",
"messageType": "STR0008",
"senderIspb": "60746948",
"senderName": "JOAO PEREIRA",
"senderDocument": "12345678901",
"senderAgency": "0001",
"senderAccount": "445566",
"receivedAt": "2026-07-14T21:00:00Z"
}Devolução de TED recebida
ted.refund.requested confirma o aceite da devolução de uma TED recebida que você comandou; ted.refund.completed avisa a liquidação da devolução no SPB e ted.refund.failed avisa que a devolução não foi concluída e o valor reservado voltou a ficar disponível na conta. Correlacione pelo numCtrlStr do crédito original.
json
{
"accountId": 10024270,
"amount": 150075,
"numCtrlStr": "STR20260714000000123",
"reasonCode": "70",
"status": "processing"
}No ted.refund.completed a entrega traz também spbNumCtrl, o número de controle da mensagem de devolução (STR0010), e não repete o campo status. No ted.refund.failed vêm errorCode e errorMessage com o motivo reportado pelo SPB.
Transferência interna
transfer.confirmed e transfer.failed acompanham a transferência entre duas contas do parceiro.
json
{
"accountId": 1042,
"destinationAccountId": 1043,
"transactionId": "TEF20260711aabbccddeeff",
"type": "internal",
"amount": 505500,
"status": "settled"
}Transferência interna recebida
transfer.received é a perna de crédito da transferência interna, entregue para a conta que recebeu. sourceAccountId identifica a conta de origem.
json
{
"accountId": 10024271,
"sourceAccountId": 10024270,
"transactionId": "TEF20260714aabbccddeeff",
"type": "internal",
"amount": 505500,
"status": "settled"
}Aliases públicos de TEF interna
tef.transfer.sent, tef.transfer.received e tef.transfer.failed são os nomes públicos compatíveis do mesmo ciclo de transfer.confirmed, transfer.received e transfer.failed. O primeiro confirma a origem, o segundo confirma o destino e o terceiro traz failureReason e failedAt. Assine apenas uma família de nomes se não quiser duas notificações do mesmo fato.
json
{
"accountId": 1042,
"senderAccountId": 1042,
"receiverAccountId": 1043,
"transactionId": "TEF20260711aabbccddeeff",
"amount": 505500,
"description": "Repasse interno",
"settledAt": "2026-07-11T10:05:00Z"
}Infração (MED)
pix.infraction.created avisa a abertura de uma infração ou MED sobre uma conta, e pix.infraction.resolved traz o resultado da análise.
json
{
"accountId": 1042,
"infractionId": "b17c9a02-4a2f-4d5e-9b1a-77e0a1c2d3e4",
"blockId": "3f21aa8c-1b2c-4d5e-8f90-0a1b2c3d4e5f",
"endToEndId": "E9999900820260711100000abcdef123",
"amount": 25000,
"status": "created",
"fraudCategory": "SCAM"
}O status é created na abertura, e founded ou unfounded na resolução.
Defesa da infração
pix.infraction.defense_submitted confirma o registro da defesa enviada pelo cliente para uma infração com bloqueio cautelar. blockId identifica o bloqueio; o desfecho da análise chega por pix.infraction.resolved.
json
{
"accountId": 1042,
"infractionId": "b17c9a02-4a2f-4d5e-9b1a-77e0a1c2d3e4",
"blockId": "3f21aa8c-1b2c-4d5e-8f90-0a1b2c3d4e5f",
"endToEndId": "E9999900820260711100000abcdef123",
"status": "defense_submitted"
}Intervenção MED
pix.med.created confirma a abertura de uma intervenção MED solicitada pela Partner API. pix.med.completed avisa que a recuperação concluiu com a devolução dos fundos, e pix.med.cancelled avisa o cancelamento. endToEndId carrega a transação raiz da intervenção.
json
{
"accountId": 1042,
"medId": "REC-a1b2c3d4",
"endToEndId": "E9999900820260711100000abcdef123",
"amount": 25000,
"status": "REFUND_COMPLETED"
}O status é CREATED na abertura, REFUND_COMPLETED ou COMPLETED na conclusão e CANCELLED no cancelamento. O campo amount (unidades-base) vem nos desfechos apurados pelo arranjo; na abertura e no cancelamento comandados pela API a entrega pode vir sem ele.
Tarifa cobrada
fee.charged avisa que uma tarifa foi cobrada de uma conta. originTransactionId e originalAmount apontam para a transação que originou a cobrança.
json
{
"feeTransactionId": "5f6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b8c",
"accountId": 10024270,
"feeType": "ted_out",
"amount": 500,
"originTransactionId": "E9999900820260714210000aabbccdd0",
"originTransactionType": "ted",
"originalAmount": 150075,
"status": "posted",
"chargedAt": "2026-07-14T21:00:00Z"
}Conta criada
account.created avisa a abertura de uma conta. O status pode ser active ou blocked, conforme a verificação cadastral.
json
{
"accountId": 10024272,
"customerId": 4711,
"accountNumber": "100123-4",
"agency": "0001",
"iban": "BR9199999008000010010012345P1",
"accountType": "payment",
"status": "active"
}Bloqueio, desbloqueio e encerramento de conta
account.blocked, account.unblocked e account.closed compartilham o mesmo formato. O status é blocked no bloqueio, active no desbloqueio e closed no encerramento.
json
{
"accountId": 10024272,
"status": "blocked"
}Teste
webhook.test é a entrega manual, útil para validar a sua URL e a verificação de assinatura. O POST /webhooks/{id}/test entrega o evento somente ao webhook informado no caminho, mesmo que ele não assine webhook.test; nenhum outro webhook recebe a entrega de teste.
json
{
"message": "Test webhook delivery",
"timestamp": "2026-07-11T10:00:00Z",
"webhookId": "0f7f279c-217b-4ba2-9a96-27d7401dfe2f"
}Validar a assinatura
A assinatura é um HMAC-SHA256, em hexadecimal minúsculo, sobre a string "{timestamp}.{corpo_bruto}", usando o segredo do webhook. O header vem como sha256=<hex>. Compare o valor calculado com o header, descartando o prefixo sha256=. Use o corpo bruto recebido, sem reserializar o JSON.
javascript
const crypto = require('crypto')
function verificar(corpoBruto, headerAssinatura, timestamp, segredo) {
const conteudo = `${timestamp}.${corpoBruto}`
const esperado = crypto.createHmac('sha256', segredo).update(conteudo).digest('hex')
return `sha256=${esperado}` === headerAssinatura
}Rejeite a entrega se a assinatura não conferir.
Reentrega automática
Uma entrega sem sucesso é retentada com backoff, em até 8 tentativas: imediato, 30s, 2min, 10min, 30min, 1h, 2h e 4h. Responda 2xx para confirmar o recebimento. As respostas 400, 401, 403, 404, 410 e 422 são tratadas como falha permanente, sem retentativa.
Falhas de recebimento e devolução MED
| Evento | Descrição / Description / Descripción |
|---|---|
pix.received.failed | Recebimento PIX recusado; não houve crédito confirmado |
pix.med.return_rejected | Tentativa de devolução MED recusada; não confirma restituição |
pix.received.failed informa a recusa do PIX de entrada. pix.med.return_rejected informa a recusa de uma tentativa de devolução vinculada ao MED. Nenhum dos dois confirma dinheiro creditado ou devolvido. Consulte a operação e trate o motivo; não transforme esse aviso em uma nova ordem automática de pagamento.
Os exemplos são sintéticos. amount usa unidades-base (1 real = 10.000); campos sem informação podem ser nulos. Na devolução, returnId identifica a tentativa e returnStage/status ficam rejected. occurredAt, quando presente, é a data do fato de origem, não a data do reenvio do webhook.
pix.received.failed
json
{
"eventType": "pix.received.failed",
"accountId": 1042,
"endToEndId": "E0000000020260922120000SYNTHETIC001",
"txId": null,
"status": "failed",
"amount": 1000000,
"reasonCode": "AB03",
"reasonDescription": "Recebimento recusado",
"debtorIspb": "00000000",
"creditorIspb": "00000001",
"creditorAccount": "1042",
"rejectedAt": "2026-09-22T12:00:00Z"
}pix.med.return_rejected
json
{
"eventType": "pix.med.return_rejected",
"accountId": 1042,
"returnId": "00000000-0000-4000-8000-000000000002",
"endToEndId": "E0000000020260922120000SYNTHETIC001",
"amount": 1000000,
"status": "rejected",
"medId": "REC-SYNTHETIC",
"returnStage": "rejected",
"reasonCode": "AC06",
"reasonDescription": "Devolução recusada",
"rejectedAt": "2026-09-22T12:00:00Z",
"occurredAt": "2026-09-22T12:00:00Z"
}