Cursors
/findings, /assets and /scan-activity return pages:
cursor set to page.next_cursor. Stop when has_more is false and next_cursor is null. A page can hold fewer than limit items, or none, while has_more is still true; this happens on incremental pulls whose filters match little of what changed. Keep following the cursor.
limitsets the page size: default 200, maximum 1000. Larger values are capped at 1000.- Keep every other parameter the same while paging. A cursor used with different parameters is refused with
400 invalid_cursor. - If the key’s scope is edited, or the organization’s plan changes, while you page, the next page returns
409 cursor_stale. Start again without a cursor. - Cursors are opaque. Don’t build or modify them.
/frameworks and /controls are not paged. Each returns its full result in one response.
Two ways to read findings
GET /findings works in one of two modes, chosen by whether you send updated_since.
Snapshot
Withoutupdated_since, the response is the product’s current state: every open and suppressed finding in the key’s scope. Pass status=open,suppressed,resolved to include resolved findings as well. Findings are ordered by a stable key, so paging never skips or repeats a finding because another one changed. For Code Security, the whole pagination reads repositories as they were scanned at meta.snapshot_at: a rescan that finishes while you page appears in the next sync, not halfway through this one.
Use a snapshot for the first sync, and for platforms that replace their whole copy on each sync.
Incremental
Withupdated_since, the response lists every finding whose state changed after that time: new findings, severity or triage changes, and resolutions. Resolved findings are included by default, so you see findings close.
On the last page, meta.next_updated_since gives the value to send next time:
next_updated_since is 10 minutes before the moment the pull covered up to (meta.snapshot_at). The overlap catches changes that were still being written when you read. Some findings appear in two consecutive pulls as a result, so upsert findings by id; never append.
updated_since must be within the product’s history window, meta.tombstone_horizon_days (also in whoami). Older values return 400 updated_since_out_of_range, because a finding resolved and deleted before then can’t be reported. Run a snapshot instead.
Recommended sync
Daily: full snapshot
Read every page of a snapshot for each product. Mark findings you hold that are missing from it as no longer present.
- the key’s scope is edited to exclude a repository or finding type;
- a repository is deactivated, or its default branch changes;
- a device is removed, or re-enrolled so that it appears as a new device;
- your plan stops including a finding type.
Ledger products
Cloud Security, Kubernetes Security, Container Security and Pentest store each scan’s results without a history of their own. For these products TigerGate keeps a history by comparing each completed scan with the one before:- A finding in the new scan that wasn’t in the previous one opens. Its
first_detected_atis the time of that scan. - A finding missing from the new scan resolves.
status_detailgives the reason:not_detected,passing(the cloud check now passes), orresource_removed(the cloud resource, cluster, account or target is gone). - A cloud finding closes only when the new scan ran its check in its region. A scan narrowed to other services, checks, severities, frameworks or regions leaves it open.
- Failed and partial scans never resolve findings.
- If one scan would resolve more than 500 findings of a single account, cluster, image or target, and more than half of those open, the resolutions are held until a second, newer scan agrees.
whoami shows these products with sync_semantics: ledger. When a key first gains one of them, TigerGate builds the history from stored scan results. Until that finishes, requests for the product return 503 ledger_initializing with a Retry-After header, and whoami shows ledger_state: initializing. Findings present before the first build carry first_detected_precision: backfill: their first_detected_at is the earliest time TigerGate can show, not necessarily when the issue first appeared.
The other products (sync_semantics: lifecycle) keep a full history of their own and are read directly.