Skip to main content

REST API

The SDKs use this API under the hood. You can call it directly from any language.

Base URL: https://api.auditail.io Auth: Authorization: Bearer <your API key> on every /v1 request.

Events are scoped to your key. One key can never read or write another key's events.

Set a User-Agent

Requests with a missing or default scripting User-Agent (for example Python's built-in urllib) can be rejected by our edge protection with 403 error code: 1010. The official SDKs set one for you. If you call the API directly, send a descriptive User-Agent such as my-agent/1.0.


POST /v1/events​

Store one event, or a batch of up to 100 as { "events": [...] }.

curl -X POST https://api.auditail.io/v1/events \
-H "Authorization: Bearer $AUDITAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"auditId": "evt_001",
"agentId": "billing-bot",
"action": "send_email",
"approved": false,
"matchedRule": "no-external-email",
"reason": "External recipient",
"payload": { "to": "[email protected]" },
"timestamp": "2026-01-15T10:30:00Z",
"environment": "production"
}'

Required: auditId ([A-Za-z0-9_-], max 64), agentId, action, approved (boolean), payload (object, max 64 KB), timestamp (ISO 8601). Optional: userId, reason, matchedRule, tags, environment, sdkVersion.

StatusMeaning
201Stored. Body: { "accepted": n, "duplicates": n, "head": { "seq", "hash" } }
200Everything in the request was already stored (safe retry).
401Missing or invalid API key.
413Request body over 1 MB.
422Invalid event; the message names the field.

Sending the same auditId twice is safe: the second copy is ignored and reported under duplicates.


GET /v1/events​

Newest first. Query parameters: limit (1-200, default 50), approved (true/false), agent_id, before_seq (for paging; use nextBeforeSeq from the previous response).

curl "https://api.auditail.io/v1/events?approved=false&limit=20" \
-H "Authorization: Bearer $AUDITAIL_API_KEY"

GET /v1/stats​

Totals, last-24-hours counts, top rules, and top agents.

GET /v1/verify​

Re-computes the hash chain and returns { "ok": true, "checked": 1234, "head": "<hash>" }, or { "ok": false, "firstBadSeq": n, "problem": "content_modified" | "broken_link" | "missing_event" }.

Verification covers up to 200,000 events per call; larger logs report "truncated": true.


Approvals​

Human approval uses two kinds of credential: an agent API key (atl_live_...) creates requests and reads their status, and an approver token (atl_appr_...) decides them. An agent key can never decide a request. See the approval guide.

POST /v1/approvals (agent key)​

curl -X POST https://api.auditail.io/v1/approvals \
-H "Authorization: Bearer $AUDITAIL_API_KEY" -H "Content-Type: application/json" \
-d '{"agentId":"payout-agent","action":"create_payout","ruleName":"payout-over-limit",
"reason":"Payouts over $10,000 need a human","payload":{"amount":25000},"timeoutSeconds":600}'

Required: agentId, action, ruleName, payload (object, max 48 KB). Optional: reason, userId, tags, environment, timeoutSeconds (10 to 86400, default 900). Returns 201 with the approval (status: "pending", expiresAt). 429 if 100 requests are already pending.

GET /v1/approvals/{id} (either credential)​

Returns the approval. status is pending, approved, denied or expired. Overdue requests flip to expired when read. Poll this endpoint, or use the SDK's waitForApproval.

GET /v1/approvals?status=pending (either credential)​

status is pending (default), approved, denied, expired or all.

POST /v1/approvals/{id}/decision (approver token)​

curl -X POST https://api.auditail.io/v1/approvals/apr_.../decision \
-H "Authorization: Bearer $AUDITAIL_APPROVER_TOKEN" -H "Content-Type: application/json" \
-d '{"decision":"approve","comment":"verified by phone"}'

decision is approve or deny. The approver's name is taken from the token. 409 if it was already decided or has expired; 403 for an agent key.

Notification settings (approver token)​

GET /v1/settings returns the webhook status (never the full URL). PUT /v1/settings with {"webhookUrl":"https://..."} sets it and returns the signing secret once; {"webhookUrl":null} removes it; add "rotateSecret":true to rotate. POST /v1/settings/test sends a test notification. Webhook format and signature verification are in the approval guide.

GET /v1/me​

Returns { "role": "agent" | "approver", "label": "...", "keyId": "..." } for the credential you sent.


Errors​

All errors share one shape:

{ "error": { "code": "invalid_event", "message": "events[0]: approved must be a boolean" } }