SIEM ingestion
Use this product-independent workflow to collect audit events periodically.
- Select the organization. An OWNER or ADMIN issues a token in Settings → Plans and API. See authentication and tokens.
- For the initial collection, set
SINCEto your required start timestamp. FixUNTILwhen collection begins. - While
next_cursoris present, request the next page with the same filters and end timestamp. Successful reads themselves create audit events, so do not advance the end timestamp during pagination. - Store events using
event_idas a unique key. Save the end timestamp as a checkpoint only after every page has been durably ingested. - Start the next window 10 minutes before the previous end timestamp. Transactions can commit later than the event timestamp. Deduplicate on
event_id. This overlap cannot guarantee coverage of unbounded delays; reconcile older windows as needed.
curl + jq pagination example
Requires Bash, curl and jq. Set the token in SPECTRA_AUDIT_TOKEN. Standard output is NDJSON. On failure, keep the previous checkpoint and fetch the same window again.
Bash
#!/usr/bin/env bash
set -euo pipefail
: "${SPECTRA_AUDIT_TOKEN:?Set the organization token}"
: "${SINCE:?Set the UTC start, for example 2026-09-01T00:00:00Z}"
UNTIL=$(date -u +%Y-%m-%dT%H:%M:%SZ)
cursor=''
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
while :; do
args=(--data-urlencode "since=$SINCE" --data-urlencode "until=$UNTIL"
--data-urlencode 'limit=1000')
if [[ -n "$cursor" ]]; then args+=(--data-urlencode "cursor=$cursor"); fi
status=$(curl --silent --show-error --get \
-H "Authorization: Bearer $SPECTRA_AUDIT_TOKEN" -H 'Accept: application/json' \
-D "$work/headers" -o "$work/page" -w '%{http_code}' \
"${args[@]}" 'https://api.spectra-app.net/api/v1/audit-events')
if [[ "$status" == '429' ]]; then
retry=$(tr -d '\r' < "$work/headers" | awk 'tolower($1)=="retry-after:" {print $2}')
[[ "$retry" =~ ^[0-9]+$ ]] || exit 1
sleep "$retry"
continue
fi
[[ "$status" == '200' ]] || { cat "$work/page" >&2; exit 1; }
jq -e 'has("data") and has("next_cursor") and (.data | type == "array") and
(.next_cursor == null or (.next_cursor | type == "string" and length > 0))' "$work/page" >/dev/null
jq -c '.data[]' "$work/page"
cursor=$(jq -r '.next_cursor // empty' "$work/page")
[[ -n "$cursor" ]] || break
done
printf 'Completed window through %s\n' "$UNTIL" >&2For example, run bash collect.sh > window.ndjson and check its exit status before ingestion. This small-file example removes duplicates within that file. Production ingestion must preserve uniqueness across runs in its destination.
jq
jq -s 'unique_by(.event_id)[]' window.ndjson