Skip to main content
Webhooks let your system react to transfer events in real time, without polling. The plugin sends a notification to your endpoint when a transfer completes, fails, or needs attention.

Available events


Each event lists the transfer types it applies to (in parentheses), when it fires, and the recommended action.

Transfer lifecycle (TED OUT, P2P)

transfer.initiated (TED OUT)

  • Trigger: the plugin created the TED OUT transfer record after it confirmed the initiation.
  • Action: update the transfer status in your system. Show “transfer in progress” to the customer.

transfer.processing_started (TED OUT)

  • Trigger: the TED OUT transfer entered processing (status path CREATED to PENDING to PROCESSING).
  • Action: show the customer that the transfer is in progress.

transfer.rejected (TED OUT)

  • Trigger: JD SPB rejected the transfer request before acceptance (invalid data or rule violation).
  • Action: notify the customer of the rejection. The plugin already cancelled the fund hold.

transfer.completed (P2P)

  • Trigger: the P2P transfer settled successfully.
  • Action: notify the customer. Generate a receipt. Update the balance display.

Reconciliation (TED OUT, TED IN)

transfer.reconciliation_required

  • Trigger: a transfer with an unknown outcome moved to reconciliation.
  • Action: track the transfer as pending. Do not assume success or failure.

transfer.reconciliation_resolved

  • Trigger: reconciliation finished and the transfer reached a final outcome.
  • Action: update the transfer to its final status.

transfer.reconciliation_exhausted

  • Trigger: reconciliation stopped after the maximum number of attempts.
  • Action: escalate the transfer for manual operator review.

transfer.reconciliation_failed

  • Trigger: a reconciliation attempt hit a deterministic error, which failed the transfer.
  • Action: treat the transfer as failed and investigate.

Incoming transfers (TED IN)

transfer_incoming.completed

  • Trigger: the plugin received an inbound TED, found the recipient, and applied the credit.
  • Action: notify the recipient that the funds arrived. Update the balance display.

transfer_incoming.chargeback

  • Trigger: a chargeback message arrived for a completed TED IN (STR0010R2).
  • Action: freeze the credited amount. Start a review with your compliance team.

transfer_incoming.undeliverable

  • Trigger: the plugin could not credit an inbound TED (for example, it did not find the recipient account).
  • Action: investigate the transfer. The plugin may return it to the origin bank.

Returns and initiation

transfer_outgoing.devolution_notified (TED OUT)

  • Trigger: a return (devolução) arrived for an outgoing transfer.
  • Action: reconcile the returned funds against the original transfer.

payment_initiation.created (TED OUT, P2P)

  • Trigger: the plugin created a payment initiation (the pre-transfer step).
  • Action: optional. Track initiations that await confirmation.
For TED OUT, the plugin does not emit transfer.completed yet. SPB confirms TED OUT completion asynchronously, and a future release will add this event. Until then, check TED OUT status with the Get Transfer endpoint or the reconciliation endpoint.

Configuring webhooks


Webhooks work per tenant. You register a destination in one of two ways. Self-service API (recommended). Register one or more HTTPS endpoints through the webhook registration API. The server generates a signingSecret on creation and returns it once. Store it securely. Use it to verify the signature on every delivered event. You can also list, update, disable, and delete registrations, rotate the signing secret, and look up the accepted event types. The plugin derives the owning tenant from the bearer token, never from a request header. Enabling delivery (operator/env). Set WEBHOOK_ENABLED=true to turn on outbound delivery. Delivery also requires RabbitMQ and the streaming outbox (STREAMING_ENABLED=true). Destinations come from the registrations above. There is no single static endpoint environment variable. You tune per-delivery behavior — timeout and max retries — at runtime through systemplane, not through env vars. See Bank Transfer configuration.

Payload structure


The plugin delivers each event as an HTTPS POST. The request body is the event payload as JSON. The event type and the signature travel in HTTP headers, not in the body. The body fields depend on the event type. Every payload carries tenantId, and transfer-scoped events also carry transferId. Amounts are decimal strings in the account currency, not centavos (for example, 100.00). Here is an example body for transfer.completed on a P2P transfer:
The transfer.completed payload carries the amounts, the accounts, and the midazTransactionId. For events with a smaller payload, or to read the full transfer record, fetch the transfer from Get Transfer with its transferId.
Payload fields differ per event type. To read every field of a transfer, use the Get Transfer endpoint.

Handling delivery failures


Your endpoint must respond with a 2xx status within 5 seconds (the webhook.timeout_ms default). If it does not, the plugin retries the delivery with exponential backoff and full jitter. After the first attempt, the plugin makes up to 3 more attempts (the webhook.max_retries default), which is 4 delivery attempts in total. The backoff base is 1 second and doubles per attempt. Full jitter applies to each delay: After all attempts fail (4 by default), the event moves to a dead-letter queue (DLQ). Set alerts on the DLQ to catch persistent delivery failures early. Tune webhook.max_retries through systemplane if your endpoint needs a longer or shorter retry budget. The webhook.retry_backoff_ms knob controls the broker reconnect backoff, not the per-delivery HTTP retry schedule above. For reliable delivery, follow these rules:
  • Respond within 5 seconds.
  • Use HTTPS with a valid certificate.
  • Return 200 even for events you ignore.
  • Move heavy processing to a background queue. Keep the webhook handler fast.

Idempotency


Your endpoint may receive the same event more than once. Use the transferId from the body and the X-Webhook-Event header to deduplicate. If you already processed that combination, return 200 and take no further action.

For developers


For signature validation code (JavaScript, Python, Go), retry implementation, and the full integration checklist, see the Bank Transfer developer guide.