May 20, 2026 · Technical Deep Dive
What's Inside an E-Signature Audit Trail?
A signed PDF is worthless without proof of who signed it, when, and that nothing changed afterwards. Here's exactly what's inside Signbee's SHA-256 certificate of completion — and how to verify it programmatically.
Founder, Signbee
TL;DR
An audit trail is the legal backbone of every e-signature. It captures the SHA-256 hash of the document at signing time, the signer's IP address, browser fingerprint, and timestamps — creating a tamper-proof chain of evidence. If the document is altered by even one character, the hash won't match. Here's how it works under the hood and how to verify it in code.
Why the audit trail matters more than the signature
Most developers focus on the signature itself — the drawn squiggle, the typed name, the checkbox. But in a legal dispute, the signature is the least important part. What matters is the evidence trail proving three things:
The ESIGN Act, eIDAS, and ECA 2000 all require these elements for an electronic signature to be legally valid. Without a proper audit trail, your signed document is just a PDF with a picture on it.
What Signbee captures during the signing process
Every document sent through the Signbee API generates a timeline of events with cryptographic proof at each step:
| Event | Data captured |
|---|---|
| Document created | Timestamp, sender IP, document hash |
| Email delivered | Timestamp, recipient email, delivery status |
| Document viewed | Timestamp, signer IP, user agent |
| Signature applied | Timestamp, signer IP, user agent, signature image |
| Document completed | Final document hash, certificate generated |
How SHA-256 hashing works (non-cryptographer version)
SHA-256 takes any input — a 1-page NDA or a 500-page merger agreement — and produces a fixed 64-character hexadecimal string. This hash is a one-way function: you can always compute the hash from the document, but you can never reconstruct the document from the hash.
The critical property: even a single changed character produces a completely different hash. Not a slightly different hash. A completely different one.
import { createHash } from "crypto";
// Original document content
const original = "# NDA\nThis agreement is between Party A and Party B.";
const originalHash = createHash("sha256").update(original).digest("hex");
console.log(originalHash);
// → "a3f2b8c1d4e5f67890abcdef1234567890abcdef1234567890abcdef12345678"
// Tampered document — one character changed ("A" → "C")
const tampered = "# NDA\nThis agreement is between Party C and Party B.";
const tamperedHash = createHash("sha256").update(tampered).digest("hex");
console.log(tamperedHash);
// → "7e9f1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef123456"
// Completely different hash — tamper detected
console.log(originalHash === tamperedHash); // → falseWhen a document is signed through Signbee, we compute the SHA-256 hash of the document at the exact moment the signature is applied. This hash is stored in our database, embedded in the certificate of completion, and included in the webhook event payload. If you ever need to prove the document hasn't been tampered with, you re-hash it and compare.
The certificate of completion
After a document is signed, Signbee generates a certificate of completion — a separate page appended to the end of the signed PDF. This certificate contains the full audit trail in human-readable format:
Verifying document integrity via the API
You don't need to manually compute hashes. The Signbee API returns the audit trail data for any completed document:
const response = await fetch("https://signb.ee/api/v1/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer sb_live_your_api_key",
},
body: JSON.stringify({
markdown: "# Non-Disclosure Agreement\n\nBetween Party A and Party B...",
recipient_name: "Jane Smith",
recipient_email: "jane@example.com",
}),
});
const { document_id, signing_url } = await response.json();
// Later, after signing — check status and get audit trail
const doc = await fetch(
`https://signb.ee/api/v1/documents/${document_id}`,
{ headers: { "Authorization": "Bearer sb_live_your_api_key" } }
);
const {
status, // "completed"
document_hash, // SHA-256 of original document
signed_hash, // SHA-256 of signed document
signed_at, // ISO 8601 timestamp
signer_ip, // IP address at time of signing
certificate_id, // Unique certificate reference
} = await doc.json();How this compares to DocuSign's audit trail
DocuSign provides a "Certificate of Completion" with similar information — timestamps, IP addresses, and signer details. However, there are key differences in how developers interact with it:
| Feature | DocuSign | Signbee |
|---|---|---|
| Hash algorithm | Not publicly documented | SHA-256 (explicit) |
| Hash in API response | Requires separate call | Included in document status |
| Certificate format | Appended PDF page | Appended PDF page |
| Webhook with hash | Via DocuSign Connect | Standard webhook payload |
| Independent verification | Download + re-hash manually | Compare hashes via API |
Real-world scenario: disputing a signed contract
Here's a concrete example. A freelancer sends a retainer agreement to a client through the Signbee API. Three months later, the client claims "the agreement said $3,000/month, not $5,000/month."
The freelancer retrieves the signed document and the certificate of completion. The SHA-256 hash on the certificate matches the hash of the document in their records. The hash proves the document has not been altered since the moment the client signed it. The audit trail shows the client's IP address, the timestamp, and the browser they used.
This is non-repudiation in practice. The client cannot credibly claim they signed a different document, because any alteration — even changing "$5,000" to "$3,000" — would produce a completely different SHA-256 hash.
Building your own verification layer
For more on how Signbee's signing certificates work at a low level, see our technical guide on how SHA-256 signing certificates work.
Standalone Verification: Independent Python & Node.js CLI Script
True non-repudiation means you never have to trust Signbee or any third party to prove that a document is authentic. You can verify the cryptographic integrity of any signed PDF independently using standard command-line tools or a simple script:
import hashlib
import json
import sys
def verify_document_integrity(pdf_filepath: str, expected_sha256: str) -> bool:
sha256 = hashlib.sha256()
with open(pdf_filepath, "rb") as f:
while chunk := f.read(65536):
sha256.update(chunk)
computed_digest = sha256.hexdigest()
print(f"Computed SHA-256: {computed_digest}")
print(f"Expected SHA-256: {expected_sha256}")
if computed_digest.lower() == expected_sha256.lower():
print("✅ INTEGRITY VERIFIED: Document matches cryptographic certificate 100%.")
return True
else:
print("❌ TAMPER ALERT: Document content differs from signed certificate seal!")
return False
# Usage: python verify.py contract_signed.pdf a3f2b8c1d4...
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: python verify.py <file.pdf> <expected_sha256>")
sys.exit(1)
verify_document_integrity(sys.argv[1], sys.argv[2])SOC 2 Type II and ISO 27001 Audit Compliance
When enterprise auditors evaluate software systems handling customer contracts or vendor onboarding, they test whether document state changes can be modified by database administrators or unauthorized engineers.
Audit Trail Retention Best Practices:
- Write-Once-Read-Many (WORM) Storage: Stream the generated certificate of completion and signed PDF directly into an AWS S3 bucket configured with Object Lock in Compliance Mode.
- Zero Mutability: Ensure database records store the immutable SHA-256 digest alongside the signed timestamp. Any attempt to re-generate or overwrite the document results in a cryptographic hash mismatch.
Node.js Implementation: Automated Audit Trail Validator
For engineering teams building automated compliance gates or ingestion pipelines in TypeScript/Node.js, you can verify the audit certificate and PDF integrity programmatically before archiving:
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
interface AuditVerificationResult {
verified: boolean;
computedHash: string;
expectedHash: string;
timestamp: string;
}
export function verifySignedDocument(
pdfBuffer: Buffer,
expectedSha256: string
): AuditVerificationResult {
const hash = createHash("sha256").update(pdfBuffer).digest("hex");
const verified = hash.toLowerCase() === expectedSha256.toLowerCase();
return {
verified,
computedHash: hash,
expectedHash: expectedSha256,
timestamp: new Date().toISOString(),
};
}
// Example usage in an event-driven webhook handler:
const fileBuffer = readFileSync("./contracts/signed_msa.pdf");
const result = verifySignedDocument(fileBuffer, "9c8d7e6f5a4b1234...");
if (!result.verified) {
throw new Error("Audit verification failed: cryptographic seal mismatch.");
}
console.log("Cryptographic audit trail successfully validated:", result);Federal Evidence Rules and Chain of Custody
In high-stakes commercial litigation, opposing counsel will frequently challenge electronic evidence under the hearsay rule or allege that document records were altered post-execution. Signbee's cryptographic audit trail establishes an unbroken chain of custody satisfying Federal Rules of Evidence Rule 803(6) (Records of a Regularly Conducted Activity) and Rule 902(13) (Certified Records Generated by an Electronic Process).
Because every audit event records synchronized UTC timestamps, geographic IP routing headers, and cryptographic hashes at both document creation and final signature execution, corporate counsel can tender the Certificate of Completion as self-authenticating documentary proof without requiring expert witness testimony.
Frequently Asked Questions
What is an e-signature audit trail?
A tamper-proof record of every event in the signing process — creation, delivery, viewing, and signing — with timestamps, IP addresses, and SHA-256 document hashes. It's the legal evidence that makes the signature enforceable.
How does SHA-256 protect signed documents?
SHA-256 creates a unique 64-character fingerprint of the document at signing time. Any change to the document — even one character — produces a completely different hash. Comparing hashes proves the document hasn't been tampered with.
Would this hold up in court?
Yes. The ESIGN Act (US), eIDAS (EU), and ECA 2000 (UK) all recognise electronic signatures with proper audit trails. SHA-256 hash verification provides non-repudiation — the signer cannot credibly claim the document was altered. See our legal compliance guide.
Every document gets a SHA-256 certificate — 5 free docs/month.
Last updated: May 20, 2026 · Michael Beckett is the founder of Signbee and B2bee Ltd.