---
sidebar_position: 9
title: Account audit log
description: Every pod, key, login, balance and settings change made with your credentials — when, by which key or session, from which IP and client.
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Account audit log

> Recording is switched on per environment (`ACCOUNT_AUDIT_LOG_ENABLED`); with it off the routes answer, with an empty `items` until it has been on.

The account audit log is one entry per request that changed something on your account: a pod created, restarted or deleted, an API key created or revoked, a login, a top-up requested, a setting changed, a workspace member added. Each entry names the action, the credential that made the request (your browser session, or an API key and the user who created it), the client (`portal`, `cli`, `sdk`, `mcp`, `admin` or `api`), the client IP, the `User-Agent`, and the `X-Request-Id` the request answered with — the same id its log lines and its error body carry. Entries are kept for 90 days and are never edited.

The entry is written after the response is sent, by the API itself, for every write route (`POST`, `PUT`, `PATCH`, `DELETE`) that resolved an account, except a short exempt list: preferences and feedback (likes, bookmarks, feedback forms), webhooks, worker and validator calls, and the address-only steps before a login exists. Requests without an account — a wrong key, a webhook, a worker — write nothing. A request that was refused (`403`, `404`, `409`, `422`) is recorded too, with its status: you see that an agent tried.

This is a different list from `GET /users/me/events` (`lium audit`), which is the pod event log: what the platform did to a pod, including the validator's replies. The audit log is what your credentials asked for, with where from. In the CLI it is `lium audit --account` (`--action`, `--source`, `--cursor`, `--since`, `--key`, `--json`); in the SDK, `Lium.audit_log(...)`.

## Read it

```bash
curl -H "X-API-Key: $LIUM_API_KEY" "https://lium.io/api/account/audit?action=pod.&limit=50"
```

An API key needs the `read` scope. A browser session works too.

```json
{
  "items": [
    {
      "id": "ee2a0782-dbf1-4bf6-82d9-ca1227b3632e",
      "created_at": "2026-09-08T23:59:22.069873",
      "action": "pod.delete",
      "source": "cli",
      "actor": {
        "auth": "api_key",
        "user_id": "c7ad12ec-8fc5-407a-876d-c759e5b5260a",
        "api_key_id": "323d3f8e-0150-44cb-ae1f-ba11071b2539",
        "api_key_name": "ci-runner"
      },
      "workspace_id": null,
      "ip": "203.0.113.9",
      "user_agent": "lium-cli/0.0.37",
      "request_id": "86943ca082d14405bacf58bc895e3a67",
      "method": "DELETE",
      "route": "/pods/{id}",
      "status_code": 200,
      "resource_type": "pod",
      "resource_id": "dc4919ac-b6aa-4890-b480-4633cdbf8114",
      "summary": { "path": { "id": "dc4919ac-b6aa-4890-b480-4633cdbf8114" } }
    }
  ],
  "next_cursor": null
}
```

Entries are newest first. `created_at` is UTC without an offset. `summary` holds the request's path parameters (`path`) and, when the response named a row, its `id` / `name` / `status` (`result`) — never a request body, never a key or a token. `actor.auth` is `session` or `api_key`; `actor.user_id` is the person behind the request (for an API key, the user who created it).

### Filters

| Parameter | What it selects |
| --- | --- |
| `action` | A prefix. `pod.` is every pod action, `pod.delete` one. Resources: `pod`, `volume`, `backup`, `restore`, `key`, `ssh_key`, `docker_credential`, `template`, `account`, `settings`, `balance`, `payment_method`, `wallet`, `payout`, `referral`, `machine_request`, `workspace`, `member`, `admin`; plus `login` and `logout`. Examples: `pod.create`, `pod.delete`, `pod.restart`, `key.create`, `key.revoke`, `account.signup`, `account.password_reset`, `account.email_verified`, `balance.topup_requested`, `member.invite`, `member.remove`. |
| `source` | `portal`, `cli`, `sdk`, `mcp`, `admin` or `api`. |
| `since`, `until` | ISO timestamps (UTC). |
| `api_key_id` | Only requests made with that key. |
| `resource_id` | A pod, volume, key or workspace id. |
| `limit` | 1–500, default 100. |
| `cursor` | The previous page's `next_cursor`, for the next (older) page. |

`next_cursor` is `null` when the page came back short; a page that is exactly full carries a cursor, and the next request may answer an empty page. Pages never skip or repeat an entry, even when many were written in the same second.

### Export as CSV

```bash
curl -H "X-API-Key: $LIUM_API_KEY" "https://lium.io/api/account/audit/export?action=pod." -o account-audit.csv
```

The same filters (except `limit` and `cursor`), every page up to 10,000 rows, as a `text/csv` attachment with the columns `created_at, action, source, actor_auth, actor_user_id, api_key_id, api_key_name, workspace_id, ip, user_agent, request_id, method, route, status_code, resource_type, resource_id`.

## Who sees what

Outside a team workspace, the log is your account's: entries made with your session or any key on your account, plus entries you made as a member of a team.

In a team workspace (a session with `X-Lium-Workspace-Id`, or a key created in the workspace), the log is the team's: an owner or admin sees every member's entries, a member their own — for a key, the role of the user who created it decides. A team key never sees the billing owner's private entries.

`ip` is filled on your own entries only. A team owner sees what a member did, not from where; the billing owner sees what a member's key did on their account, without the member's address.

## From the portal

**Activity** in the sidebar lists the same entries with filters by activity group and client, a *Load older* button and *Export CSV*.

## Where the IP comes from

The address is the one CloudFront saw the request come from: the `CloudFront-Viewer-Address` header when the distribution forwards it, otherwise the right end of `X-Forwarded-For` past the platform's own hops. A client cannot forge it by sending its own `X-Forwarded-For` or `CloudFront-Viewer-Address`: the first lands to the left of the hop the platform trusts, the second is stripped by CloudFront before the request reaches the API.
