Documentation for the Query Audit Logs API (#2232)

* Documentation for the Query Audit Logs API

* Add missing empty request body

* Review feedback
This commit is contained in:
Abdon Pijpelink
2026-05-04 13:33:57 +02:00
committed by GitHub
parent 506e326f43
commit 0fc11c07de
7 changed files with 83 additions and 0 deletions
@@ -0,0 +1 @@
Query the audit log with time range and exact-match filters.
@@ -0,0 +1,12 @@
curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \
-H 'api-key: QDRANT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"limit": 50,
"time_from": "2026-03-26T00:00:00Z",
"time_to": "2026-03-27T00:00:00Z",
"filters": {
"result": "denied",
"collection": "my_collection"
}
}'
@@ -0,0 +1,14 @@
```bash
curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \
-H 'api-key: QDRANT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"limit": 50,
"time_from": "2026-03-26T00:00:00Z",
"time_to": "2026-03-27T00:00:00Z",
"filters": {
"result": "denied",
"collection": "my_collection"
}
}'
```
@@ -0,0 +1 @@
Query the audit log via the REST API.
@@ -0,0 +1,4 @@
curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \
-H 'api-key: QDRANT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{}'
@@ -0,0 +1,6 @@
```bash
curl -X POST 'https://YOUR-CLUSTER-URL:6333/audit/logs' \
-H 'api-key: QDRANT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{}'
```
@@ -481,6 +481,11 @@ audit:
dir: ./storage/audit
rotation: daily
max_log_files: 7
# Only enable when Qdrant is behind a trusted reverse proxy or load balancer.
# When true, the client IP is taken from the X-Forwarded-For header instead of
# the TCP connection. Enabling this on a publicly reachable instance allows
# clients to spoof their IP address in audit logs.
trust_forwarded_headers: false
```
By default, audit logs are rotated daily, and the seven most recent log files are kept. To configure hourly rotation, set `rotation` to `hourly`. When the number of log files exceeds `max_log_files`, the oldest log file is deleted.
@@ -497,6 +502,46 @@ Qdrant reads the tracing ID from the first matching header in the following orde
{{< code-snippet path="/documentation/headless/snippets/audit-tracing-id/simple/" >}}
### Query Audit Logs
*Available as of v1.18.0*
The audit log can be queried via the `/audit/logs` API (requires [manage-level access](#table-of-access)). For example:
{{< code-snippet path="/documentation/headless/snippets/audit-logging/query/" >}}
By default, the API returns the 100 most recent entries, but you can change this number with the `limit` parameter (max 10,000).
In a distributed cluster, the API aggregates results from all nodes before returning them. An optional `timeout` (seconds) query parameter controls how long to wait for remote peers in a cluster.
Entries are returned in reverse-chronological order (newest first). Each entry has the following fields:
| Field | Type | Description |
|---|---|---|
| `timestamp` | ISO-8601 | When the access check occurred. |
| `method` | string | API method name, for example `upsert_points`, `search_points`. |
| `auth_type` | `"Jwt"` \| `"ApiKey"` \| `"None"` | How the request was authenticated. |
| `result` | `"ok"` \| `"denied"` | Whether access was granted. |
| `subject` | string | JWT `sub` claim. Only present for JWT-authenticated requests. |
| `remote` | string | Client IP address, if available. |
| `collection` | string | Collection name, for collection-scoped operations. |
| `tracing_id` | string | Value of the `x-request-id`, `x-tracing-id`, or `traceparent` request header. |
| `error` | string | Reason access was denied. Only present when `result` is `"denied"`. |
#### Narrowing Results with Time Ranges and Filters
To narrow results to a specific time range, use the `time_from` (inclusive) and `time_to` (exclusive) parameters.
The `filters` parameter enables exact-match filtering of entries based on specific field values. The parameter accepts a dictionary of field-value pairs. When specifying more than one pair, only entries that match all specified criteria are returned (logical AND).
Unknown filter fields silently return no matches. Filter field names are case-sensitive: filtering on a field name with incorrect casing silently returns no matches.
You can filter on any field in the entry fields table except `timestamp`. Use `time_from` and `time_to` for time-range filtering instead.
For example, to retrieve the 50 most recent denied requests to the `my_collection` collection on March 26, 2026:
{{< code-snippet path="/documentation/headless/snippets/audit-logging/query-with-filters/" >}}
## Network Bind
By default, a custom Qdrant deployment binds to all network interfaces. Your