Skip to main content

Webhooks

Overview

Set up the Core to send notifications of important issuance and verification events to a URL or MQTT topic of your choosing.

Setting up webhooks

1. Configure the webhook task provider

Add a WEBHOOK_NOTIFY task to your configuration. The following example includes URL validation and configures the system to send one notification per qualified event:

task:
WEBHOOK1: # Name the instance
type: "WEBHOOK_NOTIFY" # Required
display: "task.webhookNotify"
order: 5
params:
public:
allowedHosts: # Optional — restricts which URL and MQTT hosts the system will send notifications to
- foo.com
- *.bar.ch
- 111.222.33.44
allowInsecureHttpTransport: true # Optional — also allows insecure mqtt (vs mqtts)
private:
requestTimeout: 30 # Seconds the system waits for a response before marking as error

allowedHosts supports exact domains, wildcard subdomains, and IP addresses. If omitted, all hosts are permitted. For MQTT, the broker's host must also be in this list.

allowInsecureHttpTransport governs both transports: set it to true to allow plain http or mqtt; https and mqtts are always allowed.

requestTimeout applies the same way to both transports. For MQTT, it's the TCP connection timeout.

2. Add webhooks to an exchange protocol

Add the webhookTask parameter to any OpenID4VC issuance or verification protocol, specifying the task instance by name:

OPENID4VCI_FINAL1:
display: exchange.openid4vciFinal1
order: 3
type: "OPENID4VCI_FINAL1"
params:
public:
webhookTask: "WEBHOOK1" # Optional — references the task instance name defined above

Any time you issue or verify with the protocol you will be able to specify a webhook URL or MQTT topic for notifications.

Receiving notifications

Pass the webhook URL or MQTT topic

When creating a credential or proof request, include your webhook destination in the request body using the webhookDestinationUrl parameter:

  • POST /api/credential/v1
  • POST /api/proof-request/v1

For MQTT, use the structure mqtt(s)://host[:port]/topic.

Notification events

The system sends an HTTP POST request to your webhook URL, or publishes a message to your MQTT topic, when a credential or proof request reaches one of the following statuses.

Credential status changes:

  • ACCEPTED
  • SUSPENDED
  • REVOKED
  • ERROR

Proof request status changes:

  • ACCEPTED
  • REJECTED
  • ERROR

The request body has the following shape:

{
"credentialId": "UUID", // Present for credential notifications
"proofId": "UUID", // Present for proof request notifications
"status": "string", // New status (always present)
"eventTimestamp": "string" // Current time in RFC 3339 format (always present)
}

Response handling

The system records delivery results in notification history (entityType: NOTIFICATION). If you are implementing the receiving endpoint, respond accordingly so history events are recorded as expected.

HTTP:

  • 2xx — delivery recorded as successful in history
  • 3xx / 4xx — warning printed to logs; error recorded in history
  • No response — system waits for the duration defined in requestTimeout; if still no response, marked as error (unless retries are configured, see below)
  • 404 / 5xx — if retries are configured (see below), the system will attempt redelivery

MQTT:

  • PUBACK received — delivery recorded as successful in history
  • No PUBACK — system waits for the duration defined in requestTimeout; if retries are configured (see below), the system will attempt redelivery; once retries are exhausted (or if none are configured), marked as error

Advanced configuration

Retries

You can configure the system to retry failed notification attempts. Add retries to your task provider:

params:
private:
retries: # Optional
interval: 1 # Minimum seconds between attempts
maxAttempts: 5 # Total attempts before marking as permanently failed
exponentialFactor: 2.5 # Multiplies the interval after each retry

Retries require that you call the task endpoint on a schedule (for example, a cron job). Because retries are triggered by this call rather than on a timer, attempts will occur no sooner than interval seconds after the previous failure, but the exact timing depends on how frequently you run the task.

To trigger the task manually or via a job:

POST /api/task/v1/run
{
"name": "WEBHOOK1" // Reference the instance name
}

Once maxAttempts is exhausted, the system prints a warning to logs and records the final failure in history.