Pular para o conteúdo principal

Audit Logs

Notifica maintains comprehensive audit logs for all sensitive operations performed on your account. Audit logs help you maintain compliance, debug issues, and monitor security events.

Overview

Every API key operation, team member change, subscription modification, domain configuration, and webhook change is automatically logged with:

  • Who performed the action (user, API key, or system)
  • What action was performed
  • When it happened (with microsecond precision)
  • Which resource was affected
  • Where the request came from (IP address, user agent)
  • Additional context (metadata specific to the action)

Audit logs are immutable — once created, they cannot be modified or deleted. They are retained indefinitely for compliance purposes.

Tracked Events

API Keys

EventDescriptionMetadata
api_key.createdA new API key was generatedenvironment, key_type, scopes
api_key.revokedAn API key was revokedkey_prefix, revoked_reason
api_key.rotatedAn API key was rotated with a grace periodold_key_prefix, new_key_prefix, grace_period_hours

Team Members

EventDescriptionMetadata
team_member.invitedA new team member was invited to the workspaceemail, role
team_member.removedA team member was removed from the workspaceemail, role
team_member.role_changedA team member's role or permissions were changedold_role, new_role

Subscriptions

EventDescriptionMetadata
subscription.createdA new subscription was createdplan_id, gateway
subscription.plan_changedPlan was upgraded or downgradedold_plan_id, new_plan_id, change_type
subscription.cancelledSubscription was cancelledreason, cancel_at_period_end
subscription.payment_failedA payment attempt failedinvoice_id, invoice_number, amount_cents, reason
subscription.expiredSubscription expired after grace periodreason, days_overdue

Domains

EventDescriptionMetadata
domain.addedA new sending domain was registereddomain, status
domain.verifiedDomain verification succeeded via DNS checkdomain, dkim_verified
domain.removedA sending domain was deleteddomain, was_verified

Webhooks

EventDescriptionMetadata
webhook.createdA new webhook endpoint was configuredurl, events
webhook.updatedWebhook configuration was modifiedurl, events, active
webhook.deletedA webhook endpoint was removedurl

API Reference

List Audit Logs

Retrieve audit logs for a tenant with optional filtering.

GET /api/internal/audit-logs

Query Parameters

ParameterTypeRequiredDescription
tenant_idstringYesFilter logs by tenant ID
actionstringNoFilter by specific action (e.g., api_key.created)
resource_typestringNoFilter by resource type (e.g., api_key, team_member)
actor_typestringNoFilter by actor type: user, system, or api_key
limitintegerNoNumber of records to return (default: 50, max: 200)

Example Request

curl -X GET "https://api.notifica.app/api/internal/audit-logs?tenant_id=abc123&action=api_key.created&limit=10" \
-H "Authorization: Bearer your-admin-token"

Example Response

{
"audit_logs": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "abc123",
"actor_id": "def456",
"actor_type": "user",
"action": "api_key.created",
"resource_type": "api_key",
"resource_id": "789xyz",
"metadata": {
"environment": "production",
"key_type": "publishable",
"scopes": ["notifications:send"]
},
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
"inserted_at": "2026-02-12T10:30:45.123456Z"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"tenant_id": "abc123",
"actor_id": null,
"actor_type": "system",
"action": "subscription.payment_failed",
"resource_type": "subscription",
"resource_id": "sub_abc123",
"metadata": {
"invoice_id": "inv_xyz789",
"invoice_number": "INV-2026-001",
"amount_cents": 9900,
"reason": "card_declined"
},
"ip_address": null,
"user_agent": null,
"inserted_at": "2026-02-12T08:15:22.987654Z"
}
],
"count": 2
}

Response Fields

FieldTypeDescription
idstringUnique audit log entry ID
tenant_idstringTenant the action was performed on
actor_idstring | nullID of the actor (user, API key, or null for system)
actor_typestringType of actor: user, api_key, or system
actionstringThe action that was performed (see event tables above)
resource_typestringType of resource affected (e.g., api_key, team_member)
resource_idstring | nullID of the affected resource
metadataobjectAdditional context specific to the action
ip_addressstring | nullIP address of the requester (null for system actions)
user_agentstring | nullUser agent of the requester (null for system actions)
inserted_atstringISO 8601 timestamp when the log was created

Actor Types

Audit logs record three types of actors:

  • user — A dashboard user (team member) performing an action through the web UI
  • api_key — An API key used to make a programmatic request
  • system — Automated system actions (e.g., subscription expiration, payment failures)

Retention Policy

Audit logs are retained indefinitely to support compliance requirements (LGPD, GDPR, SOC 2). They cannot be deleted except as part of a full account deletion request.

If you require audit log exports for compliance or archival purposes, contact support.

Use Cases

Compliance & Security

  • LGPD/GDPR compliance: Track all access to personal data and demonstrate accountability
  • Security audits: Monitor API key creation, rotation, and revocation
  • Access reviews: Verify who has access to your workspace and when permissions changed

