---
title: "Validate the envelope's append-only audit hash chain"
method: GET
path: "/api/envelopes/{envelope_id}/audit"
---

# Validate the envelope's append-only audit hash chain

`GET /api/envelopes/{envelope_id}/audit`

## Request

- Base URL: `https://free-sign.com`
- URL: `https://free-sign.com/api/envelopes/{envelope_id}/audit`
- Auth: none declared

Returns the envelope's audit events (the append-only, per-envelope hash chain) together with a server-computed integrity verdict. Every `event_hash` is recomputed from its canonical material, and the `prev_event_hash` linkage plus `seq` contiguity are checked. No authentication — the 32-hex envelope id is the bearer capability, exactly like /api/receipts. The `events` array is returned verbatim (including each row's full `event_data_json`, which carries the plaintext `request_fingerprint`) so a client can independently re-derive the verdict by recomputing the hashes itself; the in-browser /verify page does exactly this and does not trust `chain.valid`. The audit chain lives only in FreeSign's database — unlike the CMS / RFC 3161 / OpenTimestamps evidence inside the PDF, validating it requires the FreeSign service to be online.

## Path parameters

- `envelope_id` string, required

## Response `200`

Audit chain and integrity verdict.

- object
  - `envelope_id` string, required
  - `attested_audit_chain_head_hash` string, nullable, required: The audit-chain head the signer froze in the v2 final payload at finalize time (security audit G-01), derived from the signed final_payload_json — not the denormalised audit_chain_head_hash column. NULL until the envelope is finalized. It is fed into the verdict's head cross-check ONLY when attested_head_signature_verified is true; an unverified head is reported here but not cross-checked.
  - `attested_head_signature_verified` boolean, required: True when the final-payload signature carrying the attested head was re-verified against the signer's on-file public key. False when the envelope is not finalized or that signature did not verify — in the latter case the attested head's provenance is unconfirmed, the head is NOT cross-checked (head_checked is false), and the audit trail should be treated as unverified.
  - `chain` object, required: Server-computed integrity verdict. Re-derivable from `events`.
    - `valid` boolean, required
    - `event_count` integer, required
    - `broken_at` integer, nullable, required: seq of the first broken event, or null when the chain is intact.
    - `reason` 'hash_mismatch' | 'broken_link' | 'seq_bad_start' | 'seq_gap' | 'seq_duplicate' | 'head_mismatch' | 'null', nullable, required: Bounded reason enum for the first break, or null. head_mismatch means the recomputed chain head does not match the head frozen in the signer-attested final payload — a re-forged chain (G-01).
    - `head_checked` boolean, required: True when a signature-verified attested head was supplied and cross-checked against the recomputed chain. False when the envelope is not finalized OR the attested head's final-payload signature did not verify (see attested_head_signature_verified).
    - `head_match` boolean, nullable, required: Result of the head cross-check, or null when no signature-verified attested head was available.
    - `events` object[], required: Per-event check flags, parallel to the raw `events` array.
      - `seq` integer, nullable
      - `id` string, nullable
      - `event_type` string, nullable
      - `created_at` string, date-time, nullable
      - `hash_ok` boolean
      - `link_ok` boolean
      - `seq_ok` boolean
  - `events` object[], required: Raw audit_events rows ordered by seq ASC — every field that goes into the event_hash, so the verdict is independently recomputable.
    - `id` string
    - `envelope_id` string
    - `signer_id` string, nullable
    - `event_type` string
    - `event_data_json` string
    - `prev_event_hash` string, nullable
    - `event_hash` string
    - `seq` integer
    - `ip_hash` string, nullable
    - `user_agent_hash` string, nullable
    - `cf_country` string, nullable
    - `created_at` string, date-time

## Other responses

- `400`: Malformed envelope_id.
- `404`: envelope_not_found.

---

[API](https://skmtc.dev/free-sign/apis/freesign-free-e-signature-api.md) · [All operations](https://skmtc.dev/free-sign/apis/freesign-free-e-signature-api/llms.txt) · [OpenAPI document](https://skmtc.dev/free-sign/apis/freesign-free-e-signature-api/revisions/5d8e9854ab85?raw)
