Skip to main content

Overview

Due delivers lifecycle events (KYC, transfers, virtual accounts) to a URL you register. Webhooks are the recommended way to track status changes rather than checking state yourself. Unlike some integrations, Due webhook endpoints are managed through the Portal Custodian API, not a provider dashboard and not the Client API. You register a URL, subscribe to events, and verify each delivery with the endpoint’s Ed25519 public key.
These calls use a Custodian API key (Authorization: Bearer [custodian-api-key]), not a client session token. Endpoints are environment-scoped: register them separately for each environment (for example Development and Production). The shorthand paths below are relative to /api/v3/custodians/me/integrations/due.

1. List available events

GET /webhooks/events returns the event types you can subscribe to.

2. Create a webhook endpoint

POST /webhooks registers your URL. Pass the events you want in events, or omit it to receive all of them.
Example response:
Store the publicKey. It is the Ed25519 key you use to verify every delivery from this endpoint, and it is returned only in the endpoint’s create and list responses.

3. Events to subscribe to

EventFires when
transfer.createdA transfer is created.
transfer.status_changedA transfer moves through awaiting_funds, funds_received, approved, payment_submitted, payment_processed (and failure or refund states).
virtual_account.createdA virtual account is created.
virtual_account.updatedA virtual account changes state, including when it activates.
bp.kyc.status_changedThe customer’s KYC status changes.
transfers.kyc.submission.status_changedA KYC submission changes state (provider-specific sumsub and bridge variants also exist).
bp.tos_acceptedThe customer accepts a terms of service document.
transfer.status_changed tracks the same statuses shown in the payins and payouts guides, and virtual_account.updated tells you when a virtual account becomes active.

4. Receive and verify deliveries

Due sends a POST to your URL for each event, with the signature hex-encoded in the X-Webhook-Signature header. Verify it against the raw request body using the endpoint’s Ed25519 publicKey before trusting the payload.
Verify the signature over the raw, unparsed body. Reframing the JSON changes the bytes and breaks verification. Reject any delivery that fails verification.
Acknowledge deliveries quickly with a 2XX, then process events asynchronously so a slow handler does not cause Due to retry.

5. Manage endpoints

  • GET /webhooks lists your registered endpoints.
  • POST /webhooks/{webhookId} updates one; send any of url, description, events, or enabled (set enabled: false to pause deliveries without deleting).
  • DELETE /webhooks/{webhookId} removes one.

6. Inspect and retry deliveries

GET /webhooks/{webhookId}/events returns the delivery history for an endpoint, including attempts, responseStatusCode, and lastError. Retry a specific event with POST /webhooks/{webhookId}/events/{eventId}/retry.
The response is paginated: when more events exist, data.next holds the cursor for the next page. Portal forwards your query parameters to Due, so pass that value back as Due’s pagination cursor on the following request to page through the history.
In the event history, eventData is the event payload as a byte array. Decode it to JSON before reading, for example JSON.parse(Buffer.from(eventData).toString('utf8')).

Next steps