DocsRegulatory evidence bundles
Regulatory evidence bundles
Generate and verify RPT-016 signed ZIP archives for regulator submission.
RPT-016 is a signed ZIP archive produced for regulatory submission. It contains an executive PDF summary, a SHA-256 manifest of every evidence file, and a HMAC-SHA-256 signature across the entire bundle.
Bundle structure
ZIP STRUCTURE
RPT-016-{checkId}.zip
├── executive-summary.pdf # Human-readable cover report
├── manifest.sha256.json # SHA-256 hash of every file
├── signature.hmac # HMAC-SHA-256 over manifest
├── kyc/
│ ├── RPT-001-{checkId}.pdf
│ └── liveness-session.json
├── aml/
│ ├── RPT-003-{checkId}.pdf
│ └── sanctions-raw.json
└── audit/
└── RPT-015-{checkId}.pdfGenerating a bundle
CURL
curl -X POST https://api.trustverify.co.uk/api/v1/reports/rpt-016 \
-H "Authorization: Bearer tv_live_sk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"checkId": "chk_01J8KX9QMN23PQRST",
"includeTypes": ["RPT-001","RPT-003","RPT-015"],
"regulatorRef": "FCA-2026-00142"
}'
# Response: { "bundleId": "bnd_abc123", "status": "generating", "estimatedReadyAt": "…" }Verifying the HMAC signature
NODE.JS
import crypto from 'crypto';
import fs from 'fs';
const manifest = fs.readFileSync('manifest.sha256.json');
const signature = fs.readFileSync('signature.hmac', 'utf8').trim();
const secret = process.env.TV_WEBHOOK_SECRET!;
const expected = crypto
.createHmac('sha256', secret)
.update(manifest)
.digest('hex');
const isValid = crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex'),
);
console.log(isValid ? '✓ Bundle is authentic' : '✗ Signature mismatch');Always verify the HMAC signature before submitting a bundle to a regulator. A failed signature check means the bundle was modified after TrustVerify signed it.