Skip to main content
GET
/
v1
/
audit-events
Audit events
curl --request GET \
  --url https://api.userepo.com/v1/audit-events
import requests

url = "https://api.userepo.com/v1/audit-events"

response = requests.get(url)

print(response.text)
const options = {method: 'GET'};

fetch('https://api.userepo.com/v1/audit-events', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.userepo.com/v1/audit-events",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

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

func main() {

url := "https://api.userepo.com/v1/audit-events"

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

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

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

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.get("https://api.userepo.com/v1/audit-events")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.userepo.com/v1/audit-events")

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

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
Every meaningful action in Repo records an audit event with metadata-only fields (never raw content). Use this endpoint to export the trail for SOC 2, GDPR, or internal review.

Required action

admin

Query parameters

limit
integer
default:"100"
Max number of events to return. Min 1, max 500.

Response

{
  "auditEvents": [
    {
      "id": "uuid",
      "organizationId": "uuid",
      "actorUserId": null,
      "actorApiKeyId": "uuid",
      "action": "context.retrieve",
      "targetType": "context_contract",
      "targetId": "request-uuid",
      "metadata": {
        "query": "What did we decide about the brand color?",
        "hitCount": 5,
        "citationCount": 5,
        "exclusionCount": 1,
        "providers": ["notion", "slack"]
      },
      "createdAt": "2026-05-30T20:14:00.123Z"
    },
    {
      "id": "uuid",
      "actorUserId": "uuid",
      "actorApiKeyId": null,
      "action": "api_key.create",
      "targetType": "api_key",
      "targetId": "uuid",
      "metadata": {
        "name": "support-agent-prod",
        "prefix": "repo_a1b2",
        "actorType": "agent",
        "allowedActions": ["search", "context", "ask"],
        "allowedProviders": ["slack", "notion"]
      },
      "createdAt": "2026-05-30T19:45:00.000Z"
    }
  ]
}

Action catalog

ActionWhen emitted
context.retrieveEvery /v1/context call
api_key.createNew API key minted
api_key.revokeAPI key revoked
connector.allowlist.updateSlack channel allowlist changed
connector_access.requestUser requested access to a gated connector (Drive/Gmail)
maintenance.slack.cleanup_system_eventsAdmin ran Slack noise cleanup
organization.createNew workspace created
sync_run.createSync run queued from the console
billing.checkout.createStripe Checkout session started
billing.portal.createStripe Billing Portal session opened

Actor identification

Each event has either actorUserId (a Supabase human) or actorApiKeyId (an API key) — never both. Look at which one is non-null to attribute the action.

What’s NOT logged

By design, Repo does NOT log:
  • Full hit content from retrieval (only counts + provider list)
  • API key secrets (only the public prefix)
  • OAuth tokens (encrypted, never appear in logs)
  • Source-item content during ingest
  • LLM completions from /v1/ask
This keeps the audit log small and reduces blast radius if the log is ever exposed.