---
title: SIEM Integration
description: Stream 1Security alerts and logs into Splunk, Microsoft Sentinel, or any SIEM via scheduled REST polling.
icon: Radar
---

This guide shows how to forward 1Security **policy alerts**, **audit logs**,
and **security alerts** into your SIEM using the [REST API](/docs/reference/api).
The model is **pull-based**: your SIEM polls on a schedule and stores a cursor so
each poll fetches only what's new.

## 1. Create an API key

In the dashboard, open **Settings → API Keys** and create a key with the scopes
you need (`logs:read`, `monitoring-alerts:read`, `security-alerts:read`). Copy
the `1sec_live_…` secret - it's shown once.

Verify it:

```bash
curl -H "Authorization: Bearer $ONESEC_API_KEY" \
  https://api.1security.ai/api/v1/ping
```

## 2. The incremental polling pattern

Don't page through the entire history on every run. Instead, **window by
ingestion time** and persist the high-water mark between polls.

<Steps>
  <Step>
    ### Track a watermark
    Persist the timestamp of your last successful poll (start with "now minus a
    few minutes").
  </Step>
  <Step>
    ### Query the window
    Ask only for events ingested since the watermark. For `/logs`, use
    `discoveredFrom` (ingestion time) rather than `from` (event time) - late-
    arriving M365 events are surfaced by ingestion time, so this never misses
    them.

    ```bash
    curl -H "Authorization: Bearer $ONESEC_API_KEY" \
      "https://api.1security.ai/api/v1/logs?discoveredFrom=2026-06-05T09:00:00Z&limit=1000"
    ```

  </Step>
  <Step>
    ### Drain pages
    Follow `pagination.nextCursor` with `?cursor=` until `hasMore` is `false`.
  </Step>
  <Step>
    ### Advance + dedupe
    Move the watermark to the current time, and dedupe on the event `id` (use it
    as the SIEM event key) so an overlapping window never double-indexes.
  </Step>
</Steps>

<Callout type="info">
  Always overlap windows slightly (re-poll the last minute or two) and rely on
  `id` dedupe rather than exact-boundary cursors. This is the safest way to
  guarantee no gaps across restarts.
</Callout>

## 3. Wire it into your SIEM

<Tabs items={['Splunk', 'Microsoft Sentinel', 'Plain cron']}>
  <Tab value="Splunk">
    Use a **REST API Modular Input** (e.g. the Splunk Add-on Builder or
    `rest_ta`):

    - Endpoint: `https://api.1security.ai/api/v1/security-alerts`
    - Auth header: `Authorization: Bearer <key>`
    - Response handler: index `data[]`, set the event time from
      `firstActivityDateTime`, and use `id` as the dedup key.
    - Schedule: every 1–5 minutes, persisting `discoveredFrom`/`from` as a
      checkpoint.

  </Tab>
  <Tab value="Microsoft Sentinel">
    Use a **Codeless Connector** (or a Logic App) that GETs each endpoint on a
    timer, paginates via `pagination.nextCursor`, and posts `data[]` to a Log
    Analytics custom table through the Data Collection Endpoint. Store the
    watermark in the connector's state.
  </Tab>
  <Tab value="Plain cron">
    Minimal poller sketch:

    ```bash
    #!/usr/bin/env bash
    SINCE=$(cat .watermark 2>/dev/null || date -u -d '-5 min' +%FT%TZ)
    CURSOR=""
    while :; do
      RESP=$(curl -s -H "Authorization: Bearer $ONESEC_API_KEY" \
        "https://api.1security.ai/api/v1/logs?discoveredFrom=$SINCE&limit=1000&cursor=$CURSOR")
      echo "$RESP" | jq -c '.data[]' >> /var/log/1security-logs.ndjson
      CURSOR=$(echo "$RESP" | jq -r '.pagination.nextCursor // empty')
      [ -z "$CURSOR" ] && break
    done
    date -u +%FT%TZ > .watermark
    ```

  </Tab>
</Tabs>

## 4. Handle rate limits

Stay under 600 requests/min per key. If you receive `429`, honor the
`Retry-After` header. Polling each endpoint once per minute with a large `limit`
is well within budget for typical tenants.

## Field mapping cheatsheet

| Use for    | Logs                            | Security alerts         |
| ---------- | ------------------------------- | ----------------------- |
| Event time | `occurredAt`                    | `firstActivityDateTime` |
| Dedup key  | `id`                            | `id`                    |
| Severity   | `severity`                      | `severity`              |
| Actor      | `actorName` / `actorIp`         | `actorDisplayName`      |
| Resource   | `resourceName` / `resourceType` | `threatDisplayName`     |

See the full [API reference](/docs/reference/api) for every field and parameter.
