How Audit Logging Tracks API Operations in OpenWA: Complete Implementation Guide
OpenWA implements a comprehensive audit logging subsystem using NestJS and TypeORM to capture every significant API interaction, storing detailed context including API keys, session IDs, HTTP metadata, and error states in a searchable database table.
The audit logging system in OpenWA (WhatsApp API) provides administrators with complete visibility into API usage patterns, security events, and operational troubleshooting data. Built on a three-layer architecture, this subsystem automatically records who performed what action, when, and with what result across all WhatsApp session operations.
Architecture Overview
The audit logging implementation follows a standard NestJS modular pattern with clear separation of concerns across three distinct layers:
- Controller Layer – Exposes the
GET /auditREST endpoint for log retrieval - Service Layer – Contains
AuditServicewith methods for creating, querying, and cleaning up log entries - Persistence Layer – Defines the
AuditLogentity schema mapped to theaudit_logdatabase table
All components are registered in src/modules/audit/audit.module.ts, which wires together the TypeORM repository, service logic, and HTTP controller.
Core Implementation Files
AuditService: The Central Logging Engine
Located in src/modules/audit/audit.service.ts, the AuditService class provides the primary interface for recording API operations. The core log method accepts an action type, severity level, and a rich context object, then persists an AuditLog entity via TypeORM.
// Core method signature from audit.service.ts
async log(
action: AuditAction,
severity: AuditSeverity,
context: AuditContext
): Promise<AuditLog>
The service exposes convenience wrappers that prepend severity levels:
logInfo– Records informational events (successful operations)logWarn– Captures warning states requiring attentionlogError– Stores failed operations with error details
For retrieval, the findAll method builds dynamic SQL where clauses from AuditQueryOptions, supporting date range filtering, pagination via limit/offset, and severity-based queries. The service also provides cleanup, which removes entries older than a configurable retention period to prevent database bloat.
AuditController: REST API for Log Access
The AuditController in src/modules/audit/audit.controller.ts exposes the GET /audit endpoint for administrators. It translates incoming query parameters into an AuditQueryOptions object and returns paginated results with total counts.
// Example request handling in audit.controller.ts
@Get()
async findAll(@Query() query: AuditQueryOptions) {
return this.auditService.findAll(query);
}
Query parameters support filtering by action, severity, apiKeyId, sessionId, and date ranges, enabling precise forensic analysis of specific API operations or credential usage.
AuditLog Entity: Database Schema Definition
The AuditLog entity defined in src/modules/audit/entities/audit-log.entity.ts maps to the audit_log table with the following critical columns:
action– Enum tracking specific operations (e.g.,SEND_MESSAGE,CREATE_GROUP)severity– Classification asINFO,WARN, orERRORapiKeyId/apiKeyName– Identifies the credential performing the requestsessionId/sessionName– Links the log to specific WhatsApp sessionsmethod,path,statusCode– Complete HTTP request contextmetadata– JSON column for flexible additional data (message IDs, group names)errorMessage– Populated exclusively for failed operationscreatedAt– Automatic timestamp generated by TypeORM
Logging API Operations in Practice
When processing requests, OpenWA services inject AuditService and invoke logging methods with request context. The following pattern from the source demonstrates tracking a message send operation:
@Injectable()
export class MessageService {
constructor(
private readonly audit: AuditService,
// additional dependencies...
) {}
async sendMessage(payload: SendMessageDto, ctx: RequestContext) {
try {
// Business logic to send WhatsApp message...
await this.audit.logInfo(AuditAction.SEND_MESSAGE, {
apiKey: ctx.apiKey,
sessionId: ctx.session.id,
ipAddress: ctx.ip,
method: ctx.method,
path: ctx.path,
statusCode: 200,
metadata: { messageId: result.id },
});
} catch (err) {
await this.audit.logError(AuditAction.SEND_MESSAGE, {
apiKey: ctx.apiKey,
sessionId: ctx.session.id,
ipAddress: ctx.ip,
method: ctx.method,
path: ctx.path,
statusCode: 500,
errorMessage: err.message,
});
throw err;
}
}
}
This implementation ensures both successful operations and failures are captured with identical context, enabling complete audit trails for compliance and debugging.
Querying and Managing Audit Logs
Administrators retrieve logs via standardized HTTP requests:
GET /audit?action=SEND_MESSAGE&severity=INFO&limit=20&offset=0
The response returns a paginated JSON structure:
{
"data": [
{
"id": "c1a2b3d4-e5f6-7890-abcd-1234567890ef",
"action": "SEND_MESSAGE",
"severity": "INFO",
"apiKeyId": "key-123",
"apiKeyName": "Production API Key",
"sessionId": "session-abc",
"ipAddress": "203.0.113.42",
"method": "POST",
"path": "/messages",
"statusCode": 200,
"metadata": { "messageId": "msg-987" },
"createdAt": "2026-05-21T14:33:12.000Z"
}
],
"total": 42
}
For maintenance, the cleanup method in AuditService executes scheduled deletions based on configurable retention days, ensuring the audit_log table remains performant as volume scales.
Summary
- Three-layer architecture: Controller (
GET /audit), Service (AuditService), and Entity (AuditLog) work together insrc/modules/audit/ - Comprehensive context capture: Every log stores API key, session, IP, HTTP method/path, status code, and optional metadata
- Severity-based logging: Use
logInfo,logWarn, orlogErrorto classify events automatically - Queryable storage: Filter by action type, date ranges, or credentials via
AuditQueryOptions - Automatic maintenance: Built-in
cleanupfunctionality prevents unlimited database growth
Frequently Asked Questions
What information does OpenWA store in each audit log entry?
Each entry in the audit_log table captures the action performed (enum), severity level (INFO/WARN/ERROR), the API key and session identifiers, source IP address, HTTP method and path, response statusCode, optional JSON metadata, and errorMessage for failures. The createdAt timestamp is automatically generated by TypeORM when the record persists.
How do I query audit logs via the API?
Send a GET request to the /audit endpoint with query parameters matching AuditQueryOptions. Supported filters include action, severity, apiKeyId, sessionId, and date ranges. The controller returns a paginated response containing both the dataset array and total count, enabling frontend pagination implementations.
Can I configure automatic cleanup of old audit logs?
Yes. The AuditService includes a cleanup method that removes entries older than a configurable number of days. This housekeeping function prevents the audit_log table from growing indefinitely and can be invoked via scheduled tasks or administrative triggers according to your retention policy requirements.
Which API operations trigger audit logging in OpenWA?
Any service can trigger audit logging by injecting AuditService and calling log, logInfo, logWarn, or logError. Common tracked operations include SEND_MESSAGE, session creation, group management, and webhook processing. The system uses the AuditAction enum to standardize operation names across the codebase.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →