Skip to content

SIEM: REST API Poll

The REST API Poll test checks your application's log or audit API the way a SIEM uses it. Helena plays the SIEM, or a log collector, in the most common integration: REST API polling. Splunk, Microsoft Sentinel, QRadar and similar products call a log API every few minutes to fetch new events. The Okta System Log API, Microsoft Graph audit logs and Salesforce Event Monitoring all work this way.

Each run:

  1. Works out the time window to ask for: the last N minutes, or everything since the last passed run.
  2. Calls the log endpoint with your API key as Authorization: Bearer {api-key}.
  3. Follows pagination (Link header, a next-page URL, or a cursor) up to a page limit.
  4. Checks the responses and the collected events: status, JSON shape, event count, required fields, and timestamps inside the window.
  5. Writes each request, each page's metadata and a sample of the events to the Test Log.

It can also check the opposite: that the API refuses an invalid or revoked key.

sequenceDiagram
    participant H as Helena (collector)
    participant A as Your log API
    H->>H: Resolve window [since, until]
    H->>A: GET endpoint?since=…&until=…  (Bearer api-key)
    A-->>H: 200 [events…] + next page
    loop Until no next page, an empty page, or max pages
        H->>A: GET next page (same origin only)
        A-->>H: 200 [events…]
    end
    H->>H: Assert status, shape, count, fields, timestamps

Sidebar: SIEM → REST API Poll

Before you begin

  • You need the log API's endpoint URL, which must be public HTTPS.
  • You need an API key or access token that the API accepts as a Bearer token.

Bearer authentication only

Helena always sends Authorization: Bearer {api-key}. APIs that need a different scheme are not supported yet, such as Okta's SSWS {token} for API tokens. Okta, for example, accepts OAuth access tokens as Bearer tokens.

Field reference

Log API

Field Key Required Default Supported values / notes
Method http_method ✅ GET GET sends the parameters and window as a query string. POST sends them as a JSON body, for search-style APIs.
Endpoint URL endpoint_url ✅ — Public HTTPS URL, up to 2048 characters. A query string in the URL is kept.
API key secret api_key ✅ — Up to 4096 characters. Sent as Authorization: Bearer {key}. Encrypted, never shown again. On edit, leave it blank to keep the stored key.
Parameters query_params — Static parameters sent on every request, one name=value per line, up to 20. E.g. limit=100.

Time window

Field Key Required Default Supported values / notes
Each poll asks for window_mode ✅ lookback The last N minutes (lookback): a fixed lookback from the time of the run. Everything since the last passed run (since_last_run): works like a collector checkpoint. See Time windows.
Lookback (minutes) lookback_minutes ✅ 5 1–10080 (7 days). Also used as the first run's window in since_last_run mode.
Time format time_format ✅ iso8601 ISO 8601 (2026-10-28T12:00:00Z), Unix seconds (unix), or Unix milliseconds (unix_ms).
Window start parameter since_param — Name of the parameter that carries the window start, e.g. since or startTime. Leave blank to send no time filter.
Window end parameter until_param — Name of the parameter that carries the window end, e.g. until. Must differ from the start parameter.

Parameter names may contain letters, digits and _ . - [ ] $ : @, up to 100 characters.

Response

Field Key Required Default Supported values / notes
Events path events_path — Where the event array is in the JSON body: a key or dot path, e.g. value (Microsoft Graph), records (Salesforce) or data.events. Leave it blank if the body is the array (Okta).
Event timestamp field timestamp_field — Event field to check against the window, e.g. published or createdDateTime. It accepts ISO 8601 or Unix seconds or milliseconds.
Pagination pagination ✅ none See Pagination.
Next page URL path next_url_path ✅ (body next URL) — Where the next-page URL is in the body, e.g. @odata.nextLink or nextRecordsUrl.
Cursor path cursor_path ✅ (cursor) — Where the cursor is in the body, e.g. meta.next_cursor.
Cursor parameter cursor_param ✅ (cursor) — Parameter name used to send the cursor back, e.g. cursor.
Maximum pages max_pages ✅ 5 1–20. Always 1 when pagination is None.

Paths try the whole string as a literal key first, then fall back to a dot path. That way keys that contain dots, such as @odata.nextLink, work as written.

Expected result

Field Key Default Supported values / notes
The log API should expected_outcome success Return log events (success) or Refuse the API key (rejection).
HTTP status expected_status — 100–599. Blank: any 2xx on success, 401 or 403 on refusal.
Minimum events min_events 0 0–1,000,000, counted across all pages. 0 accepts an empty window.
Maximum events max_events — Optional, at least Minimum events.
Required event fields required_fields — Field paths every event must have (non-null, non-empty), one per line, up to 20. E.g. uuid, eventType, actor.id.
Specification checks strict_spec_checks On Also check that the response is JSON, and that a 401 includes a WWW-Authenticate: Bearer … challenge (RFC 6750 §3).

Time windows

