Retrieve audit logs
Pull the tenant’s audit trail over the API: discover the available filters, query a date range, and stream every entry into your SIEM with a simple paginated export job.
Before you begin
Section titled “Before you begin”- Audit logs are served by the RBAC service under
/rbac/api/v1/audit-logs. Use a token issued by a tenant admin with theadmincategory (see Automate personal access tokens). - Both list parameters
start_dateandend_dateare required and useYYYY-MM-DDdates. Both bounds are inclusive.
Each entry has five fields: id, log (a human-readable message describing the action), category (for example rbac), generated_by (the user who performed the action) and created_at.
Discover filter values
Section titled “Discover filter values”Fetch the categories and users that currently appear in the audit log, so you can build valid category and generated_by filters.
curl "https://acme.app.elastio.com/rbac/api/v1/audit-logs/filters" \ -H "Authorization: Bearer $ELASTIO_TOKEN"import os, requests
BASE = "https://acme.app.elastio.com"HEADERS = {"Authorization": f"Bearer {os.environ['ELASTIO_TOKEN']}"}
resp = requests.get(f"{BASE}/rbac/api/v1/audit-logs/filters", headers=HEADERS, timeout=30)resp.raise_for_status()filters = resp.json()print(filters["categories"], filters["generated_by"])$Base = "https://acme.app.elastio.com"$Headers = @{ Authorization = "Bearer $env:ELASTIO_TOKEN" }Invoke-RestMethod -Uri "$Base/rbac/api/v1/audit-logs/filters" -Headers $Headers{ "categories": ["rbac", …], "generated_by": ["jane.doe@example.com", "ops-bot@example.com"]}Query a date range with filters
Section titled “Query a date range with filters”List entries between two dates. Narrow the results with category, generated_by or a free-text search over the log content. Pagination is offset-based: limit defaults to 50 (maximum 1000) and offset defaults to 0. The response includes pagination.total_count.
curl -G "https://acme.app.elastio.com/rbac/api/v1/audit-logs" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ --data-urlencode "start_date=2026-10-01" \ --data-urlencode "end_date=2026-10-12" \ --data-urlencode "category=rbac" \ --data-urlencode "generated_by=jane.doe@example.com" \ --data-urlencode "limit=100"params = { "start_date": "2026-10-01", "end_date": "2026-10-12", "category": "rbac", "generated_by": "jane.doe@example.com", "limit": 100,}resp = requests.get(f"{BASE}/rbac/api/v1/audit-logs", headers=HEADERS, params=params, timeout=30)resp.raise_for_status()for entry in resp.json()["data"]: print(entry["created_at"], entry["generated_by"], entry["log"])$Query = "start_date=2026-10-01&end_date=2026-10-12&category=rbac&limit=100"$Result = Invoke-RestMethod -Uri "$Base/rbac/api/v1/audit-logs?$Query" -Headers $Headers$Result.data | Format-Table created_at, generated_by, log{ "data": [ { "id": "0b7e4c52-3a2f-4d8e-9c61-5f0a1b2c3d4e", "log": "…", "category": "rbac", "generated_by": "jane.doe@example.com", "created_at": "2026-10-11T16:42:09Z" } ], "pagination": { "next_page_token": null, "prev_page_token": null, "total_count": 1 }}Export to a SIEM
Section titled “Export to a SIEM”A typical forwarder runs on a schedule (for example, daily), pulls the previous day’s entries page by page, and writes them as JSON lines that a SIEM agent or HTTP collector can ingest. Because start_date and end_date are whole days, de-duplicate on id if your job’s windows overlap.
- Pick the window:
start_dateandend_dateset to the day you’re exporting. - Request
limit=1000(the maximum) starting atoffset=0. - Write each entry in
datato your sink. - Add the number of returned entries to
offsetand repeat untiloffsetreachespagination.total_countor a page comes back empty. - Record the last exported date so the next run picks up where this one stopped.
#!/usr/bin/env bash# Export one day of audit logs as JSON lines.DAY=${1:-$(date -u -d yesterday +%F)}OFFSET=0; LIMIT=1000while :; do PAGE=$(curl -s -G "https://acme.app.elastio.com/rbac/api/v1/audit-logs" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ --data-urlencode "start_date=$DAY" --data-urlencode "end_date=$DAY" \ --data-urlencode "limit=$LIMIT" --data-urlencode "offset=$OFFSET") COUNT=$(echo "$PAGE" | jq '.data | length') echo "$PAGE" | jq -c '.data[]' >> "elastio-audit-$DAY.jsonl" OFFSET=$((OFFSET + COUNT)) TOTAL=$(echo "$PAGE" | jq '.pagination.total_count // 0') [ "$COUNT" -eq 0 ] || [ "$OFFSET" -ge "$TOTAL" ] && breakdoneimport json, os, requestsfrom datetime import date, timedelta
BASE = "https://acme.app.elastio.com"HEADERS = {"Authorization": f"Bearer {os.environ['ELASTIO_TOKEN']}"}
def export_day(day: date, sink): offset, seen = 0, set() while True: resp = requests.get( f"{BASE}/rbac/api/v1/audit-logs", headers=HEADERS, params={"start_date": day.isoformat(), "end_date": day.isoformat(), "limit": 1000, "offset": offset}, timeout=60, ) resp.raise_for_status() page = resp.json() rows = page["data"] for row in rows: if row["id"] not in seen: seen.add(row["id"]) sink.write(json.dumps(row) + "\n") offset += len(rows) if not rows or offset >= page["pagination"].get("total_count", 0): return len(seen)
yesterday = date.today() - timedelta(days=1)with open(f"elastio-audit-{yesterday}.jsonl", "a") as sink: print("exported", export_day(yesterday, sink))$Day = (Get-Date).ToUniversalTime().AddDays(-1).ToString("yyyy-MM-dd")$Offset = 0; $Limit = 1000$Out = "elastio-audit-$Day.jsonl"do { $Uri = "$Base/rbac/api/v1/audit-logs?start_date=$Day&end_date=$Day&limit=$Limit&offset=$Offset" $Page = Invoke-RestMethod -Uri $Uri -Headers $Headers $Page.data | ForEach-Object { $_ | ConvertTo-Json -Compress } | Add-Content -Path $Out $Offset += @($Page.data).Count} while (@($Page.data).Count -gt 0 -and $Offset -lt $Page.pagination.total_count)Point your SIEM’s file or HTTP collector at the JSON lines output. Each line is one audit entry with the fields shown above.