Public API¶
The Public API exposes two endpoints for the audit log:
GET /v1/audit/logreturns events newest first, page by page.POST /v1/audit/log/downloadexports every matching event into one JSON file and returns a short-lived download link.
Both accept the same filters and require the project owner or an admin member.
Authenticate¶
Requests use an access token from the OAuth 2.0 client credentials flow, with the Cloud API credentials of the project whose log you want to read:
ACCESS_TOKEN=$(curl -s -X POST https://api.verda.com/v1/oauth2/token \
-H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials","client_id":"<CLIENT_ID>","client_secret":"<CLIENT_SECRET>"}' \
| jq -r .access_token)
The project is taken from the credentials, so no project id is needed in the request.
Read events¶
curl -G https://api.verda.com/v1/audit/log \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d object_type=compute \
-d action=delete \
-d page_size=100
The response holds the events in data and, when more pages remain, a cursor:
{
"data": [
{
"specversion": "1.0",
"id": "log_033FNaNcc0AtphhH71DLBW",
"source": "https://api.verda.com/project/7c9e6a41-2f8b-4d3e-9a15-0b6c4d2e8f37",
"subject": "7bdb4161-c7d2-478c-9850-05719adc8381",
"type": "com.verda.api.cloud.compute.delete.v1",
"time": "2026-07-28T14:15:52.872Z",
"data": {
"contract": "PAY_AS_YOU_GO",
"hostname": "tiny-tree-unfolds-fin-01",
"instance_type": "CPU.4V.16G",
"location_code": "FIN-01",
"discontinue_reason": "by_user_action",
"request_ip": "203.0.113.10",
"request_origin": "console-11.67.0",
"actor_id": "5bbb59cb-fced-44a4-85c6-5005e7480a8f",
"compute": {
"id": "7bdb4161-c7d2-478c-9850-05719adc8381",
"hostname": "tiny-tree-unfolds-fin-01",
"instance_type": "CPU.4V.16G",
"ip": "192.0.2.15",
"os_volume_id": "2b7d0e2e-fc8d-4e9c-8b89-6117a4d8d941",
"location_code": "FIN-01",
"is_cluster": false
}
}
}
],
"cursor": "log_02yTr8Kc11BspqLM40XZQV"
}
Query parameters¶
object_type=compute: return events for one object type, for examplecompute,volume,ssh_key,user. See supported events.action=delete: return events for one action, for examplecreate,delete,login.start_date=2026-07-01T00:00:00.000Z: events at or after this timestamp. Cannot be more than 90 days ago. Defaults to 90 days ago.end_date=2026-07-31T00:00:00.000Z: events at or before this timestamp. Cannot be beforestart_date.page_size=100: events per page, from 1 to 100. Defaults to 20.cursor=log_02yTr8Kc11BspqLM40XZQV: continue from thecursorreturned by the previous response.
Page through the log¶
This endpoint uses cursor pagination rather than the page and pageSize parameters used elsewhere in the API. Pass the cursor from each response back in the next request. The last page has no cursor.
Because the order is fixed (newest first, by event time), events written while you page do not shift the ones you have already read.
import requests
URL = "https://api.verda.com/v1/audit/log"
headers = {"Authorization": f"Bearer {access_token}"}
params = {"object_type": "compute", "page_size": 100}
events = []
while True:
response = requests.get(URL, headers=headers, params=params, timeout=60)
response.raise_for_status()
page = response.json()
events.extend(page["data"])
cursor = page.get("cursor")
if not cursor:
break
params["cursor"] = cursor
# first page
curl -G https://api.verda.com/v1/audit/log \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d page_size=100
# next page, using the cursor from the previous response
curl -G https://api.verda.com/v1/audit/log \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d page_size=100 \
-d cursor=log_02yTr8Kc11BspqLM40XZQV
Exporting to a JSON file¶
POST /v1/audit/log/download takes the same filters as the read endpoint, without page_size and cursor. Verda writes every matching event to a file in object storage and returns a pre-signed link to it:
curl -X POST https://api.verda.com/v1/audit/log/download \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"object_type":"compute","start_date":"2026-07-01T00:00:00.000Z"}'
{
"url": "https://objects.fin-03.verda.storage/audit-logs/7c9e6a41-2f8b-4d3e-9a15-0b6c4d2e8f37/2026/audit-log-20260730-141552-3f0c9a71-b08f-4d48-9e03-6ab6196c186b.json?X-Amz-Signature=...",
"expires_at": "2026-07-30T14:30:52.872Z"
}
Download it with any HTTP client, no extra credentials needed:
- The file is a single JSON array of the same event objects the read endpoint returns, newest first.
- The link is valid for 15 minutes, until
expires_at. Request a new export once it expires. - Each export writes a new file, so exporting twice with the same filters gives you two links.
- The file is written before the response comes back. For a busy project, filter by date range or object type to keep the export small and the request short.
Errors¶
| Status | Reason |
|---|---|
400 |
start_date is more than 90 days ago, or end_date is before start_date |
401 |
The access token is missing or expired |
403 |
The credentials belong to a developer member rather than the project owner or an admin member |