Integrations Overview
Integrations let the Business Wallet push domain events to your own systems as soon as they happen — for example, when a wallet is created or a new identifier (DID, X509, JWK) is added. You no longer have to poll the REST API to find out what changed.
Every event is delivered as a CloudEvents 1.0 message in binary HTTP mode (for webhooks) or structured mode (for Kafka and JMS), so any CloudEvents-compatible receiver can parse it without custom code.
How a webhook integration looks
At a glance, an event flows from the Business Wallet to your own backend like this:
When a domain event happens, the wallet signs the payload with HMAC SHA-256 and POSTs a CloudEvents message to your endpoint. Your backend verifies the signature, dedupes on the CloudEvents id, and replies 2xx. Anything else triggers a retry with exponential back-off — see delivery semantics below.
What you can do
- Configure one or more integration channels (webhook, Kafka, JMS, or a custom adapter) per wallet.
- Subscribe each channel to one or more event types from the event catalog.
- Inspect every outbound message in the Deliveries view, with the full request, response, and timing.
- Replay failed deliveries after fixing the receiver, or dismiss them once they are no longer relevant.
Webhooks vs on-premise channels
Most customers integrate over webhooks because they work everywhere — SaaS or on-premise — and need no extra infrastructure. Kafka and JMS are reserved for on-premise deployments where the messaging middleware already exists in your network. Custom adapters are for on-premise customers who embed the wallet as a library and want to bridge to systems we do not ship out of the box (SNS, Pub/Sub, an internal bus, …).
| Channel | Available in | When to use | Notes |
|---|---|---|---|
| Webhook | SaaS + on-premise | The default. You expose an HTTPS endpoint; we POST CloudEvents to it. | Always available. HMAC SHA-256 signature is always on; API-key and OAuth2 client-credentials auth are optional. See webhook authentication. |
| Kafka | On-premise only | You already run a Kafka cluster and prefer log-based fan-out. | Requires the optional Kafka Maven dependency to be on the classpath. Structured-mode CloudEvents on the topic. |
| JMS | On-premise only | You run an enterprise message broker (ActiveMQ, IBM MQ, …) and want exactly-once-style delivery to a queue. | Requires the optional JMS Maven dependency. Structured-mode CloudEvents in the message body. |
| Custom adapter | On-premise (embedded library) only | You want to bridge wallet events to a system we do not ship — SNS, Pub/Sub, an internal pub/sub, etc. | Implement the channel SPI; see on-premise integration. |
Permissions
Four authorities control who can configure integrations and inspect their deliveries.
| Authority | Grants |
|---|---|
WALLET_INTEGRATION_CHANNEL_READ | View configured channels and their settings (secrets are never returned). |
WALLET_INTEGRATION_CHANNEL_CRUD | Create, edit, rotate secrets, and delete channels. Implies READ. |
WALLET_INTEGRATION_DELIVERY_READ | View the deliveries log for any channel in the wallet. |
WALLET_INTEGRATION_DELIVERY_CRUD | Replay or dismiss FAILED deliveries. Implies READ. |
Super-admins with GLOBAL_WALLET_CRUD can perform any of the above on any wallet.
Delivery semantics
Integrations are designed for reliability over speed.
- At-least-once delivery. Each delivery is recorded atomically with the event that produced it, so events are never lost — even if the wallet crashes immediately afterwards.
- Retries with exponential back-off. Failed deliveries are retried automatically with increasing delays. Non-retryable HTTP responses (e.g.
400,401,403,404) move the delivery toFAILEDimmediately so they can be triaged. - Receivers must be idempotent. Because of the at-least-once contract, the same event may be delivered more than once (for example, after a network blip or a wallet restart). Use the
idfield in the CloudEvents envelope as your dedupe key — it is stable across retries. - Ordering is best-effort, not guaranteed. Two events from the same wallet may arrive at your receiver out of order; rely on
timeand your own state, not on receipt order.
Lifecycle of a delivery
Every outbound integration delivery moves through the following state machine:
State reference
| State | Meaning |
|---|---|
PENDING | The delivery is queued and waiting to be sent. Also the state used between automatic retries while attempts remain. |
DELIVERING | The wallet is currently sending the delivery to the configured channel. |
DELIVERED | The receiver acknowledged the delivery (HTTP 2xx for webhooks, broker ack for Kafka / JMS). Terminal. |
FAILED | All retry attempts exhausted, or a non-retryable error occurred (e.g. 4xx other than 408 / 429). The delivery is preserved with the last response code, body excerpt, and error message for diagnosis. |
DISMISSED | An operator deliberately marked a FAILED delivery as no-longer-relevant. Terminal — these deliveries are excluded from cleanup and from the failed-deliveries metric. |
Manual transitions (FAILED →)
- Replay moves the delivery back to
PENDINGand resets the attempt count. It will be re-sent shortly afterwards. - Dismiss moves the delivery to
DISMISSED. The original payload and error are kept for audit but the delivery is no longer considered actionable.
Both transitions require the WALLET_INTEGRATION_DELIVERY_CRUD authority and are recorded in the audit log as INTEGRATION history events.
Where to next
- Webhook authentication — HMAC, API-key, and OAuth2 details, with code samples.
- Event catalog — the v1 events emitted today.
- CloudEvents envelope — the wire format for every integration.
- On-premise integration — Kafka, JMS, and custom-adapter configuration for self-hosted deployments.