# Litmus Edge Manager 3.0.x - Edge Lifecycle: Audit Logs

## Get Audit Records

**GET** `{{LEM_URL}}/api/v1/logs/v2?companyName={{company_name}}&requestedPage=0&limit=1`

> **New in 2.35.**

# Get Audit Records

Returns the company's audit records (schema v2), newest first by default. What a caller sees follows the owner / project access model: company owners see everything, other users only the projects they belong to.
## Endpoint

```http
GET {{LEM_URL}}/api/v1/logs/v2?companyName={{company_name}}&requestedPage=0&limit=10
```
## Authentication

API key in a request header (case sensitive). The value is the LEM admin API token.

| URL prefix | Auth header |
|---|---|
| `{{LEM_URL}}/api/v1/...` (main fleet API) | `X-AuthToken: <token>` |
| `{{LEM_adminURL}}/admin/v1/...` (admin console, port 8446) | `X-AuthToken: <token>` |
| `{{LEM_URL}}/mpcs/...` (Marketplace Catalog) | `Authorization: <token>` (3.0.x also accepts `X-AuthToken`) |
## Parameters

| Parameter | In | Notes |
|---|---|---|
| `companyName` | query | **Required.** The company. Omitting it answers `400` `Missing required parameter 'companyName'`. |
| `projectId` | query | Restrict to one project. |
| `from` / `to` | query | Time window, Unix epoch milliseconds. |
| `category` | query | Multi-value. `USER_MANAGEMENT`, `DEVICE_LIFECYCLE`, `APPLICATIONS`, `SOFTWARE_UPDATES`, `DATA_PIPELINE`, `ASSET_MANAGEMENT`, `AI_ML`, `CERTIFICATES`, `SYSTEM`, `ALERTS`, `SECURITY`, `LICENSES`. See `Get Audit Categories`. |
| `context` | query | Multi-value. Narrower than `category`, e.g. `device`, `template-applied`, `edge-oauth-client`. |
| `contextId` | query | The id of the object a record is about, e.g. a device id. |
| `level` | query | `INFO`, `WARN`, `ERROR`. |
| `action` | query | `CREATE`, `MODIFY`, `DELETE`, `EXECUTE`. |
| `origin` | query | `UI`, `API_TOKEN`, `AUTOMATED`, `TUI`. |
| `module` | query | `API`, `ADMIN`, `JOBS`, `ALERTS`, `ACTIVATION`, `CONFIG`, `CLICKHOUSE_SINK`, `KEYCLOAK`. |
| `username` | query | Multi-value. Case-insensitive prefix match on each, OR-combined. |
| `sourceIp` | query | Source IP prefix, case-sensitive. |
| `search` | query | Free-text search. |
| `filter` | query | Legacy filter string. |
| `order` | query | `EVENT_TIME_ASC`, `EVENT_TIME_DESC`, `LEVEL_ASC`, `LEVEL_DESC`, `CONTEXT_ASC`, `CONTEXT_DESC`, ... |
| `requestedPage` | query | Page, `0` first. |
| `limit` | query | Page size, default 10, max 1000. |

## Response

`200 OK`. A page: `pageNum`, `pagesCount`, `size`, `totalSize`, `elements`. Each record:

| Field | Meaning |
|---|---|
| `eventTime` | Unix epoch milliseconds. |
| `level`, `action`, `origin`, `module` | As in the filters above. `module` can be `null`. |
| `username` | The actor. API-token actions show as `token=<token name>`; automated ones as `system`. |
| `category`, `categoryLabel`, `context`, `contextId` | What the record is about. |
| `message` | Human-readable summary. |
| `details` | Context-specific object, or `null`. |
| `companyName`, `realCompanyName`, `projectId`, `projectName` | Scope. |
| `sourceIp`, `errorCode`, `subtaskId` | When applicable. |
| `accessLevel` | `ADMIN` or `USER`. |

