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 SDK
Every SDK wraps the same create-then-poll flow under client.audit.exports: create a job with optional filters, then poll get until status is ready and read download_url.
Python
job = await client.audit.exports.create(
organization_id="org_01J8F3KQ2R7VWX9YB4ND6MCZAH",
format="csv", # "csv" | "ndjson"
filters={"action": "user.signed_in"}, # optional
)
while True:
status = await client.audit.exports.get(job["id"])
if status["status"] in ("ready", "failed"):
break
await asyncio.sleep(2)
if status["status"] == "ready":
print(status["download_url"])Good to know
- Filters mirror
GET /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.