Running Keel Verify
This walkthrough shows how a signed audit export is independently verifiable against exported signing material, without relying on a Keel dashboard, support response, or private Keel system.
Use a clean terminal on a machine where you can preserve the original downloaded files. Do not edit, reformat, decompress, or re-compress the export bundle before verification.
1. Install keel-verify
Install the verifier using the distribution path your Keel contact provides.
python -m pip install keel-verifierIf your review process requires source pinning, clone the published verifier repository and run the script from that checkout.
git clone https://github.com/keelapi/keel-verifier.git
cd keel-verifier
python -m pip install -r requirements.txtConfirm that the CLI is available.
keel-verify --help2. Request a signed export from your Keel admin
Ask your Keel admin to create an audit export with chain entries included.
POST /v1/compliance/exports?include_chain_entries=trueFor a scoped review, specify the relevant time window and an audit-grade export type such as full_audit, hipaa_audit, soc2_evidence, or incident_evidence.
curl -sS -X POST "https://api.keelapi.com/v1/compliance/exports?include_chain_entries=true" \
-H "Authorization: Bearer $KEEL_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"export_type": "full_audit",
"format": "json",
"filters": {
"created_at_from": "2026-05-01T00:00:00Z",
"created_at_to": "2026-05-07T23:59:59Z"
}
}'The important part is include_chain_entries=true. Without bundled chain entries, the verifier can still verify the export signature, but it cannot walk the event chain or verify permit closure evidence.
3. Download the export bundle and manifests
Download the export result from:
GET /v1/compliance/exports/{export_id}Preserve these files exactly as downloaded:
| File | Example name | Notes |
|---|---|---|
| Export bundle | bundle.json | The audit export payload. |
| Export manifest | export-manifest.json | The signed manifest for the bundle. |
| Public key manifest | public-key-manifest.json | Download from GET /v1/compliance/keys, or use --key-manifest-url. |
For non-self-attested verification, prefer the public key manifest or a pinned key over relying only on a key embedded in the artifact.
4. Run the verifier
Run export verification, chain walking, and closure verification together.
keel-verify export \
--export-file bundle.json \
--manifest export-manifest.json \
--key-manifest public-key-manifest.json \
--walk-events \
--verify-closureYou can also fetch the key manifest at verification time.
keel-verify export \
--export-file bundle.json \
--manifest export-manifest.json \
--key-manifest-url https://api.keelapi.com/v1/compliance/keys \
--walk-events \
--verify-closureThe current source-script argument names are --export-file and --manifest. If your packaged binary accepts positional files, the equivalent command is the same export bundle plus export manifest, with --walk-events and --verify-closure enabled.
5. Interpret the output
Successful verification prints VERIFIED, then separate WALK-EVENTS: VERIFIED and VERIFY-CLOSURE: VERIFIED sections when you enabled both checks.
VERIFIED
Export: bundle.json
Content hash: sha256:7f4a0e2d4f0a6c7c1a9c8a0c1e2b3d4f5a6b7c8d9e0f1234567890abcdef1234
Signature: ed25519:7n5e2i9Kq8nP4m1Zp0...
Public key: ed25519:BASE64_PUBLIC_KEY...
Key id: export-2026-annual
Trust source: key manifest (public-key-manifest.json) key_id=export-2026-annual status=active
WALK-EVENTS: chain_scope=project:6f38 first sequence_number=1028, prev_hash unverifiable from this bundle (continuity prior to window requires server-side verify_chain_integrity)
WALK-EVENTS: VERIFIED
chain_scopes: 1
entries_walked: 42
record_hash_checks: 42 PASS
prev_hash_checks: 41 PASS (excludes window-edge entries)
sequence_checks: 41 PASS
VERIFY-CLOSURE: VERIFIED
chain_scopes: 1
closures_verified: 9
signature_checks: 9 PASS
digest_checks: 18 PASS
dispatch_digest_check: PASSVERIFIED
Export: bundle.json
Content hash: sha256:7f4a0e2d4f0a6c7c1a9c8a0c1e2b3d4f5a6b7c8d9e0f1234567890abcdef1234
Signature: ed25519:7n5e2i9Kq8nP4m1Zp0...
Public key: ed25519:BASE64_PUBLIC_KEY...
Key id: export-2026-annual
Trust source: key manifest (public-key-manifest.json) key_id=export-2026-annual status=active
FAILED: WALK_RECORD_HASH_MISMATCH: event_id=evt_01JX2EXAMPLE expected=sha256:8b8d1b6c... actual=sha256:4c41a991...Read the output in layers:
VERIFIEDmeans the export bundle matched its signed export manifest.WALK-EVENTS: VERIFIEDmeans the bundled chain entries recomputed and linked correctly inside the exported window.VERIFY-CLOSURE: VERIFIEDmeans closure signatures, dispatch request body bytes digests, and provider/client digest references matched the bundled evidence.FAILED: <CODE>:means the verifier found a tampering signal or an untrusted format. Use the Tampering Detection Matrix.
6. What to do if verification fails
Treat any verification failure as an audit-integrity incident until disproven.
- Preserve the original export bundle, export manifest, public key manifest, verifier version, command, stdout, and stderr.
- Re-run the same command from a clean directory without modifying the downloaded files.
- Request a fresh export for the same time window and compare the failure.
- Confirm that the key manifest came from
GET /v1/compliance/keysfor the same Keel environment. - Stop relying on the affected export in audit files until the failure is explained.
- Escalate to your Keel admin and to security@keelapi.com. Include the export ID, command, verifier version, error code, and file hashes.
- For incidents, request an
incident_evidenceexport that brackets the affected window with the closest available checkpoints before and after the window.
Do not manually repair an export and then rely on the repaired copy. If the original fails verification, the original is the evidence.