> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ada.cx/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server.

# List Audit log events

GET https://example.ada.support/api/v2/analytics/audit-log/events/

Retrieve the authenticated account's own Audit log events, newest first, in cursor-paginated pages. Intended for pulling the Audit log into a SIEM.

Pagination is cursor-based: read `meta.next_page_url` and replay it verbatim to fetch the next page. `next_page_url` is `null` on the last or empty page. The time window and `cursor` must be held constant across pages; the recommended way to guarantee this is to replay the returned `next_page_url` unchanged.

No field filters are exposed: callers pull the full time window and filter on their own side (the SIEM).

Validation errors (missing or invalid `start_date` or `end_date`, a window wider than 30 days, a malformed cursor, or a window change mid-pagination) return `400`.

Rate limits (per account): 10 requests per second, 120 per minute, and 40,000 per day. A `429` means a limit was exceeded; back off and retry. For ongoing ingestion, poll on a steady cadence (for example, every few minutes) rather than in a tight loop.

Backfilling vs incremental pulls: a single request covers at most 30 days. To backfill more history, issue successive requests over adjacent windows of up to 30 days. For incremental pulls, set `start_date` to just after the newest `timestamp` you have already stored, then follow `next_page_url` until it is `null`.

Reference: https://docs.ada.cx/reference/audit-log/list-audit-log-events

## Authentication

- `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer <token>`, where token is your auth token.

## Request

### Query parameters

- `start_date` (string, required) — Start of the time window (inclusive), ISO 8601. The window (`end_date - start_date`) may not exceed 30 days.
- `end_date` (string, optional) — End of the time window (inclusive), ISO 8601. When omitted it defaults to the request time (UTC); the resolved value is reflected in `next_page_url`, so replay the returned `next_page_url` verbatim to keep the window fixed across pages.
- `limit` (integer, optional, default: 50) — Maximum events per page. Out-of-range or non-integer values are rejected with `400`; the applied limit is not echoed in the response.
- `cursor` (string, optional) — Opaque base64-encoded pagination cursor from a previous response's `meta.next_page_url`. Treat it as an opaque token, not an id. The time window and `cursor` must be held constant across pages: replay the returned `next_page_url` unchanged.

## Response

### 200

A cursor-paginated page of Audit log events

- `data` (list of AuditLogEvent, required) — The page of Audit log events (at most `limit` items)
- `meta` (AuditLogEventListMeta, required) — Pagination metadata

## Errors

### 400 Bad Request Error

Bad Request (validation, cursor, or window drift)

- `errors` (list of ErrorsErrorsItems, required) — A list of errors

### 401 Unauthorized Error

Unauthorized (missing or non-Bearer token)

- `errors` (list of ErrorsErrorsItems, required) — A list of errors

### 404 Not Found Error

Not Found (Audit log API not enabled for this account)

- `errors` (list of ErrorsErrorsItems, required) — A list of errors

### 429 Too Many Requests Error

Too Many Requests (rate limit)

- `errors` (list of ErrorsErrorsItems, required) — A list of errors

### 500 Internal Server Error

Internal Server Error

- `errors` (list of ErrorsErrorsItems, required) — A list of errors

## Types

### AuditLogEvent

A single Audit log event: one configuration change recorded for the account. Empty-string fields mean the value was unavailable for that event (for example, a system actor has no email).

