### To subscribe to webhook notifications:

1.  **Sign in**: Navigate to [https://dashboard.truevault.com.au/](https://dashboard.truevault.com.au/) and sign in with your credentials. (Use [https://dashboard.sandbox.truevault.com.au/](https://dashboard.sandbox.truevault.com.au/) for sandbox access)

2.  **User Settings**: Once logged in, click on `Account` in the upper right corner.

3.  **Webhooks Tab**: Within the user settings, find the "Webhooks" tab. Click on it to access settings related to webhook subscriptions.

4.  **Add a new Webhook subscription**: In the Webhooks Tokens tab, you should find your existing webhooks keys listed. Click on `Add Webhook` if a you are not yet subscribed to API notifications.

### Configuring a new Webhook

1.  Enter a **name**, e.g. Core API Notifications

2.  Add your receiving **URL** - the location in your app we should send responses to. E.g. `https://your-app.com/truevault/webhooks/receive`

3.  Add a **secret\_key**. You must verify that all incoming requests conthain this key in a JWT inside the header x-webhook-secret. See the pseudo-code example below for an example workflow to validate the secret\_key header. A suitable Linux command for a secure 32-byte (256-bit) token is `openssl rand -hex 32` or `cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`

4.  Expand the **Events** options, and check all available boxes.

#### Pseudo-code example for verifying the webhook secret header

```plainText
function verifySecretHeader(secret_key, validate = true):
    headers = getRequestHeaders()

    // 1. Check header exists
    if "x-webhook-secret" not in headers:
        log("Webhook secret header missing")
        return 404

    // 2. Decode and validate JWT payload (expiry, timestamps, etc.)
    jws = JWT.deserialize(headers["x-webhook-secret"])
    payload = JWT.getPayload(jws)

    try:
        JWT.validatePayload(payload, require_expiry = true)
    catch InvalidPayload:
        log("Invalid webhook JWT payload")
        return 404

    // 3. Verify HMAC-SHA256 signature against shared secret
    valid = JWT.verifySignature(jws, secret_key, algorithm = HS256)

    if not valid and validate:
        log("Webhook signature verification failed")
        return 404 
```

## Webhook request headers

TrueVault sends these headers with every callback. Verify `X-Webhook-Signature` before trusting the payload.

| Field | Type | Required | Description |
|---|---|---|---|
| `X-Webhook-Event` | string | yes | Event: identityRequestCompleted |
| `X-Webhook-Signature` | string | no | HMAC signature for webhook verification |
| `X-Webhook-ID` | string | no | Unique identifier for this webhook delivery |
| `X-Callback-URL` | string | yes | The callback URL expression that receives this request |
| `Authorization` | string | no |  |
| `X-Tenant-Id` | string | no |  |
| `X-Request-Timestamp` | string | no |  |

## Webhook request body

| Field | Type | Required | Description |
|---|---|---|---|
| `title` | string | no | The title of the webhook response. Currently unused. |
| `description` | string | no | The description of the webhook response. Currently unused. |
| `eventKey` | string | no | Type of event that triggered the webhook |
| `timestamp` | string | no |  |
| `data` | object | no | This will only be present for identity.api.complete events. |