Debugging & Troubleshooting

  • Payment failures: Identify when and why subscription payments failed
  • Domain verification issues: Track domain registration and verification attempts
  • Webhook debugging: See when webhook configurations were changed

Operational Monitoring

  • Team changes: Monitor when team members are added, removed, or role changes occur
  • Subscription lifecycle: Track plan changes, cancellations, and reactivations
  • API usage patterns: Analyze API key usage by examining audit logs

SDK Examples

Audit logs are accessible via all official Notifica SDKs. Note that audit log access requires admin authentication (bearer token from backoffice login), not regular API keys.

Node.js

import { NotificaAdmin } from '@notifica/node';

const admin = new NotificaAdmin({
token: process.env.NOTIFICA_ADMIN_TOKEN,
});

// List audit logs with filters
const { auditLogs } = await admin.auditLogs.list({
tenantId: 'your-tenant-id',
action: 'api_key.created',
limit: 50,
});

for (const log of auditLogs) {
console.log(`${log.insertedAt} | ${log.actorType} | ${log.action}`);
}

// Filter by resource type
const apiKeyLogs = await admin.auditLogs.list({
tenantId: 'your-tenant-id',
resourceType: 'api_key',
});

Python

from notifica import NotificaAdmin

admin = NotificaAdmin(token="your-admin-token")

# List audit logs
audit_logs = admin.audit_logs.list(
tenant_id="your-tenant-id",
action="api_key.created",
limit=50
)

for log in audit_logs:
print(f"{log.inserted_at} | {log.actor_type} | {log.action}")

# Filter by date range
recent_logs = admin.audit_logs.list(
tenant_id="your-tenant-id",
actor_type="user",
limit=100
)

Go

package main

import (
"context"
"fmt"
"github.com/notifica-tech/notifica-go"
)

func main() {
client := notifica.NewAdminClient("your-admin-token")

logs, err := client.AuditLogs.List(context.Background(), &notifica.AuditLogListParams{
TenantID: "your-tenant-id",
Action: notifica.String("api_key.created"),
ResourceType: notifica.String("api_key"),
Limit: notifica.Int(50),
})
if err != nil {
panic(err)
}

for _, log := range logs.AuditLogs {
fmt.Printf("%s | %s | %s\n", log.InsertedAt, log.ActorType, log.Action)
}
}

Java

import com.notifica.NotificaAdmin;
import com.notifica.model.AuditLog;
import com.notifica.param.AuditLogListParams;

NotificaAdmin admin = NotificaAdmin.builder()
.token("your-admin-token")
.build();

AuditLogListParams params = AuditLogListParams.builder()
.tenantId("your-tenant-id")
.action("api_key.created")
.limit(50L)
.build();

List<AuditLog> logs = admin.auditLogs().list(params).getAuditLogs();

for (AuditLog log : logs) {
System.out.printf("%s | %s | %s%n",
log.getInsertedAt(), log.getActorType(), log.getAction());
}

Raw API Examples

If you're not using an SDK, you can access audit logs directly via HTTP:

Export Recent Audit Logs

import requests

API_URL = "https://app.usenotifica.com.br/api/internal/audit-logs"
ADMIN_TOKEN = "your-admin-token"
TENANT_ID = "your-tenant-id"

response = requests.get(
API_URL,
params={"tenant_id": TENANT_ID, "limit": 100},
headers={"Authorization": f"Bearer {ADMIN_TOKEN}"}
)

audit_logs = response.json()["audit_logs"]
print(f"Retrieved {len(audit_logs)} audit log entries")

for log in audit_logs:
print(f"{log['inserted_at']} | {log['actor_type']} | {log['action']}")

Monitor Critical Actions

const axios = require('axios');

const CRITICAL_ACTIONS = [
'api_key.revoked',
'team_member.removed',
'subscription.cancelled',
'domain.removed',
'webhook.deleted'
];

async function checkCriticalActions(tenantId) {
const response = await axios.get('https://app.usenotifica.com.br/api/internal/audit-logs', {
params: { tenant_id: tenantId, limit: 50 },
headers: { Authorization: `Bearer ${process.env.ADMIN_TOKEN}` }
});

const criticalLogs = response.data.audit_logs.filter(log =>
CRITICAL_ACTIONS.includes(log.action)
);

if (criticalLogs.length > 0) {
console.warn(`⚠️ Found ${criticalLogs.length} critical actions:`);
criticalLogs.forEach(log => {
console.warn(` - ${log.action} by ${log.actor_type} at ${log.inserted_at}`);
});
}
}

Best Practices

  1. Regular Reviews: Review audit logs weekly to catch unauthorized changes
  2. Alerting: Set up automated alerts for critical actions (key revocation, member removal)
  3. Compliance: Export and archive audit logs quarterly for compliance documentation
  4. Investigation: When investigating issues, filter by resource_id to trace a specific resource's history
  5. Team Awareness: Share audit log access with your security and compliance teams