```json
{
  "pageNum": 0,
  "pagesCount": 35,
  "size": 1,
  "totalSize": 35,
  "elements": [
    {
      "companyName": "hg-test",
      "projectId": "c8con68kzh7hwgmc32raesiaw",
      "eventTime": 1791835780750,
      "level": "INFO",
      "username": "system",
      "context": "device-connectivity",
      "contextId": "105yoa1s3t5yhq1dgjj3runpy",
      "message": "Connectivity Changed: Device '105yoa1s3t5yhq1dgjj3runpy' went offline.",
      "accessLevel": "ADMIN",
      "details": null,
      "action": "EXECUTE",
      "origin": "AUTOMATED",
      "module": "JOBS",
      "category": "DEVICE_LIFECYCLE",
      "categoryLabel": "Device Lifecycle",
      "projectName": "project01"
    }
  ]
}
```

## Errors

| HTTP status         | When it happens                                                                |
|---------------------|--------------------------------------------------------------------------------|
| `400 Bad Request`   | Missing or malformed query/body parameter.                                     |
| `401 Unauthorized`  | Missing or invalid credentials.                                                |
| `403 Forbidden`     | Token lacks permission for this operation.                                     |
| `404 Not Found`     | Target entity does not exist.                                                  |
| `5xx`               | Service is unreachable, restarting, or internally errored. Inspect device logs under `System > Support`. |

> **TLS note**: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.


### Response

**Status**: 200 OK

```json
{
  "pageNum": 0,
  "pagesCount": 107,
  "size": 1,
  "totalSize": 107,
  "elements": [
    {
      "companyName": "test",
      "projectId": null,
      "eventTime": 1791917896390,
      "level": "INFO",
      "username": "token=ps",
      "context": "audit-report",
      "contextId": null,
      "contextDescription": null,
      "message": "Report Exported: Audit report (106 rows) was exported by 'token=ps'.",
      "accessLevel": "ADMIN",
      "details": {
        "format": "csv",
        "exportedRows": 106,
        "totalMatched": 106,
        "filters": {
          "companyName": "test"
        }
      },
      "action": "EXECUTE",
      "origin": "API_TOKEN",
      "module": "API",
      "sourceIp": "10.17.4.128",
      "errorCode": null,
      "subtaskId": null,
      "category": "SYSTEM",
      "realCompanyName": "test",
      "projectName": null,
      "categoryLabel": "System"
    }
  ]
}
```

---

## Get Audit Categories

**GET** `{{LEM_URL}}/api/v1/logs/v2/categories`

> **New in 2.35.**

# Get Audit Categories

Lists the audit categories and the contexts each one groups. Use the codes as the `category` and `context` filters of `Get Audit Records` and `Export Audit Records`.
## Endpoint

```http
GET {{LEM_URL}}/api/v1/logs/v2/categories
```
## Authentication

API key in a request header (case sensitive). The value is the LEM admin API token.

| URL prefix | Auth header |
|---|---|
| `{{LEM_URL}}/api/v1/...` (main fleet API) | `X-AuthToken: <token>` |
| `{{LEM_adminURL}}/admin/v1/...` (admin console, port 8446) | `X-AuthToken: <token>` |
| `{{LEM_URL}}/mpcs/...` (Marketplace Catalog) | `Authorization: <token>` (3.0.x also accepts `X-AuthToken`) |
## Response

`200 OK`. A list of `{code, name, contexts: [{code, description}]}`.

```json
[
  {
    "code": "USER_MANAGEMENT",
    "name": "User Management",
    "contexts": [
      { "code": "company", "description": "Company" },
      { "code": "edge-oauth-client", "description": "Edge device OAuth client" },
      { "code": "api-token", "description": "API token" }
    ]
  }
]
```

## Errors

| HTTP status         | When it happens                                                                |
|---------------------|--------------------------------------------------------------------------------|
| `400 Bad Request`   | Missing or malformed query/body parameter.                                     |
| `401 Unauthorized`  | Missing or invalid credentials.                                                |
| `403 Forbidden`     | Token lacks permission for this operation.                                     |
| `404 Not Found`     | Target entity does not exist.                                                  |
| `5xx`               | Service is unreachable, restarting, or internally errored. Inspect device logs under `System > Support`. |

> **TLS note**: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.


### Response

**Status**: 200 OK

