List audit-log entries (cursor-paginated)
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Get, RequestUri = new Uri("https://api.vendorica.com/v1/audit-log?operation=UPDATE&severity=info&limit=50"), Headers = { { "Authorization", "Bearer <token>" }, },};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://api.vendorica.com/v1/audit-log?operation=UPDATE&severity=info&limit=50"
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))
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url("https://api.vendorica.com/v1/audit-log?operation=UPDATE&severity=info&limit=50") .get() .addHeader("Authorization", "Bearer <token>") .build();
Response response = client.newCall(request).execute();const url = 'https://api.vendorica.com/v1/audit-log?operation=UPDATE&severity=info&limit=50';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);}use reqwest;
#[tokio::main]pub async fn main() { let url = "https://api.vendorica.com/v1/audit-log";
let querystring = [ ("operation", "UPDATE"), ("severity", "info"), ("limit", "50"), ];
let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Authorization", "Bearer <token>".parse().unwrap());
let client = reqwest::Client::new(); let response = client.get(url) .query(&querystring) .headers(headers) .send() .await;
let results = response.unwrap() .json::<serde_json::Value>() .await .unwrap();
dbg!(results);}curl --request GET \ --url 'https://api.vendorica.com/v1/audit-log?operation=UPDATE&severity=info&limit=50' \ --header 'Authorization: Bearer <token>'Cursor-paginated read of the hash-chained audit trail. Pass ?cursor=<opaque>&limit=<n> to advance; the response carries cursor.nextCursor (null on the last page) plus cursor.hasMore. The legacy ?page= parameter returns 400 — see /v1/openapi.json for the canonical contract.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Example
UPDATEFilter to entries whose operation matches, compared CASE-INSENSITIVELY (create and CREATE are the same filter). The vocabulary is OPEN and deliberately not published as an enum: operation is a free-form column and new domain events mint new names without an API release, so a closed list here would reject a value the feed genuinely contains. Values in use today are the CRUD/session set (CREATE, UPDATE, DELETE, LOGIN, LOGOUT, EXPORT, EDIT_START, EDIT_FINISH, VIEW) plus dotted domain-event names such as connector.run.fail, connector.run.skipped, vendor_qualification.reminder.sent and spend_limit.exceeded. A value nothing has recorded is not an error — it matches no rows and returns an empty page.
Lower bound (inclusive) on createdAt, as an ISO date or datetime. Takes PRECEDENCE over the deprecated dateFrom: when both are sent, dateFrom is ignored.
Upper bound (inclusive) on createdAt, as an ISO date or datetime. A BARE DATE covers the whole of the day it names — 2026-09-01 means through 2026-09-01T23:59:59.999Z — so createdFrom and createdTo set to the same date return that day. Send a datetime instead when you want a precise instant; it is used exactly as given. Takes PRECEDENCE over the deprecated dateTo: when both are sent, dateTo is ignored.
Deprecated alias for createdFrom, kept for existing /v1 integrations. Ignored without error when createdFrom is also present. Migrate to createdFrom; no removal date is set, and removal would be announced per the versioning policy before it happens.
Deprecated alias for createdTo, kept for existing /v1 integrations. Ignored without error when createdTo is also present. Migrate to createdTo; no removal date is set, and removal would be announced per the versioning policy before it happens.
Responses
Section titled “Responses”Success
object
object
The user who made the change. Null for every non-user actorType — read actorType before concluding an entry is unattributed.
The user’s email at the time of the change. Null for an api_client actor; for a system actor it carries the job identity (e.g. system:retention-purge) rather than an address.
The user’s role name at the time of the change. Null for api_client and system actors.
Which credential produced the entry: user (a signed-in person), api_client (a public-API key) or system (a scheduled job or platform process). Typed as a string rather than a closed enum because the set is designed to be extensible; treat an unrecognised value as non-human.
The API key that made the change, for api_client entries; null for every other actor type. Stable for the life of the entry — deleting the key does not clear it, so this is the field to correlate on.
The API key’s current name, resolved at read time. Null when the key has since been deleted (the entry keeps its apiClientId), and null for every non-api_client entry. Renaming a key changes this for its historical entries too.
object
Example
{ "success": true, "data": [ { "id": "947f0edf-a104-45e7-8dec-65ecc3246c38", "entityType": "string", "entityId": "string", "operation": "string", "oldValues": {}, "newValues": {}, "changedFields": [ "string" ], "userId": "string", "userEmail": "string", "userRole": "string", "actorType": "api_client", "apiClientId": "b63c4c60-42ec-4e46-8ee6-069fbf1c6601", "apiClientName": "string", "ipAddress": "string", "userAgent": "string", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H", "description": "string", "severity": "string", "createdAt": "2026-08-19T09:41:12.004Z" } ], "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H", "message": "string", "cursor": { "nextCursor": "string", "hasMore": true, "limit": 1 }}Validation error
object
Example
{ "success": false, "error": "Bad request", "code": "BAD_REQUEST", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Unauthorized
object
Example
{ "success": false, "error": "Unauthorized", "code": "UNAUTHORIZED", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Forbidden — missing scope
object
Example
{ "success": false, "error": "Forbidden", "code": "FORBIDDEN", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Not found
object
Example
{ "success": false, "error": "Resource not found", "code": "NOT_FOUND", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}Rate limit exceeded
object
Example
{ "success": false, "error": "Too many requests", "code": "TOO_MANY_REQUESTS", "timestamp": "2026-08-19T09:41:12.004Z", "requestId": "req_01J5X8ZC3K4T7Q9M2W6B0N1V4H"}