Audit Trail
Each Korala document carries a complete audit trail that records each action from creation through completion. The trail is immutable; no one can modify or delete an event.
Event Types
| Event | Description |
|---|---|
document_created | Document was uploaded and created |
document_sent | Document was sent for signing |
document_viewed | A signer opened the document |
field_filled | A signer filled in a field value |
field_locked | The sender fixed a field value for a signer through a signing packet; the signer reviews it but cannot change it |
signature_applied | A signature image was applied to a field |
document_signed | A signer completed all their fields |
document_completed | All signers finished and Korala applied the cryptographic seal |
document_failed | Document completion failed after retries |
document_voided | Document was cancelled before completion |
document_declined | A signer declined to sign |
reminder_sent | A signing reminder was sent to a signer |
access_revoked | A signer’s access was revoked |
Retrieving the Audit Trail
TypeScript
import { KoralaClient } from '@korala/api-client';
const korala = new KoralaClient({
apiKeyId: 'your-api-key-id',
apiSecret: 'your-api-secret',
});
const events = await korala.documents.getAuditTrail(documentId);
for (const event of events) {
console.log(`${event.createdAt}: ${event.eventType}`);
if (event.ipAddress) {
console.log(` IP: ${event.ipAddress}`);
}
if (event.signerId) {
console.log(` Signer: ${event.signerId}`);
}
}Event Details
Each audit event includes:
| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier |
documentId | string | The document this event belongs to |
signerId | string | null | The signer who triggered the event (if applicable) |
eventType | string | One of the event types listed above |
ipAddress | string | null | IP address of the actor |
claimedIpAddress | string | null | Partner-asserted end-user IP (from X-Client-IP header) |
userAgent | string | null | Browser or client user agent |
metadata | object | null | Additional context (e.g., field ID for field_filled) |
createdAt | string | ISO 8601 timestamp |
Response Format
[
{
"id": "evt_abc123",
"documentId": "doc_xyz789",
"signerId": null,
"eventType": "document_created",
"ipAddress": "203.0.113.1",
"claimedIpAddress": null,
"userAgent": "KoralaClient/1.0",
"metadata": null,
"createdAt": "2024-01-14T09:00:00Z"
},
{
"id": "evt_def456",
"documentId": "doc_xyz789",
"signerId": "sgn_abc123",
"eventType": "document_signed",
"ipAddress": "198.51.100.42",
"claimedIpAddress": "192.0.2.10",
"userAgent": "Mozilla/5.0...",
"metadata": { "bulkSign": false },
"createdAt": "2024-01-15T10:30:00Z"
}
]Certificate of Completion
When a document completes, Korala generates a Certificate of Completion PDF that summarizes the entire audit trail. This certificate includes:
- Document name and ID
- All signers with their signing timestamps
- IP addresses and user agents for each action
- Cryptographic signature verification details
The certificate is available as certificateFileUrl on the completed document:
TypeScript
const document = await korala.documents.get(documentId);
if (document.status === 'completed' && document.certificateFileUrl) {
// Download the Certificate of Completion
const certificate = await fetch(document.certificateFileUrl);
fs.writeFileSync('certificate.pdf', await certificate.buffer());
}Signing packet evidence
A signing packet adds shared authorization evidence without replacing the document audit trail. Each signed document keeps its certificate and records the packet ID, packet item ID, packet action ID, and manifest hash in its audit metadata. You can verify one document without retrieving the other packet items.
The packet Certificate of Completion records the cross-document context:
- Frozen document manifest and source hashes
- Recipient consent and confirmation text
- Authentication method, IP address, user agent, and timestamps
- Result for each selected item
Retrieve packet events and the certificate URL through the authenticated management API:
const audit = await korala.signingPackets.audit(packetId);
for (const event of audit.events) {
console.log(`${event.createdAt}: ${event.eventType}`);
}
if (audit.certificateUrl) {
const certificate = await fetch(audit.certificateUrl);
// Store or inspect the packet Certificate of Completion.
}certificateUrl remains null until the packet worker finishes the action and
generates the certificate.
IP Address Tracking
Korala captures two IP address fields per event:
ipAddress: The IP address Korala’s servers observe (the direct connection)claimedIpAddress: The end-user’s IP address your application asserts via theX-Client-IPrequest header
If you call the API on behalf of end users (e.g., through a backend proxy), pass the X-Client-IP header so the audit trail reflects the end user’s IP rather than your server’s.
Using Audit Trails for Compliance
Audit trails are essential for legal compliance in electronic signatures. They provide evidence of:
- Intent to sign: The signer viewed the document and filled fields
- Identity: IP address, user agent, and timing establish who signed
- Integrity: The cryptographic seal and RFC 3161 timestamp prove no one has modified the document since signing
- Non-repudiation: The complete event history makes it difficult for a signer to deny their participation