---
title: Audit Log Reference
path: reference/audit-log
status: published
---

# Audit Log Reference

Every mutating request against ScaiGrid is recorded in the audit log. This reference describes how to query and export it.

**Required permission:** `admin:access` (for tenant audit), `accounting:view_partner` (for partner-wide), super admin (for platform-wide).

## What's recorded

For every POST/PUT/PATCH/DELETE request (with a few exceptions like audit queries themselves, OAI-compat inference, and health checks):

- Actor identity (user ID, email, partner, tenant)
- Actor type (`user` / `service` / `webhook`)
- Action (`model.create`, `user.update`, `budget.delete`, etc.)
- Resource type and ID
- IP address and User-Agent
- Status (`SUCCESS` / `FAILURE`)
- Timestamp
- Request ID (for correlating with application logs)

Read requests are not logged by default to avoid log explosion. Module-specific audit can be enabled for sensitive reads via module config.

## GET /v1/audit-log

Query the audit log.

Query params:

| Param | Description |
|-------|-------------|
| `start` | ISO 8601 timestamp |
| `end` | ISO 8601 timestamp |
| `action` | Filter by action string (e.g., `user.create`) |
| `actor_id` | Filter by actor |
| `resource_type` | `user`, `model`, `backend`, `budget`, etc. |
| `resource_id` | Specific resource |
| `status` | `SUCCESS` / `FAILURE` |
| `ip_address` | Filter by IP |
| `limit` | Page size (default 100, max 1000) |
| `cursor` | Pagination cursor |

Response:

```json
{
  "data": {
    "items": [
      {
        "id": "audit_...",
        "timestamp": "2026-04-22T14:30:00Z",
        "action": "budget.create",
        "actor_id": "user_alice",
        "actor_email": "alice@acme.example",
        "actor_type": "user",
        "tenant_id": "tenant_acme",
        "partner_id": "partner_internal",
        "resource_type": "budget",
        "resource_id": "budget_xyz",
        "ip_address": "198.51.100.42",
        "user_agent": "curl/8.4.0",
        "status": "SUCCESS",
        "details": {"limit": "500.00", "period": "monthly"}
      }
    ]
  },
  "pagination": {"has_more": true, "next_cursor": "..."}
}
```

Per default, tenant admins see only their tenant's audit events. Partner admins see all tenants under their partner. Super admins see the platform-wide log.

## GET /v1/audit-log/export

Export audit trail to CSV, JSON, or NDJSON.

Query params: same filters as `/audit-log`, plus `format`.

```bash
curl "https://scaigrid.scailabs.ai/v1/audit-log/export?start=2026-04-01&end=2026-04-30&format=ndjson" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -o april-audit.ndjson
```

For large exports (> 100K events), use narrower time windows. Streams the entire result.

## Common action patterns

```
{resource_type}.{verb}
```

Examples:

- `model.create`, `model.update`, `model.delete`
- `user.create`, `user.update`, `user.delete`, `user.role_update`
- `api_key.create`, `api_key.delete`
- `budget.create`, `budget.update`, `budget.delete`
- `webhook.create`, `webhook.update`, `webhook.delete`
- `tenant.create`, `tenant.suspend`, `tenant.unsuspend`
- Module events: `scaibot.bot.create`, `scaicore.core.deploy`, etc.

Unusual patterns:

- `auth.login` — successful user login
- `auth.logout` — explicit logout
- `mcp.tool.invoke` — MCP tool invocation
- `scailink.capability.invoke` — ScaiLink tool invocation

## Retention

Default retention is 365 days. Configurable per tenant (minimum 90 days for compliance).

Expired events are permanently deleted. Export before deletion if you need longer retention.

## Error codes

| Code | Meaning |
|------|---------|
| `AUTHZ_PERMISSION_DENIED` | Caller lacks `admin:access` or higher |
| `VALIDATION_ERROR` | Invalid query parameters |

## Related

- [Webhooks](./08-webhooks.md) — subscribe to audit-level events
- [Authentication Reference](./01-authentication.md) — login/logout events
- [Users and Access](./02-users-and-access.md) — user management actions
