> ## Documentation Index
> Fetch the complete documentation index at: https://docs.auditrails.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify Audit Hash Chain — AuditRails API Reference

> Cryptographically verify the tamper-evident SHA-256 hash chain across a range of audit log events to detect unauthorized modifications.

The Verify Hash Chain endpoint gives you a way to independently confirm that your audit log has not been tampered with. For every event in the requested sequence range, AuditRails recomputes the expected SHA-256 hash from the canonical payload and checks that each event's `prev_hash` matches the hash of the event immediately before it. If every event in the range passes both checks, the response reports `valid: true`. If any event fails, the response pinpoints the first broken link in the chain.

## Endpoint

```
GET https://api.auditrails.io/v1/events/verify
```

## How Verification Works

For each event in the requested range, AuditRails performs two checks:

1. **Hash recomputation** — Recomputes `SHA-256(prev_hash + canonical_payload + timestamp)` and compares the result to the stored `hash`. A mismatch means the event's content has been altered after it was written.
2. **Chain continuity** — Confirms that the event's `prev_hash` matches the `hash` of the preceding event. A mismatch means an event was deleted, inserted, or reordered.

The **canonical payload** used for recomputation includes: `log_id`, `tenant_id`, `action`, `actor_id`, `resource`, and `metadata`. The fields `country`, `city`, `ip_address`, and all chain fields (`chain_seq`, `prev_hash`, `hash`) are intentionally excluded from the canonical payload.

## Query Parameters

<ParamField query="from_seq" type="integer" default="1">
  The `chain_seq` of the first event to include in verification. Defaults to `1` (the very first event in the project).
</ParamField>

<ParamField query="to_seq" type="integer">
  The `chain_seq` of the last event to include. If omitted, defaults to `from_seq + 1000`. You cannot verify more than 1000 events in a single request — for larger ranges, page through in successive calls.
</ParamField>

## Response Fields

<ResponseField name="valid" type="boolean" required>
  `true` if every event in the range passed both the hash recomputation check and the chain continuity check. `false` if any event failed.
</ResponseField>

<ResponseField name="checked" type="integer" required>
  Total number of events verified in this response. When `valid` is `false`, this reflects the count of events examined up to and including the first broken event.
</ResponseField>

<ResponseField name="first_seq" type="integer" required>
  The `chain_seq` of the first event that was verified, echoing your `from_seq` input.
</ResponseField>

<ResponseField name="last_seq" type="integer" required>
  The `chain_seq` of the last event that was verified. When `valid` is `true` this equals your effective `to_seq`. When `valid` is `false` this equals `broken_at`.
</ResponseField>

<ResponseField name="broken_at" type="integer">
  The `chain_seq` of the first event that failed verification. Only present when `valid` is `false`.
</ResponseField>

<ResponseField name="broken_hash" type="string">
  The stored `hash` value of the event at `broken_at`. Only present when `valid` is `false`. Compare this against a trusted copy of the event to determine whether the hash or the payload was modified.
</ResponseField>

<Warning>
  **A broken chain is a critical security finding.** If `valid` is `false`, take these steps immediately:

  1. **Export and preserve** the full verification response, including `broken_at` and `broken_hash`.
  2. **Do not modify or delete** any events in your project until the investigation is complete.
  3. **Fetch the affected event** using [Get Single Event](/api-reference/get-event) and compare its fields to your own application's records or backups.
  4. **Investigate upstream** whether the tampering occurred in your ingestion pipeline, a third-party integration, or at the storage layer.
  5. **Contact AuditRails support** with the `X-Request-Id` header value from the verify response for platform-level assistance.
</Warning>

<Note>
  A single verify request covers at most 1000 events. To verify a larger chain, issue successive requests by advancing `from_seq` and `to_seq` in 1000-event increments. If you find a broken chain in a range, you can narrow the exact failure point by bisecting with smaller sub-ranges.
</Note>

<Note>
  The response body does not include a `request_id` field. Use the `X-Request-Id` response header to correlate this verification run with your internal audit records or a support case.
</Note>

## Example Request

```bash theme={null}
curl -G https://api.auditrails.io/v1/events/verify \
  -H "Authorization: Bearer at_live_xxx" \
  -d "from_seq=1" \
  -d "to_seq=1000"
```

## Example Response — Chain Intact

```json theme={null}
{
  "valid": true,
  "checked": 500,
  "first_seq": 1,
  "last_seq": 500
}
```

## Example Response — Tampering Detected

```json theme={null}
{
  "valid": false,
  "checked": 42,
  "first_seq": 1,
  "last_seq": 42,
  "broken_at": 42,
  "broken_hash": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}
```

## Verifying Large Chains

For projects with more than 1000 events, page through the chain in successive 1000-event windows:

```bash theme={null}
# Window 1: events 1–1000
curl -G https://api.auditrails.io/v1/events/verify \
  -H "Authorization: Bearer at_live_xxx" \
  -d "from_seq=1" \
  -d "to_seq=1000"

# Window 2: events 1001–2000
curl -G https://api.auditrails.io/v1/events/verify \
  -H "Authorization: Bearer at_live_xxx" \
  -d "from_seq=1001" \
  -d "to_seq=2000"

# Window 3: events 2001–3000
curl -G https://api.auditrails.io/v1/events/verify \
  -H "Authorization: Bearer at_live_xxx" \
  -d "from_seq=2001" \
  -d "to_seq=3000"
```

Continue advancing the window until you have covered all chain sequence numbers in your project, or until a `valid: false` response signals a break in the chain. You can determine the highest `chain_seq` in your project by inspecting recent events from the [List Events](/api-reference/get-events) endpoint.

## Error Responses

| Status | Code                 | Description                                                               |
| ------ | -------------------- | ------------------------------------------------------------------------- |
| `401`  | `auth/key_not_found` | The API key provided in the `Authorization` header is missing or invalid. |