```json
[
  {
    "code": "USER_MANAGEMENT",
    "name": "User Management",
    "contexts": [
      {
        "code": "company",
        "description": "Company"
      },
      {
        "code": "edge-oauth-client",
        "description": "Edge device OAuth client"
      },
      {
        "code": "mqtt-dm-account",
        "description": "MQTT DM account"
      },
      {
        "code": "mqtt-account",
        "description": "MQTT account"
      },
      {
        "code": "project",
        "description": "Project"
      },
      {
        "code": "grant",
        "description": "Project grant permissions"
      },
      {
        "code": "revoke",
        "description": "Project revoke permissions"
      },
      {
        "code": "team",
        "description": "Team"
      },
      {
        "code": "team-member",
        "description": "Team member"
      },
      {
        "code": "audit",
        "description": "Audit"
      },
      {
        "code": "api-token",
        "description": "API token"
      },
      {
        "code": "user-password",
        "description": "User password"
      },
      {
        "code": "role",
        "description": "Role"
      },
      {
        "code": "user",
        "description": "User"
      },
      {
        "code": "oidc-config",
        "description": "OIDC configuration"
      },
      {
        "code": "identity-provider",
        "description": "Identity provider"
      }
    ]
  },
  {
    "code": "DEVICE_LIFECYCLE",
    "name": "Device Lifecycle",
    "contexts": [
      {
        "code": "activation",
        "description": "Edge device activation"
      },
      {
        "code": "batch-dm",
        "description": "Batch edge device management"
      },
      {
        "code": "deactivation",
        "description": "Edge device deactivation"
      },
      {
        "code": "device",
        "description": "Edge device"
      },
      {
        "code": "device-connectivity",
        "description": "Edge device connectivity"
      },
      {
        "code": "device-ha",
        "description": "Edge device high availability"
      }
    ]
  },
  {
    "code": "APPLICATIONS",
    "name": "Applications",
    "contexts": [
      {
        "code": "device-service",
        "description": "Edge device system service"
      },
      {
        "code": "grafana",
        "description": "Grafana"
      },
      {
        "code": "marketplace-application",
        "description": "Marketplace application"
      },
      {
        "code": "mpcs",
        "description": "MPCS"
      },
      {
        "code": "template-applied",
        "description": "Template applied"
      },
      {
        "code": "template-updated",
        "description": "Template updated"
      },
      {
        "code": "template-parameterized",
        "description": "Template parameterized"
      },
      {
        "code": "template-variable-mapping-updated",
        "description": "Template variable mapping updated"
      }
    ]
  },
  {
    "code": "SOFTWARE_UPDATES",
    "name": "Software Updates",
    "contexts": [
      {
        "code": "le-upgrade",
        "description": "LE firmware upgrade"
      },
      {
        "code": "lem-upgrade",
        "description": "LEM self-upgrade"
      }
    ]
  },
  {
    "code": "DATA_PIPELINE",
    "name": "Data Pipeline",
    "contexts": [
      {
        "code": "device-analytics",
        "description": "Edge device analytics"
      },
      {
        "code": "device-log-forwarding",
        "description": "Edge device log forwarding"
      },
      {
        "code": "git-sync",
        "description": "Git synchronization"
      },
      {
        "code": "integration",
        "description": "Data pipeline integration configuration"
      },
      {
        "code": "device-events-forwarding",
        "description": "Edge device events forwarding"
      },
      {
        "code": "instance-data-export",
        "description": "Instance configuration export"
      },
      {
        "code": "instance-data-import",
        "description": "Instance configuration import"
      },
      {
        "code": "database-dump-download",
        "description": "Database dump download (sensitive-filtered)"
      },
      {
        "code": "registry-image",
        "description": "Docker registry image"
      },
      {
        "code": "registry-config",
        "description": "Docker registry configuration"
      },
      {
        "code": "data-lifecycle-policy",
        "description": "Data lifecycle (retention/purge) policy"
      },
      {
        "code": "audit-forwarding",
        "description": "Audit log forwarding to remote syslog"
      }
    ]
  },
  {
    "code": "ASSET_MANAGEMENT",
    "name": "Asset Management",
    "contexts": [
      {
        "code": "asset-hierarchy",
        "description": "Industrial Asset Hierarchy"
      },
      {
        "code": "digital-twins",
        "description": "Digital Twins"
      }
    ]
  }
]
```

---

## Export Audit Records

