---
title: "Export Audit Log"
description: "Downloads your organization's audit log for one period as a CSV file, sign-ins included."
---

`GET /api/organization/audit/export`

Returns the audit log of your organization for one period as a CSV file. The log records
administrative actions (every write through the dashboard or the API, with old and new value
where the action records it) and sign-in events: successful and failed sign-ins of existing
accounts, sign-outs, password resets, password changes and ended sessions. Entries are kept for
12 months and cannot be changed or deleted through the application.

Only organization administrators can call it, with a session or an organization-wide API token
whose issuer is an admin. Connected apps (MCP agents) cannot. Every export is itself recorded in the audit log.

## Query parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `from` | ISO 8601 UTC | Start, inclusive. Default: 30 days before `to`. |
| `to` | ISO 8601 UTC | End, exclusive. Default: now. |

One export spans at most 366 days and at most 100,000 entries. Split a longer period into
several exports. The export only contains entries that are still stored.

## Example (cURL)

```bash
BASE_URL="https://uptimeify.io"
TOKEN="<your-api-token>"

curl -o audit-log.csv \
  "$BASE_URL/api/organization/audit/export?from=2026-01-01T00:00:00.000Z&to=2026-04-01T00:00:00.000Z" \
  -H "Authorization: Bearer $TOKEN"
```

## Response

`200` with `Content-Type: text/csv; charset=utf-8`, a `Content-Disposition` attachment and
`Cache-Control: no-store`. Rows are sorted oldest first; entries with the same timestamp keep a
stable order. The file is UTF-8 without BOM: in Excel open it via Data > From Text/CSV so
umlauts show correctly.

```csv
"time","actor","agent","action","auth","summary","target","changes","ip","user_agent","request_id"
"2026-03-02T08:14:03.512Z","admin@example.com","no","auth.login.succeeded","password","Signed in","user:Xk2f9","","","",""
"2026-03-02T08:15:40.101Z","admin@example.com","no","websites.update","","Website updated","website:46","[{""field"":""checkInterval"",""from"":5,""to"":1}]","","","9b1e2c4a"
```

| Column | Content |
| --- | --- |
| `time` | When it happened, ISO 8601 UTC |
| `actor` | Email address of the acting user, or their ID; empty for a failed sign-in and a requested password reset |
| `agent` | `yes` when a connected app (MCP agent) acted on behalf of the user |
| `action` | Event type, for example `websites.update` or `auth.login.failed` |
| `auth` | Sign-in events only: method and, for a failed sign-in, the reason code as `method:reason` (for example `password:INVALID_EMAIL_OR_PASSWORD`), otherwise just the method (`password`, `password_mfa`, `sso`); empty for all other events |
| `summary` | Short description |
| `target` | Affected object as `type:id`, for sign-in events the account |
| `changes` | Changed fields as JSON (`field`, `from`, `to`); secrets only as changed |
| `ip`, `user_agent` | Only when a connected app (MCP agent) acted; empty otherwise, sign-in events included |
| `request_id` | Correlation ID of the request |

Every cell is quoted. A cell that starts with `=`, `+`, `-` or `@`, also after leading
whitespace, gets a leading `'`, so spreadsheet applications show it as text instead of running it
as a formula.

## Common errors

- `400 Invalid query` (`data.code: invalidRequestBody`) when `from` or `to` is not an ISO 8601 timestamp in UTC (ending in `Z`)
- `400` (`data.code: invalidDateRange`) when `from` is not before `to`
- `400` (`data.code: auditExportRangeTooLarge`) when the period is longer than 366 days or holds more than 100,000 entries
- `400 User must belong to an organization` when no organization can be derived from the session or token
- `401 Unauthorized` when you are not authenticated
- `403 Forbidden` when your role is not admin
