API and Dashboard
Using Webhooks

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.

Get API Key

Creation of a webhook endpoint in Paradym.

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:

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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
    "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:

JSON
{
    "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "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:

JavaScript
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.