Audit Logs
Twenty endpoints covering the audit log surface: orgs and their lifecycle, signed events, webhook streams, hosted-viewer portals, and exports.
/integrations/webhooks/:tokenReceive provider webhooks (zero-code ingest)The inbound endpoint your auth provider (Clerk or Auth0) delivers to. Created from Dashboard → Audit Logs → Integrations, which mints the unguessable token in the URL (shown once). Not called with an API key: Clerk deliveries are Svix-signature verified, Auth0 deliveries are checked against the stream's Authorization token. Mapped events become signed audit events; unmapped or org-less events return 200, are counted as skipped, and consume no quota, so provider retries never loop and over-subscribing is harmless.
POST /integrations/webhooks/{token}
svix-id: msg_2sK9… ← Clerk (Svix) headers; Auth0 sends
svix-timestamp: 1752300000 Authorization: <your stream token>
svix-signature: v1,base64…
Content-Type: application/json
{ …provider event payload… }
/audit/orgsCreate an orgCreates an audit org, one of your end customers, addressed by your own organization_id. Events reference the org by that id. Requires the audit:write scope. Retention defaults to your plan cap and can be lowered per org.
POST /audit/orgs
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"organization_id": "org_01J8F3KQ2R7VWX9YB4ND6MCZAH",
"name": "Acme Production"
}
/audit/orgs/:idRename an orgSets, changes, or clears an org's display name after creation. The id accepts the aorg_ id or your organization_id. Pass null (or an empty string) to clear the name. Names are display-only; events reference the org by organization_id, so renaming never affects signed data. Requires the audit:write scope.
PATCH /audit/orgs/aorg_01J…
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"name": "Acme Production (EU)"
}
/audit/orgsList orgsReturns your audit orgs, newest first. Archived orgs are hidden by default; pass ?include_archived=true to include them. Requires the audit:read scope.
GET /audit/orgs?include_archived=true
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/integrityCheck sequence integrityScans an org's gap-free sequence for holes. A contiguous range proves nothing was deleted between the integrity floor and the latest event; a gap is a tamper signal. Requires the audit:read scope.
GET /audit/orgs/aorg_01J…/integrity
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/retentionSet retentionSets how long an org's events are retained, in days, clamped to your plan's maximum. Older events tier to cold storage and are eventually purged. Requires the audit:write scope.
PUT /audit/orgs/aorg_01J…/retention
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"days": 365
}
/audit/orgs/:id/archiveArchive an orgFreezes an org for new activity: event ingest, webhook deliveries, new streams, portal links, and exports return 409 org_archived, and stream delivery pauses. Existing history stays readable and verifiable, and retention keeps aging events on the normal clock. Idempotent and fully reversible. Archived orgs still count toward your plan's org cap. Requires the audit:write scope.
POST /audit/orgs/aorg_01J…/archive
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/unarchiveUnarchive an orgClears archived_at and everything resumes: ingest and webhook deliveries are accepted again, new streams, portal links, and exports unblock, and stream delivery picks up from its held cursor. Idempotent. Requires the audit:write scope.
POST /audit/orgs/aorg_01J…/unarchive
Authorization: Bearer invoance_live_xxx
/audit/orgs/:idDelete an orgPermanently deletes an org and frees its plan-cap slot and organization_id for reuse. Allowed only when nothing signed would be destroyed: either the org never ingested an event (and none was accepted within the last 24 hours), or it is archived and retention has already purged all of its data. Anything else returns 409 org_not_deletable with the reason. Requires the audit:write scope.
DELETE /audit/orgs/aorg_01J…
Authorization: Bearer invoance_live_xxx
/audit/eventsSend an eventRecords one activity event. The server normalizes occurred_at, signs the canonical bytes with your tenant Ed25519 key, and assigns a gap-free per-org sequence. An Idempotency-Key header is required. Requires the audit:write scope.
POST /audit/events
Authorization: Bearer invoance_live_xxx
Idempotency-Key: <uuid>
Content-Type: application/json
{
"organization_id": "org_01J8F3KQ2R7VWX9YB4ND6MCZAH",
"action": "user.signed_in",
"occurred_at": "2026-06-24T12:00:00.000Z",
"actor": { "type": "user", "id": "user_123", "name": "Ada Lovelace" },
"targets": [{ "type": "team", "id": "t_eng" }],
"context": { "location": "203.0.113.10", "user_agent": "Chrome/126.0.0.0" },
"metadata": { "plan": "growth" }
}
/audit/eventsList eventsReturns events for an org, newest first, keyset-paginated with an opaque cursor. Filter by actions, actor_id, target_id, and a range_start/range_end window. Requires the audit:read scope.
GET /audit/events?organization_id=org_01J8F3KQ2R7VWX9YB4ND6MCZAH&actions=user.signed_in&range_start=2026-06-01T00:00:00Z&limit=50
Authorization: Bearer invoance_live_xxx
/audit/events/:idRetrieve an eventReturns a single audit event by id, scoped to your tenant. Read-only.
GET /audit/events/aevt_01J…
Authorization: Bearer invoance_live_xxx
/audit/events/:id/verifyVerify an eventRebuilds the canonical signed bytes from the stored columns, recomputes the hash, and checks the Ed25519 signature against the tenant's pinned key (never the value stored on the row). Returns whether the event is authentic and why.
GET /audit/events/aevt_01J…/verify
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/streamsCreate a webhook streamRegisters a destination URL for an org. New events are delivered in order, HMAC-signed with X-Invoance-Signature, with retries and exponential backoff. The signing secret is returned once. Capped per plan. Requires the audit:write scope.
POST /audit/orgs/aorg_01J…/streams
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"type": "webhook",
"url": "https://example.com/webhooks/audit"
}
/audit/orgs/:id/streamsList streamsReturns the org's stream destinations and their delivery health (state, failure streak, last error). Never returns the signing secret. Requires the audit:read scope.
GET /audit/orgs/aorg_01J…/streams
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/streams/:stream_id/testTest a streamSends a synthetic event to the destination and returns the delivery result, so a customer can confirm their endpoint before real traffic flows. Requires the audit:write scope.
POST /audit/orgs/aorg_01J…/streams/astr_01J…/test
Authorization: Bearer invoance_live_xxx
/audit/orgs/:id/streams/:stream_idDelete a streamRemoves a stream destination. Delivery stops immediately; in-flight events are not retried to the deleted endpoint. Requires the audit:write scope.
DELETE /audit/orgs/aorg_01J…/streams/astr_01J…
Authorization: Bearer invoance_live_xxx
/audit/portal_sessionsMint a hosted-viewer linkCreates a one-time link to a read-only, org-scoped viewer your customer opens with no Invoance account. Set intent to audit_logs for the event viewer or log_streams for the stream-config screen. The token is shown once. Requires the audit:write scope.
POST /audit/portal_sessions
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"organization_id": "org_01J8F3KQ2R7VWX9YB4ND6MCZAH",
"intent": "audit_logs",
"session_duration_seconds": 7200,
"link_duration_seconds": 300
}
/audit/exportsCreate an exportQueues an async CSV or NDJSON export of an org's events with optional filters. A polling worker streams the matching hot and cold events to one file. Requires the audit:read scope.
POST /audit/exports
Authorization: Bearer invoance_live_xxx
Content-Type: application/json
{
"organization_id": "org_01J8F3KQ2R7VWX9YB4ND6MCZAH",
"format": "csv",
"filters": {
"actions": "user.signed_in",
"range_start": "2026-06-01T00:00:00Z",
"range_end": "2026-06-30T23:59:59Z"
}
}
/audit/exports/:idPoll an exportReturns the export's status and, when ready, a short-lived presigned download URL. Poll until status is ready or failed.
GET /audit/exports/aexp_01J…
Authorization: Bearer invoance_live_xxx