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/v1POST /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:
ACCEPTEDSUSPENDEDREVOKEDERROR
Proof request status changes:
ACCEPTEDREJECTEDERROR
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.