Using Webhooks
Webhooks in Paradym provide a powerful way to listen to events that occur within Paradym. Webhooks can be used with different events.
Setting up Webhooks
To start receiving webhooks, some configuration is needed in the dashboard.
Go to Webhooks
To configure a webhook listener, go to the Webhooks tab (opens in a new tab) in the dashboard.
Create webhook endpoint
Enter the URL on which you want to receive the webhook events, and give it a unique name.
You can use a site such as Webhook.site (opens in a new tab) or Request Baskets (opens in a new tab) to get a temporary endpoint to receive events and play around with.
Note that webhook events contain sensitive information, and these services do not verify the HMAC of the events. You should not use these services for production webhooks.
Save webhook secret
Make sure to copy and save the webhook secret as it won't be displayed again. See Security for more information on how to secure your webhook endpoint.
From now on, all events are sent to the created webhook endpoint. You can create multiple webhook endpoints, but be aware that all events are sent to all configured webhook endpoints.
When creating a webhook using the Webhook API (opens in a new tab) you can configure specific event types for the webhook. When configured, only events matching one of the eventTypes
configured on the webhook will be sent to the webhook endpoint. This allows you to have different handlers for different event types, or filter out webhook events you're not interested in.
Webhook Events
For events emitted related to the workflow builder see the Workflow Builder Webhook Events.
The events emitted by Paradym are divided into categories:
OpenID4VC
The following OpenID4VC webhook events are currently emitted:
openid4vc.issuance.offered
openid4vc.issuance.partiallyIssued
openid4vc.issuance.completed
openid4vc.issuance.failed
openid4vc.verification.requested
openid4vc.verification.verified
openid4vc.verification.failed
All openid4vc.issuance
events contain an openId4VcIssuanceId
in the payload that can be used to retrieve an OpenID4VC issuance session (opens in a new tab) using the API. Similarly, All openid4vc.verification
events contain an openId4VcVerificationId
in the payload that can be used to retrieve an OpenID4VC verification session (opens in a new tab) using the API.
openid4vc.issuance.offered
Event dispatched when a OpenID4VC issuance offer is created.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.issuance.offered",
"payload": {
"openId4VcIssuanceId": "<openid4vc-issuance-id>"
}
}
openid4vc.issuance.partiallyIssued
Event dispatched when a credential has been issued in the OpenID4VC issuance session.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.issuance.partiallyIssued",
"payload": {
"openId4VcIssuanceId": "<openid4vc-issuance-id>"
}
}
openid4vc.issuance.completed
Event dispatched when all credentials have been issued in the OpenID4VC issuance session.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.issuance.completed",
"payload": {
"openId4VcIssuanceId": "<openid4vc-issuance-id>"
}
}
openid4vc.issuance.failed
Event dispatched when an OpenID4VC issuance failed.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.issuance.failed",
"payload": {
"openId4VcIssuanceId": "<openid4vc-issuance-id>",
"error": {
"message": "error-message",
"code": "error-code",
"details": "error-details"
}
}
}
openid4vc.verification.requested
Event dispatched when a OpenID4VC verification request is created.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.verification.requested",
"payload": {
"openId4VcVerificationId": "<openid4vc-verification-id>"
}
}
openid4vc.verification.verified
Event dispatched when the presentation in an OpenID4VC verification session has been verified.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.verification.verified",
"payload": {
"openId4VcVerificationId": "<openid4vc-verification-id>"
}
}
openid4vc.verification.failed
Event dispatched when an OpenID4VC verification failed.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "openid4vc.verification.failed",
"payload": {
"openId4VcVerificationId": "<openid4vc-verification-id>",
"error": {
"message": "error-message",
"code": "error-code",
"details": "error-details"
}
}
}
DIDComm
The following DIDComm webhook events are currently emitted:
didcomm.connection.created
didcomm.connection.reused
didcomm.messaging.basic.received
didcomm.messaging.custom.received
didcomm.issuance.offered
didcomm.issuance.completed
didcomm.issuance.failed
didcomm.verification.requested
didcomm.verification.verified
didcomm.verification.failed
All didcomm.issuance
events contain an didcommIssuanceId
in the payload that can be used to retrieve a DIDComm issuance session (opens in a new tab) using the API. Similarly, All didcomm.verification
events contain an didcommVerificationId
in the payload that can be used to retrieve a DIDComm verification session (opens in a new tab) using the API.
didcomm.connection.created
Event dispatched when a DIDComm connection is created based on a created invitation. This event is not emitted for connections created based on received invitations (for this you get back the connection directly when receiving the invitation).
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.connection.created",
"payload": {
"didcommInvitationId": "<didcomm-invitation-id>",
"didcommConnectionId": "<didcomm-connection-id>"
}
}
didcomm.connection.reused
Event dispatched when a DIDComm connection is reused based on a created invitation. This event is not emitted for connections reused based on received invitations (for this you get back the connection directly when receiving the invitation).
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.connection.reused",
"payload": {
"didcommInvitationId": "<didcomm-invitation-id>",
"didcommConnectionId": "<didcomm-connection-id>"
}
}
didcomm.messaging.basic.received
Event dispatched when a basic message is received.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.messaging.basic.received",
"payload": {
"didcommConnectionId": "<existing-connection-id>",
"message": "<message-content>",
"messageId": "<received-message-id>",
"sentTime": "<sent-time>"
}
}
didcomm.messaging.custom.received
Event dispatched when a custom message is received.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.messaging.custom.received",
"payload": {
"didcommConnectionId": "<existing-connection-id>",
"message": {
"@id": "<message-id>",
"@type": "<message-type>",
"<custom-message-field>": "<custom-message-value>"
}
}
}
didcomm.issuance.offered
Event dispatched when a DIDComm issuance offer is created.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.issuance.offered",
"payload": {
"openId4VcIssuanceId": "<didcomm-issuance-id>"
}
}
didcomm.issuance.completed
Event dispatched when the credential has been issued in the DIDComm issuance session.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.issuance.completed",
"payload": {
"openId4VcIssuanceId": "<didcomm-issuance-id>"
}
}
didcomm.issuance.failed
Event dispatched when a DIDComm issuance failed.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.issuance.failed",
"payload": {
"openId4VcIssuanceId": "<didcomm-issuance-id>",
"error": {
"message": "error-message",
"code": "error-code",
"details": "error-details"
}
}
}
didcomm.verification.requested
Event dispatched when a DIDComm verification request is created.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.verification.requested",
"payload": {
"didcommVerificationId": "<didcomm-verification-id>"
}
}
didcomm.verification.verified
Event dispatched when the presentation in a DIDComm verification session has been verified.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.verification.verified",
"payload": {
"didcommVerificationId": "<didcomm-verification-id>"
}
}
didcomm.verification.failed
Event dispatched when a DIDcomm verification failed.
Example:
{
"webhookId": "<webhook-id>",
"webhookPublishedAt": "<time-of-publication>",
"projectId": "<project-id>",
"eventType": "didcomm.verification.failed",
"payload": {
"didcommVerificationId": "<didcomm-verification-id>",
"error": {
"message": "error-message",
"code": "error-code",
"details": "error-details"
}
}
}
Timeouts and retries
Webhooks are subject to a 5 second timeout. If your server does not respond with a 200 OK
HTTP status code within 5 seconds, the webhook will be considered failed and will not be retried.
Security
If you choose not to use the secret, your webhook becomes vulnerable to unauthorized events. Anybody who knows the webhook URL would be able to send events to it.
To prevent events not sent by Paradym from being sent to your webhook endpoint, Paradym employs a security measure using SHA256 HMAC. The X-Paradym-HMAC-SHA-256
header is included in each webhook HTTP request.
Here's a basic example of how to verify the request using Node.js and the crypto
standard library:
const express = require('express')
const crypto = require('crypto')
const bodyParser = require('body-parser')
const PORT = 3000
const SECRET = 'your-webhook-secret'
const app = express()
// middleware to get the raw request body
app.use(
bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString()
}
})
)
app.post('/webhook', (req, res) => {
const hmac = req.get('X-Paradym-HMAC-SHA-256')
const computedHmac = crypto.createHmac('sha256', SECRET).update(req.rawBody, 'utf8').digest('hex')
if (computedHmac !== hmac) {
console.log('HMAC is invalid!')
res.sendStatus(401)
return
}
console.log('HMAC is valid!')
// process the webhook event
console.log(req.body)
res.sendStatus(200)
})
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`)
})
In this example, the code computes the HMAC digest of the incoming request payload with your secret and compares it to the request's X-Paradym-HMAC-SHA-256
. This allows you to confirm that the webhook was sent by Paradym, preventing any spoofing attempts. The secret should be securely stored on your server and is not included in the webhook requests.