Mode Window sent Notes
The last N minutes now − lookback → now Simple and stateless. Consecutive scheduled runs overlap or leave gaps unless the schedule matches the lookback.
Everything since the last passed run The previous passed run's start time → now Works like a real collector's checkpoint. A failed or errored run doesn't move the checkpoint, so the next run asks for the missed period again. The first run uses the lookback. The window is capped at 7 days.

The window is only sent if you set a Window start parameter (and optionally an end parameter). The run's Build log request step records the window it used and where it came from:

window.source Meaning
lookback The fixed lookback
previous_run Since the last passed run
first_run_lookback No passed run yet, so the lookback was used
previous_run_capped The last passed run was more than 7 days ago, so the window was cut to 7 days

When Event timestamp field is set, every event must fall within the window, with ±60 seconds allowed for clock skew.

Pagination

Option (UI label) pagination How the next page is found
None (single request) none One request only.
Link header, rel="next" (RFC 8288) link_header Link: <https://…?after=x>; rel="next". Used by the Okta System Log.
Next page URL in the body body_next_url A URL at Next page URL path, which can be absolute or path-absolute. Used by Microsoft Graph (@odata.nextLink) and Salesforce (nextRecordsUrl).
Cursor token in the body cursor A token at Cursor path, sent back in Cursor parameter with the original method and parameters.

Next-page URLs are always fetched with GET. Paging stops at Maximum pages, on an empty page, on a non-2xx page, or when a next URL or cursor repeats.

Same-origin rule

Your API key is only ever sent to the endpoint's own origin (scheme, host and port). A next-page URL that points anywhere else is not followed, and an assertion fails. This stops a misconfigured or compromised API from redirecting your key elsewhere.

What gets checked

When the log API should return events:

Assertion When
HTTP status / HTTP status is 2xx Always (first page)
Content-Type is JSON Specification checks on, and a 2xx response
Events list found 2xx. The value at Events path, or the root, must be a JSON array.
Page N returned a list of events Each page after the first
Next page URL stays on the log API origin When pagination returned URLs
Event count Minimum events > 0 or Maximum events set
Every event has `field` One per required field, when there are events
`field` within the poll window Event timestamp field set and there are events

When the log API should refuse the key (only the first request is sent):

Assertion When
HTTP status / API key refused (HTTP 401 or 403) Always
No log events returned Always. Fails on a 2xx.
401 includes a Bearer WWW-Authenticate challenge (RFC 6750 §3) Specification checks on, and a 401

Reading the results

Step Shows
Build log request Method, URL, parameters, the API key's fingerprint and the window (since, until, minutes, source)
Fetch page N Status, selected headers (content-type, link, www-authenticate, retry-after, rate-limit headers, x-request-id), event count, and the next page or why it wasn't followed. The body is included when the page failed or in a refusal test.
Collected events total, pages, logged, and a sample of up to 25 events (64 KB at most). The total is always exact.

Logged events go through the same redaction as the rest of the log.

Examples

Okta System Log

Field Value
Endpoint URL https://acme.okta.com/api/v1/logs
API key An OAuth access token with okta.logs.read
Parameters limit=100 and sortOrder=ASCENDING
Each poll asks for Everything since the last passed run
Window start / end parameter since / until, ISO 8601
Events path (blank, because the body is an array)
Event timestamp field published
Required event fields uuid, eventType, actor.id
Pagination Link header, 5 pages
Cron expression (UTC) */5 * * * *

Microsoft Graph sign-in logs

Field Value
Endpoint URL https://graph.microsoft.com/v1.0/auditLogs/signIns
Parameters $top=50
Events path value
Pagination Next page URL in the body, path @odata.nextLink
Event timestamp field createdDateTime

Graph filters by time with $filter=createdDateTime ge …, not a plain parameter. Leave Window start parameter blank, and add a static $filter parameter if you need one.

Salesforce event log files

Field Value
Endpoint URL https://acme.my.salesforce.com/services/data/v61.0/query?q=SELECT+Id,EventType,LogDate+FROM+EventLogFile
Events path records
Pagination Next page URL in the body, path nextRecordsUrl
Required event fields Id, EventType

Checking that a revoked key is refused

Store the revoked key, set The log API should to Refuse the API key, and leave Specification checks on. The run passes on a 401 with WWW-Authenticate: Bearer error="invalid_token". It fails if any events are returned.

Troubleshooting

Symptom Likely cause
Events list found fails Events path is wrong. Check the Fetch page 1 body to see where the array is.
… within the poll window fails The API ignores the window parameters, or uses a different name or format for them. Check Time format and the parameter names.
Next page URL stays on the log API origin fails The API returns next links on a different host (e.g. a CDN). Point Endpoint URL at that host, if it serves the first page too.
Every run returns 0 events The window is too short for your event volume. Increase Lookback (minutes), or keep Minimum events at 0.
401 with a valid key The API expects a scheme other than Bearer. See Before you begin.