- `id` (string, required) — Globally unique event id (uuid4)
- `timestamp` (string, required) — When the change occurred (ISO 8601, UTC, millisecond precision)
- `entity_type` (string, required) — The type of entity that was changed
- `entity_id` (string, required) — The id of the entity that was changed
- `activity` (string, required) — What happened to the entity. One of `created`, `updated`, `deleted`, `executed`, `invited`, `activated`, or `deactivated`.
- `actor_email` (string, optional) — Email of the user who made the change, or the owner of a dashboard-created Platform API key. Empty for system and service-token actors.
- `actor_name` (string, optional) — Display name of the actor; empty when unavailable
- `actor_user_id` (string, optional) — User id of the actor. For an API key, the id of the user who created the key. Empty for system and service-token actors.
- `entity_name` (string, optional) — A human-readable name for the changed entity
- `interface` (string, optional) — Where the change originated, such as `dashboard`, `api`, `mcp`, `cli`, `import`, `export`, or `system` (background jobs and Ada's internal processing).
- `context_ip` (string, optional) — Source IP address of the request that made the change
- `context_user_agent` (string, optional) — User agent string of the request that made the change
- `api_key_name` (string, optional) — Name of the API key used, when the change was made by a dashboard-created Platform API key; empty otherwise.

### AuditLogEventListMeta

Pagination metadata

- `next_page_url` (string, optional, nullable) — URL for the next page of results, or `null` on the last or empty page. Replay it unchanged to keep the time window and the cursor constant across pages.

### ErrorsErrorsItems

- `type` (string, required) — The error type
- `message` (string, required) — The error message
- `details` (string, optional, nullable) — Extra information about the error

## Examples

### A full page with a populated next_page_url

**Response**

```json
{
  "data": [
    {
      "id": "7f1c2d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f",
      "timestamp": "2026-06-09T12:34:56.789+00:00",
      "entity_type": "playbook",
      "entity_id": "65a17e3f43bec88e2792d0eb",
      "activity": "updated",
      "actor_email": "admin@example.com",
      "actor_name": "Dana Admin",
      "actor_user_id": "65a17e3f43bec88e2792d0ec",
      "entity_name": "Refund flow",
      "interface": "dashboard",
      "context_ip": "203.0.113.42",
      "context_user_agent": "Mozilla/5.0",
      "api_key_name": ""
    }
  ],
  "meta": {
    "next_page_url": "https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=2026-06-01T00%3A00%3A00.000%2B00%3A00&end_date=2026-06-09T00%3A00%3A00.000%2B00%3A00&cursor=MjAyNi0wNi0wOVQxMjozNDo1Ni43ODkrMDA6MDA6OmFiYzo6ZGVhZGJlZWZjYWZl"
  }
}
```

**SDK Code**

```python A full page with a populated next_page_url
import requests

url = "https://example.ada.support/api/v2/analytics/audit-log/events/"

querystring = {"start_date":"start_date"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript A full page with a populated next_page_url
const url = 'https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go A full page with a populated next_page_url
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby A full page with a populated next_page_url
require 'uri'
require 'net/http'

url = URI("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java A full page with a populated next_page_url
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php A full page with a populated next_page_url
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp A full page with a populated next_page_url
using RestSharp;

var client = new RestClient("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift A full page with a populated next_page_url
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Last (or empty) page — next_page_url is null

**Response**

```json
{
  "data": [
    {
      "id": "8a2d3e4f-5c6b-7d8e-9f0a-1b2c3d4e5f60",
      "timestamp": "2026-06-08T09:00:00.000+00:00",
      "entity_type": "knowledge_source",
      "entity_id": "65a17e3f43bec88e2792d0ea",
      "activity": "created",
      "actor_email": "admin@example.com",
      "actor_name": "Dana Admin",
      "actor_user_id": "65a17e3f43bec88e2792d0ec",
      "entity_name": "Help center",
      "interface": "api",
      "context_ip": "203.0.113.42",
      "context_user_agent": "ada-python/1.2.0",
      "api_key_name": "CI Deploy Key"
    }
  ],
  "meta": {
    "next_page_url": {}
  }
}
```

**SDK Code**

```python Last (or empty) page — next_page_url is null
import requests

url = "https://example.ada.support/api/v2/analytics/audit-log/events/"

querystring = {"start_date":"start_date"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript Last (or empty) page — next_page_url is null
const url = 'https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Last (or empty) page — next_page_url is null
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Last (or empty) page — next_page_url is null
require 'uri'
require 'net/http'

url = URI("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java Last (or empty) page — next_page_url is null
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php Last (or empty) page — next_page_url is null
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp Last (or empty) page — next_page_url is null
using RestSharp;

var client = new RestClient("https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift Last (or empty) page — next_page_url is null
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://example.ada.support/api/v2/analytics/audit-log/events/?start_date=start_date")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```