Exporting events
Exports are asynchronous. Create a job with the same filters you would pass to the list endpoint, poll until its status is ready, then download from the short-lived presigned URL. Choose csv for spreadsheets or ndjson for line-delimited JSON. A single export spans both hot and cold-storage rows, so an old range comes back whole.
1Create the export
curl -X POST https://api.invoance.com/v1/audit/exports \
-H "Authorization: Bearer invoance_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"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"
}
}'2Poll until ready
curl https://api.invoance.com/v1/audit/exports/aexp_01J… \
-H "Authorization: Bearer invoance_live_xxx"3Download the file
curl -L "https://…r2.cloudflarestorage.com/…" -o audit-export.csvWith the Python SDK
The SDK wraps the same create-then-poll flow. Node is identical under client.audit.exports.
import asyncio
from invoance import InvoanceClient
async with InvoanceClient() as client:
job = await client.audit.exports.create(
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"},
)
while True:
status = await client.audit.exports.get(job["id"])
if status["status"] in ("ready", "failed"):
break
await asyncio.sleep(2)
print(status["status"], status.get("download_url"))Good to know
- Filters mirror
GET /v1/audit/events: actions, actor_id, target_id, and a range_start/range_end window. - The
download_urlis presigned and short-lived. Re-poll the job to mint a fresh one if it expires. - Exports are read-only and never billed; reads and verification are always free.