# System Audit Logs

| Operation                                   | Syntax                               |
| ------------------------------------------- | ------------------------------------ |
| [List audit events](#list-audit-events)     | GET /api/preview/system/audit        |
| [Export audit events](#export-audit-events) | GET /api/preview/system/audit/export |

Audit Logs record every API call, providing a record of actions conducted within Veza. Depending on your use case, you can export a continuous list of events, or get events matching a filter in chronological order. Developers, administrators, and security teams can use these requests to:

* Integrate Veza with an SIEM platform or other auditing tools
* Detect potential inappropriate access or usage
* Get insight into how users are interacting with the Veza platform

See [Audit events](#audit-events) for more details about the audit event object.

### Pagination

Responses will include a `next_page_token`. Use this `page_token` in the request query to get the next batch of results.

Setting a page size is required for requests. The maximum page size is currently 10,000 records.

### List audit events

{% openapi src="<https://1967633068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZDkWMxox3pekd0NsZJ%2Fuploads%2Fgit-blob-d0cc152d188a7ade16cd0e6e7f7f205786a7e186%2Fopenapi.yaml?alt=media>" path="/api/preview/system/audit" method="get" %}
[openapi.yaml](https://1967633068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZDkWMxox3pekd0NsZJ%2Fuploads%2Fgit-blob-d0cc152d188a7ade16cd0e6e7f7f205786a7e186%2Fopenapi.yaml?alt=media)
{% endopenapi %}

This endpoint supports filtering by `ended_at` timestamp, `method`, `user_id`, and `url`. Results are ordered by time completed.

A timestamp filter is always required. The API allows querying events for up to 90 days in the past.

Example:

```shell
curl -X GET "$VEZA_URL/api/preview/system/audit?page_token=&page_size=1&filter=ended_at+GE+%222023-08-04T22:11:25.915674671Z%22" \
-H "authorization: Bearer $VEZA_TOKEN"
```

### Export audit events

Returns a paginated list of events, intended for exporting entries into an external log management system.

{% openapi src="<https://1967633068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZDkWMxox3pekd0NsZJ%2Fuploads%2Fgit-blob-d0cc152d188a7ade16cd0e6e7f7f205786a7e186%2Fopenapi.yaml?alt=media>" path="/api/preview/system/audit/export" method="get" %}
[openapi.yaml](https://1967633068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MZDkWMxox3pekd0NsZJ%2Fuploads%2Fgit-blob-d0cc152d188a7ade16cd0e6e7f7f205786a7e186%2Fopenapi.yaml?alt=media)
{% endopenapi %}

To ingest events as they become available without skipping any entries, first make call with a `persisted_at GE "TIMESTAMP"` filter. Then, continuously call the next page. The export endpoint can return the error code `ResourceExhaused`. If encountered, clients should wait for a minute before retrying the request.

Example:

```shell
curl -X GET "$VEZA_URL/api/preview/system/audit/export?filter=persisted_at+GE+%222023-08-07T22:11:25.915674671Z%22&page_size=5&next_page_token=" \
-H "authorization: Bearer $VEZA_TOKEN"
```

{% hint style="info" %}
**Question**: If a customer includes the `persisted_at` timestamp hard-coded in a script, and Veza only exports events for 1 month, what happens after a month?

**Answer**: The `persisted_at` parameter is ignored if you send a `page_token` in the API call. It won’t matter if the date is more than 90 or 30 days in the past.
{% endhint %}

### Audit events

An event describes an API-level action, including the IP address and user agent of the caller. Requests can originate from user sessions, or from applications using API keys. The following is a sample event for a successful API key generation:

```json
{
    "identity": {
        "user_id": "aeaa34cf-e97f-4315-b185-249018cf191c",
        "session_id": "b0ba024d-0158-4c7e-a47f-bbe8f7b98806",
        "api_key_id": "",
        "email": "cookie@cookie.ai"
    },
    "status": {
        "grpc_code": "OK",
        "http_status": 200,
        "error_reason": "OK"
    },
    "client": {
        "ip": "10.42.1.1",
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
    },
    "endpoint": "/api_protos.v1.APIKeyService/CreateAPIKey",
    "method": "POST",
    "url": "/api/preview/keys",
    "request_id": "1a98184880f9952551c53d836598b258",
    "request": {
        "name": "KeyName1"
    },
    "response": {
        "value": {
            "id": "fde4386f-3d85-4ef2-82d0-324dacb6e9ba",
            "name": "KeyName1",
            "team_id": "613df06e-9a40-4331-947c-5c327b54b228",
            "user_id": "aeaa34cf-e97f-4315-b185-249018cf191c"
        }
    },
    "started_at": "2023-07-26T08:23:17.134994459Z",
    "ended_at": "2023-07-26T08:23:17.151080751Z"
}
```

#### Identity

| Field        | Description                      |
| ------------ | -------------------------------- |
| `user_id`    | Unique user identifier.          |
| `session_id` | Unique session identifier.       |
| `api_key_id` | Unique identifier of an API key. |
| `email`      | User email address.              |

#### Status

| Field          | Description                          |
| -------------- | ------------------------------------ |
| `grpc_code`    | gRPC code indicating request status. |
| `http_status`  | HTTP status code of the response.    |
| `error_reason` | Details about a bad request.         |

#### Client

| Field        | Description               |
| ------------ | ------------------------- |
| `ip`         | Client IP address.        |
| `user_agent` | Client user agent string. |

#### Event

| Field        | Description                                |
| ------------ | ------------------------------------------ |
| `endpoint`   | The API endpoint that was accessed.        |
| `method`     | The HTTP method used for the request.      |
| `url`        | The URL of the request.                    |
| `request_id` | The unique identifier for the request.     |
| `request`    | The contents of the API request.           |
| `response`   | Excerpt of the API response.               |
| `started_at` | RFC 3339 timestamp when the event started. |
| `ended_at`   | RFC 3339 timestamp when the event ended.   |

* `request` and `response` both only contain some whitelisted fields. Due to size limitations, the entire message is not recorded.
