---
id: openid4vc-webhooks
hide_title: true
title: Set up webhooks for OpenID4VC integrations
description: Understand how to configure webhooks in OpenID4VC workflows to manage real‑time events like credential issuance, updates, and verification responses.
keywords: [webhooks, OpenID4VC, event notifications, credential issuance events, verification events, Organisation Wallet, European Business Wallet, API integration]
sidebar_label: Webhook Events
slug: /openid4vc-webhooks/
---

> **Build this with an AI coding agent.** Install the iGrant.io Agent Skills, then ask your agent to build the integration:
>
> ```bash
> npx skills add L3-iGrant/skills
> ```


# Webhook Events

Organisation Wallet Suite by iGrant.io provides webhooks to notify your application about important events in the OpenID4VC-based credential issuance and verification process. This document lists all available webhook events and their descriptions for the OpenID4VC implementation.

## Webhook Management

Before receiving webhook events, you need to configure your webhook endpoints. The following APIs are available for managing webhooks:

| API | Description | Documentation |
|-----|-------------|---------------|
| Create Webhook | Create a new webhook endpoint | [Create Webhook](/docs/openid4vc-api/config-create-webhook) |
| Read Webhook | Get details of a specific webhook | [Read Webhook](/docs/openid4vc-api/config-read-webhook) |
| Update Webhook | Modify an existing webhook configuration | [Update Webhook](/docs/openid4vc-api/config-update-webhook) |
| Delete Webhook | Remove a webhook endpoint | [Delete Webhook](/docs/openid4vc-api/config-delete-webhook) |
| List Webhooks | Get all configured webhooks | [List Webhooks](/docs/openid4vc-api/config-list-webhooks) |

## Issuer Webhooks

Issuer webhooks notify you about events related to credential issuance and management.

| Event Name | Description |
|------------|-------------|
| `openid.credential.offer_sent` | Triggered when a credential offer is created and delivered using QR code or credential offer endpoint |
| `openid.credential.offer_received` | Triggered when a credential offer is accessed by the wallet unit (or holder) |
| `openid.credential.token_issued` | Triggered when a token is issued during the credential issuance process |
| `openid.credential.credential_issued` | Triggered when a credential is issued to the wallet unit (or holder) by the issuer |
| `openid.credential.credential_acked` | Triggered when a credential is received and acknowledged in the wallet unit (or holder) |
| `openid.credential.credential_accepted` | Triggered when the credential is accepted by the wallet unit (or holder) to store |
| `openid.credential.credential_deleted` | Triggered when the credential is deleted by the wallet unit (or holder) |
| `openid.credential.issuance_denied` | Triggered when credential issuance is denied for various reasons such as: wallet unit attestation invalid or missing, proof of possession invalid, valid credential already exists (if credential uniqueness is enforced), or authorisation failed |

## Verifier Webhooks

Verifier webhooks notify you about events related to presentation requests and verifications.

| Event Name | Description |
|------------|-------------|
| `openid.presentation.request_sent.v3` | Triggered when a presentation request is created and delivered using QR code |
| `openid.presentation.request_received.v3` | Triggered when a presentation request is accessed by the wallet unit (or holder) |
| `openid.presentation.presentation_acked.v3` | Triggered when a presentation request is received, acknowledged, and verification is performed by the verifier |

## Webhook Payload

Each webhook event includes a JSON payload containing relevant information about the event. The payload structure follows a consistent format with common fields and event-specific data.

### Common Payload Fields

| Field | Type | Description |
|-------|------|-------------|
| `deliveryID` | string | Unique identifier for this webhook delivery |
| `webhookID` | string | Identifier of the webhook configuration |
| `timestamp` | string | ISO 8601 timestamp of when the event occurred |
| `type` | string | The type of event (e.g. "openid.credential.offer_sent") |
| `data` | object | Event-specific payload data that varies by event type |

### Payload Structure

All webhook events follow this consistent structure:

#### Issuance Webhook Example
```json
{
  "deliveryID": "67f770eec8426b0b55e30c2e",
  "webhookID": "67f770936e45cf84e6880d25",
  "timestamp": "2025-04-10T07:19:10Z",
  "data": {
    "credential": {
      "CredentialExchangeId": "3e154218-88d5-4529-8143-bf1ccf0e08c0",
      "credentialDefinitionId": "a79fb535-5e17-4571-928a-7b30011e4fa8",
      "walletUnitAttestationVerified": false
      // Additional credential history fields
    },
    "organisationId": "64ec561de2f6a8000142c671"
  },
  "type": "openid.credential.offer_sent"
}
```

#### Verification Webhook Example

```json
{
  "deliveryID": "67f77188c8426b0b55e30d08",
  "webhookID": "67f770936e45cf84e6880d25",
  "timestamp": "2025-04-10T07:21:44Z",
  "data": {
    "organisationId": "64ec561de2f6a8000142c671",
    "presentation": {
      "presentationExchangeId": "73315f05-089f-4548-b7ba-052ce828c7d7",
      "presentationDefinitionId": "bd28cfc2-4938-4f47-b91a-77412676d107",
      "walletUnitAttestationVerified": false
      // Additional verification history fields
    }
  },
  "type": "openid.presentation.request_received.v3"
}
```

For detailed field definitions, please refer to:
- [Issue credential](/docs/openid4vc-api/config-digital-wallet-open-id-issue-credential) response section for issuance webhooks
- [Send verification request (v3)](/docs/openid4vc-api/config-create-digital-wallet-open-id-verification-request-v-3) response section for current version verification webhooks

## Delivery Guarantees

Webhook delivery follows an at-most-once guarantee. This means:
- Delivery is attempted once
- There is no built-in retry mechanism if the target endpoint is unreachable or errors out
- It is recommended to implement appropriate error handling and logging on your webhook endpoint

For detailed information about the payload structure for each event type, please refer to the specific event documentation.

## Webhook Security

Each webhook delivery includes an `X-iGrant-Signature` header that allows you to verify the authenticity of the webhook. The signature is generated using HMAC-SHA256 and includes a timestamp to prevent replay attacks.

### Signature Format

The `X-iGrant-Signature` header follows this format:
```
X-iGrant-Signature: t=<timestamp>,sig=<signature>
```

Where:
- `timestamp`: ISO 8601 timestamp in UTC (e.g., "2025-04-10T07:19:10Z")
- `signature`: HMAC-SHA256 signature of the payload

### Verifying the Signature

To verify a webhook signature:

1. Extract the timestamp and signature from the header
2. Get the raw request body
3. Concatenate the timestamp and request body with a period (`.`)
4. Compute HMAC-SHA256 using your webhook's secret key
5. Compare the computed signature with the received signature

Example verification code in Go:

```go
func verifyWebhookSignature(timestamp, signature, secretKey string, payload []byte) bool {
    // Construct the signed payload
    signedPayload := timestamp + "." + string(payload)
    
    // Create HMAC-SHA256 hash
    h := hmac.New(sha256.New, []byte(secretKey))
    h.Write([]byte(signedPayload))
    
    // Get the computed signature
    computedSig := hex.EncodeToString(h.Sum(nil))
    
    // Compare signatures
    return hmac.Equal([]byte(computedSig), []byte(signature))
}
```

### Security Best Practices

1. Always verify the webhook signature before processing the payload
2. Check that the timestamp is recent (e.g., within 5 minutes) to prevent replay attacks
3. Keep your webhook secret key secure and never share it
4. Use HTTPS endpoints for webhook delivery
5. Consider implementing rate limiting to prevent abuse
