ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop on the web portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
Policies
    Policy Catalog
    Authentication
    Authorization
    MCP Authorization
    Security & Validation
      Rate LimitingComplex Rate LimitingAudit LogsRequest ValidationWeb Bot AuthBot DetectionPrompt Injection DetectionMCP Capability FilterRequire OriginRequest Size LimitSecret MaskingData Loss Prevention InboundData Loss Prevention OutboundStripe Webhook AuthAkamai AI Firewall
    Metrics, Billing & Quotas
    Testing
    Request Modification
    Response Modification
    Upstream Authentication
    Archival
    GraphQL
    Other
    Guides
Handlers
API Keys
Rate Limiting
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
GraphQL
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Security & Validation

Audit Logs Policy

Audit logging is an important part of API security that plays a critical role in detecting and correcting issues such as unauthorized access or permission elevations within your system. Audit logging is also a requirement for many compliance certifications as well as part of the buying criteria for larger enterprises.

Adding Audit Logging to your APIs that are secured with Zuplo is as easy as adding a policy. Typically you want to add audit logs to any API that modifies data, however depending on the API you may want it on read operations as well (i.e. retrieve a secret key, etc.)

Enterprise Feature

This policy is only available as part of our enterprise plans. It's free to try only any plan for development only purposes. If you would like to use this in production reach out to us: sales@zuplo.com

Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

config/policies.json
{ "name": "my-audit-log-inbound-policy", "policyType": "audit-log-inbound", "handler": { "export": "AuditLogInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "eventTypeBase": "com.zuplo.api", "include": { "geolocation": true, "ipAddress": true, "queryParams": true, "user": true }, "samplingRate": 1 } } }

Policy Configuration

  • name <string> - The name of your policy instance. This is used as a reference in your routes.
  • policyType <string> - The identifier of the policy. This is used by the Zuplo UI. Value should be audit-log-inbound.
  • handler.export <string> - The name of the exported type. Value should be AuditLogInboundPolicy.
  • handler.module <string> - The module containing the policy. Value should be $import(@zuplo/runtime).
  • handler.options <object> - The options for this policy. See Policy Options below.

Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

  • eventTypeBase <string> - Reverse-DNS prefix used for the auto-emitted request event type. Defaults to 'com.zuplo.api'. Defaults to "com.zuplo.api".
  • bucketId <string> - Override the bucket id this policy emits events for. Defaults to the bucket id from the runtime environment.
  • samplingRate <number> - Fraction of requests to capture, between 0 (none) and 1 (all). Defaults to 1. Defaults to 1.
  • include <object> - Controls which potentially-sensitive parts of each request are captured in the auto-emitted audit event. Disable fields to satisfy your own data-handling and PII policies. All are enabled by default.
    • queryParams <boolean> - Include the request's query-string parameters in the logged URL. Disable if query strings may contain sensitive data. Defaults to true.
    • user <boolean> - Include the authenticated user / actor identity (subject, email, connection). Defaults to true.
    • ipAddress <boolean> - Include the caller's IP address. Defaults to true.
    • geolocation <boolean> - Include the caller's geolocation (country, region, city). Defaults to true.

Using the Policy

Automatic Request Auditing

Once the Audit Logs policy is added to a route, it automatically records one structured audit event for every request that passes through it — no extra code required. Each event captures who made the request, what they called, and the outcome.

The automatic event uses the type com.zuplo.api.request and includes the actor, the HTTP method and path, the response status, and the geolocation of the caller.

For very high-volume routes you can record only a fraction of requests by setting the samplingRate option (for example 0.1 to capture 10% of requests).

Controlling What's Logged

Audit events can contain personal or sensitive data. To keep audit logging compliant with your own data-handling and PII policies, use the include option to turn individual fields off. Everything is captured by default; set a flag to false to omit it:

  • queryParams — the request's query-string parameters (in the logged URL).
  • user — the authenticated user / actor identity (subject, email, connection). The user vs anonymous classification is always kept, but the identifying values are omitted when disabled.
  • ipAddress — the caller's IP address.
  • geolocation — the caller's country, region, and city.
Code
{ "name": "audit-logs-inbound", "policyType": "audit-logs", "handler": { "export": "AuditLogInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "include": { "queryParams": false, "ipAddress": false } } } }

These settings also apply to the geolocation automatically added to custom events emitted via log().

Emitting Custom Events

Beyond the automatic per-request event, you can record your own domain events — for example "account deleted" or "API key rotated" — from a handler or custom policy using the static AuditLogInboundPolicy.log() method. Any fields you don't supply are filled in automatically from the request context (event id, time, actor, request id, IP address, user agent, and so on).

Code
// module - ./modules/audit.ts import { AuditLogInboundPolicy, ZuploContext, ZuploRequest, } from "@zuplo/runtime"; export async function deleteAccount( request: ZuploRequest, context: ZuploContext, ) { const accountId = request.params.accountId; // ...perform the delete... AuditLogInboundPolicy.log(context, { type: "com.acme.account.deleted", subject: `account|${accountId}`, resources: [{ type: "account", id: accountId }], success: true, data: { reason: "user-initiated" }, }); return new Response(null, { status: 204 }); }

The event object passed to log() supports the following fields. Only type is required.

  • type — the event type, in reverse-DNS form (e.g. com.acme.account.deleted).
  • subject — the primary entity the event is about.
  • resources — an array of { type, id, metadata? } describing the resources the event affected.
  • success — whether the operation succeeded.
  • data — any additional structured data to attach to the event.
  • actor — override the automatically-derived actor ({ sub, type, email, connection }).
  • country, region, city — override the caller's geolocation. These default to the current request's location, so you normally don't need to set them.

Audit logging is best-effort: log() never throws and never blocks or fails the request, even if an event cannot be recorded.

Audit Log Event Shape

Every audit event follows the CloudEvents 1.0 envelope. An automatically-emitted request event looks like this:

Code
{ "specversion": "1.0", "id": "e6c8b1f2-2c3d-4a5b-9e10-1f2a3b4c5d6e", "type": "com.zuplo.api.request", "time": "2026-07-05T18:12:04.123Z", "actorsub": "user|12356", "actortype": "user", "requestid": "b1a2c3d4-e5f6-7890-abcd-ef1234567890", "httpmethod": "GET", "httpurl": "/customers/12345?expand=orders", "httpstatus": 200, "success": true, "ipaddress": "203.0.113.7", "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...", "country": "US", "region": "Washington", "city": "Seattle" }

Custom events emitted via log() share the same envelope; the type, subject, resources, success, and data fields come from the event you pass, and the remaining fields are populated from the request context.

Viewing Audit Logs

In-portal viewing and retrieval of audit logs is coming soon.

Read more about how policies work

Edit this page
Last modified on July 6, 2026
Complex Rate LimitingRequest Validation
On this page
  • Configuration
    • Policy Configuration
    • Policy Options
  • Using the Policy
  • Automatic Request Auditing
  • Controlling What's Logged
  • Emitting Custom Events
  • Audit Log Event Shape
  • Viewing Audit Logs
JSON
JSON
TypeScript
JSON