---
title: "Verify eIDAS Audit Log Integrity"
description: "Verify that the organization eIDAS audit hash chain is intact in the walt.id Enterprise Stack."
stack: "Enterprise Stack (commercial) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/administration/events-and-metrics/eidas-audit-log/verify-integrity
generated: 2026-10-01
---
# Verify eIDAS Audit Log Integrity

This guide shows you how to check that the eIDAS audit log for your organization has not been tampered with. Run this periodically as part of compliance monitoring, or after an incident review.

## How Integrity Works

Every audit entry in an organization forms a single append-only chain:

1. Each entry receives a monotonic `sequenceNumber`.
2. Each entry stores `prevEntryHash` (the previous entry's `entryHash`, or `GENESIS` for the first entry).
3. Each entry stores its own `entryHash`, derived from the previous hash and the entry contents.

If an entry is modified, removed from the middle of the chain, or its sequence numbers are disrupted, verification fails and reports where the break starts.

**Error:**

Verifying the live database chain alone cannot prove that a complete trailing segment was never deleted. For production compliance programs, export signed checkpoints (sequence number + tip hash) to storage outside the Enterprise API database on a regular schedule.

## Prerequisites

Before you begin, ensure you have:

- **A Bearer token** with the `view-audit-log` permission at **organization scope**.
- **Access via the organization host**, e.g. `https://{orgID}.enterprise-sandbox.waltid.dev`.

**Note:**

Chain verification must be called at organization-root scope. The API rejects the request if the resolved route target is not the organization itself.

---

## Verify the Chain

Call `GET /v1/audit/verify-chain`. Optionally limit the check to a sequence range.

**Option: CURL**

**Endpoint:** `GET /v1/audit/verify-chain` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/eIDAS%20Audit%20Log/get_v1_audit_verify_chain)

##### Example Request

```bash
curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/audit/verify-chain?fromSequence=0&toSequence=1000' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}'
```

**Path Parameters**

- **orgID**: _String_ (required) - Your organization ID used as the host alias, e.g. `test.enterprise-sandbox.waltid.dev`.

**Query Parameters**

- **fromSequence**: _Number_ (optional) - Inclusive start of the sequence range. Defaults to `0`.
- **toSequence**: _Number_ (optional) - Inclusive end of the sequence range. Defaults to the end of the chain.

**Header Parameters**

- **Authorization**: _String_ (required) - Bearer token for Enterprise Stack authentication. Format: `Bearer {token}`.

---

##### Example Response (Intact)

```json
{
  "intact": true,
  "checkedEntries": 128,
  "firstBrokenAt": null,
  "message": "Chain intact: 128 entries verified (seq 0–127)"
}
```

##### Example Response (Broken)

```json
{
  "intact": false,
  "checkedEntries": 42,
  "firstBrokenAt": 42,
  "message": "Hash mismatch at seq=42: stored=9f86d081884c7d65… recomputed=2c26b46b68ffc68f…"
}
```

**Response Fields**

- **intact**: _Boolean_ - `true` if every checked entry recomputes correctly and sequence numbers are continuous.
- **checkedEntries**: _Number_ - How many entries were verified in this run.
- **firstBrokenAt**: _Number_ or `null` - Sequence number of the first failing entry, or `null` when intact.
- **message**: _String_ - Human-readable summary of the result.

**Response Codes**

- `200` — Verification completed (inspect `intact` for the outcome).
- `400` — Invalid sequence parameters.
- `401` — Invalid or missing authentication token.
- `403` — Missing `view-audit-log` permission, or call was not made at organization-root scope.

🎉 You've verified the integrity of the organization audit chain for the selected range.

---

## Interpreting Results

| Result | What to do |
|:-------|:-----------|
| `intact: true` | The checked range is consistent. Continue with your scheduled monitoring. |
| `intact: false` | Treat as a security / compliance incident. Note `firstBrokenAt` and `message`, freeze related exports, and investigate database access outside the Enterprise API. |
| `checkedEntries: 0` | No entries exist in the requested range — expected for a new organization or an empty sequence window. |

---

## Recommended Operating Practice

1. **Grant least privilege** — Give `view-audit-log` only to compliance and security roles.
2. **Query by session during investigations** — Start from a known `sessionId` or nonce, then expand the time window if needed.
3. **Verify on a schedule** — Run `/audit/verify-chain` regularly and alert on `intact: false`.
4. **Keep external checkpoints** — Periodically store the latest `sequenceNumber` and `entryHash` outside MongoDB so trailing deletions can be detected later.
5. **Separate concerns** — Use [Events & Metrics](https://docs.walt.id/enterprise-stack/administration/events-and-metrics/overview.md) for product analytics; use this audit log for compliance evidence.

---

## Next Steps

- **Review recorded evidence** — [Entry Types](https://docs.walt.id/enterprise-stack/administration/events-and-metrics/eidas-audit-log/entry-types.md).
- **Retrieve entries for an investigation** — [Query the Audit Log](https://docs.walt.id/enterprise-stack/administration/events-and-metrics/eidas-audit-log/query.md).
- **Manage auditor access** — [Permissions](https://docs.walt.id/enterprise-stack/administration/access-and-permissions/permissions/overview.md).
