List Audit Log
Returns the audit log of your organization: who did what and when, filterable by period, area and outcome.
GET /api/organization/audit
Returns the logged actions in your organization, newest first. Without since the list covers the last 30 days. Entries are kept for 12 months; older ones within that period through since or the export.
Access
Organization admins only, with a session or an organization-wide API token whose issuer is an admin. Other roles get 403 forbidden. Agent tokens (connected apps) are refused for this path. The organization is derived from the session or token; you cannot read another organization's log.
Query parameters
| Parameter | Default | Description |
|---|---|---|
since | 30 days before now | Unix time in milliseconds, inclusive lower bound. Pass an earlier value to read further back. |
until | none | Unix time in milliseconds, inclusive upper bound: an entry at exactly until is included. |
limit | 100 | 1 to 500. |
offset | 0 | 0 to 50000. |
sortBy | ts | ts, actor, status, summary or durationMs. |
sortOrder | desc | asc or desc. |
q | none | Case-insensitive text filter over area, summary and the actor's email or user id. |
area | none | Exact area, e.g. websites. |
success | none | true or false. Entries without an outcome are left out when this is set. |
envelope | none | items answers { items, total, page, perPage }. |
total counts the entries after all filters.
Example (cURL)
BASE_URL="https://uptimeify.io"
TOKEN="<your-api-token>"
curl -X GET "$BASE_URL/api/organization/audit?since=1759276800000&limit=50&envelope=items" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"Response
{
"items": [
{
"id": "4f1c2a9e-8b7d-4c3e-9f20-6a5b4c3d2e1f",
"ts": 1761126000000,
"organizationId": 1,
"area": "websites",
"summary": "Websites updated",
"actor": { "email": "admin@youragency.com", "userId": "u_123" },
"success": true,
"durationMs": 42,
"type": "websites.update",
"method": "PATCH",
"route": "/api/websites/[id]",
"statusCode": 200,
"resourceType": "websites",
"resourceId": "17",
"changes": [{ "field": "name", "from": "Shop", "to": "Shop (live)" }]
}
],
"total": 1,
"page": 1,
"perPage": 50
}| Field | Description |
|---|---|
ts | Unix time in milliseconds. |
summary | Short English description. |
route | Route template, never the raw path. |
actor | Who acted, or null. |
ipAddress, userAgent | Only recorded for requests made by a connected app (MCP agent). |
agent | Set when a connected app acted on behalf of the actor. |
auth | { method, reason }, only on sign-in events (type starts with auth.). method: password, password_mfa or sso for a sign-in; one, others or all for auth.sessions.revoked; otherwise null. reason: error code of a failed sign-in (e.g. INVALID_EMAIL_OR_PASSWORD), otherwise null. |
changes | What became what, where the action records it. Secret values are not logged (redacted: true). |
List form: with envelope=items the list comes as { items, total, page, perPage } (perPage is limit, page is floor(offset / limit) + 1). Without the parameter the endpoint still answers in the previous form { "events": [...], "pagination": { "limit", "offset", "total" } }; it is deprecated, from 2027-01-18 { items, ... } is the default.
Sign-in events
Besides requests, the log records these type values: auth.login.succeeded, auth.login.failed (known accounts only; actor is null), auth.logout, auth.password_reset.requested, auth.password_reset.completed, auth.password.changed, auth.sessions.revoked and app_link.redeemed (sign-in to the app with a QR code). The type audit.export records each audit log export with its period and row count. Sign-in events never carry ipAddress or userAgent; only account, time, method and reason code are stored.
Common errors
400 invalidRequestBodywhen a query parameter is out of range or malformed400 userMustBelongToOrgwhen no organization can be derived from the session or token401 unauthorizedwhen you are not authenticated403 forbiddenwhen you are not an organization admin