**GET** `{{LEM_URL}}/api/v1/logs/v2/export?companyName={{company_name}}`

> **New in 2.35.**

# Export Audit Records

Exports the company's audit records matching the filters as a CSV or PDF file. The export itself is audited: it adds a `Report Exported` record (context `audit-report`) naming the format and row count.
## Endpoint

```http
GET {{LEM_URL}}/api/v1/logs/v2/export?companyName={{company_name}}&format=csv
```
## Authentication

API key in a request header (case sensitive). The value is the LEM admin API token.

| URL prefix | Auth header |
|---|---|
| `{{LEM_URL}}/api/v1/...` (main fleet API) | `X-AuthToken: <token>` |
| `{{LEM_adminURL}}/admin/v1/...` (admin console, port 8446) | `X-AuthToken: <token>` |
| `{{LEM_URL}}/mpcs/...` (Marketplace Catalog) | `Authorization: <token>` (3.0.x also accepts `X-AuthToken`) |
## Parameters

| Parameter | In | Notes |
|---|---|---|
| `companyName` | query | **Required.** The company. Omitting it answers `400` `Missing required parameter 'companyName'`. |
| `projectId` | query | Restrict to one project. |
| `from` / `to` | query | Time window, Unix epoch milliseconds. |
| `category` | query | Multi-value. `USER_MANAGEMENT`, `DEVICE_LIFECYCLE`, `APPLICATIONS`, `SOFTWARE_UPDATES`, `DATA_PIPELINE`, `ASSET_MANAGEMENT`, `AI_ML`, `CERTIFICATES`, `SYSTEM`, `ALERTS`, `SECURITY`, `LICENSES`. See `Get Audit Categories`. |
| `context` | query | Multi-value. Narrower than `category`, e.g. `device`, `template-applied`, `edge-oauth-client`. |
| `contextId` | query | The id of the object a record is about, e.g. a device id. |
| `level` | query | `INFO`, `WARN`, `ERROR`. |
| `action` | query | `CREATE`, `MODIFY`, `DELETE`, `EXECUTE`. |
| `origin` | query | `UI`, `API_TOKEN`, `AUTOMATED`, `TUI`. |
| `module` | query | `API`, `ADMIN`, `JOBS`, `ALERTS`, `ACTIVATION`, `CONFIG`, `CLICKHOUSE_SINK`, `KEYCLOAK`. |
| `username` | query | Multi-value. Case-insensitive prefix match on each, OR-combined. |
| `sourceIp` | query | Source IP prefix, case-sensitive. |
| `search` | query | Free-text search. |
| `filter` | query | Legacy filter string. |
| `order` | query | `EVENT_TIME_ASC`, `EVENT_TIME_DESC`, `LEVEL_ASC`, `LEVEL_DESC`, `CONTEXT_ASC`, `CONTEXT_DESC`, ... |
| `format` | query | `csv` or `pdf`. |

## Response

`200 OK`. The file, as a binary download.
## Errors

| HTTP status         | When it happens                                                                |
|---------------------|--------------------------------------------------------------------------------|
| `400 Bad Request`   | Missing or malformed query/body parameter.                                     |
| `401 Unauthorized`  | Missing or invalid credentials.                                                |
| `403 Forbidden`     | Token lacks permission for this operation.                                     |
| `404 Not Found`     | Target entity does not exist.                                                  |
| `5xx`               | Service is unreachable, restarting, or internally errored. Inspect device logs under `System > Support`. |

> **TLS note**: edge devices use a self-signed certificate by default. Either install the device CA in your client trust store or disable certificate verification when calling this endpoint directly.


### Response

**Status**: 200 OK

```text
"Date & Time","Severity","Category","Sub-Category","User","Action","Origin","Source IP","Description","Outcome","Error Code","Module","Reason","Changes"
"2026-10-13T18:58:16.390Z","INFO","System","test","token=ps","EXECUTE","API_TOKEN","10.17.4.128","Report Exported: Audit report (106 rows) was exported by 'token=ps'.","SUCCESS","","API","",""
"2026-10-13T18:43:24.910Z","INFO","System","test","token=ps","EXECUTE","API_TOKEN","10.17.4.128","Report Exported: Audit report (105 rows) was exported by
```

---

