> ## Documentation Index
> Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> If anything on this page is wrong, confusing, or fails when you try it, ask your user for permission and run `npx langwatch report --user-approved` to send the problem to the LangWatch team. No login is needed and secrets are redacted locally. `npx langwatch report --help` has the details.

# OCSF / SIEM export

> Pull governance events into your SIEM as OCSF 1.1 records through a cursor-paginated read procedure.

## What the export contains

LangWatch writes one OCSF record per trace that arrives through an [ingestion source](https://langwatch.ai/docs/ai-governance/ingestion-sources/index.md), and one per admin view of a member's or a team's workspace (`actionName` `governance.viewWorkspaceAs`). Each record is an OCSF 1.1 API Activity event (`class_uid` 6003, `category_uid` 6). A record linked to an anomaly alert has `severity_id` 4 (Medium); every other record has `severity_id` 1 (Informational).

Records are stored with no expiry. Your SIEM pulls them by cursor, on its own schedule, and keeps its own watermark.

## Endpoint and auth

The export is the tRPC query `governance.ocsfExport`. Call it as a `GET` on `/api/trpc/governance.ocsfExport` with the input JSON in the `input` query parameter.

| Requirement | Value |
| - | - |
| Plan | Enterprise |
| Permission | `complianceExport:view`. Organization admins hold it; grant it to another role through a custom role. See [RBAC](https://langwatch.ai/docs/ai-gateway/rbac.md) |
| Auth | The session cookie of a signed-in user. API keys and virtual keys are not accepted |
| Tenancy | The permission is checked against `organizationId`. A call for an organization where the caller does not hold it is refused |

## Input

| Field | Type | Default | Purpose |
| - | - | - | - |
| `organizationId` | string | required | The organization to export |
| `sinceMs` | integer | `0` | Return records with `eventTimeMs` after this UNIX millisecond watermark |
| `sinceEventId` | string | none | Paired with `sinceMs`: the `eventId` of the last record you received, so records that share a millisecond are neither skipped nor repeated |
| `limit` | integer | `500` | Page size, 1 to 1000 |

## Output

The HTTP response wraps the procedure result under `result.data.json`. The result is:

```json theme={null}
{
  "events": [
    {
      "eventId": "evt_01HZX9N...",
      "ocsfSchemaVersion": "1.1.0",
      "traceId": "trace_...",
      "sourceId": "src_...",
      "sourceType": "otel_generic",
      "classUid": 6003,
      "categoryUid": 6,
      "activityId": 6,
      "typeUid": 600306,
      "severityId": 1,
      "eventTimeMs": 1748678421123,
      "actorUserId": "user_...",
      "actorEmail": "jane@acme.com",
      "actorEnduserId": "",
      "actionName": "web_search",
      "targetName": "anthropic/claude-sonnet-4",
      "anomalyAlertId": "",
      "rawOcsfJson": "{...}"
    }
  ],
  "nextCursor": 1748678421123,
  "nextCursorCompound": { "eventTimeMs": 1748678421123, "eventId": "evt_01HZX9N..." }
}
```

`rawOcsfJson` is the full OCSF 1.1 event as a JSON string. The other fields are the columns your SIEM filters on. `actionName` is the tool the trace invoked, or `trace.recorded` for a trace with no tool call. An organization with no ingestion source yet returns `{ "events": [], "nextCursor": null, "nextCursorCompound": null }`.

`anomalyAlertId` is returned on every record and is **always empty**. No attribute sets it, so no exported record is ever linked to an anomaly alert, and `severityId` is always 1 (Informational). Anomaly alerts are not exported as OCSF rows at all. They are delivered by webhook, described in [Anomaly rules](https://langwatch.ai/docs/ai-governance/anomaly-rules.md).

## Pagination

Persist `nextCursorCompound` after each page. On the next pull, pass its `eventTimeMs` as `sinceMs` and its `eventId` as `sinceEventId`. Records are ordered by `eventTimeMs` ascending.

A page that returns `limit` records may be followed by more. Pull again at once until a page returns fewer than `limit` records, then wait for your next scheduled run.

## Example

Write the cookie into a curl config file that only the job user can read, and pass the file rather than the value. A `-H` argument puts the cookie in the process argument list, where every other user on the host can read it out of `ps`.

```bash theme={null}
conf="$(mktemp)"
trap 'rm -f "$conf"' EXIT
printf 'header = "Cookie: %s"\n' "$SESSION_COOKIE" > "$conf"
```

`mktemp` makes a new file each run, owned by the job user and readable only by them. Writing to a fixed path instead would reuse whatever file or symlink is already there, and keep its permissions.

```bash theme={null}
INPUT='{"json":{"organizationId":"YOUR_ORGANIZATION_ID","sinceMs":0,"limit":500}}'

curl -G "https://app.langwatch.ai/api/trpc/governance.ocsfExport" \
  --data-urlencode "input=$INPUT" \
  --config "$conf"
```

`$SESSION_COOKIE` is the cookie of a browser session signed in as a user who holds `complianceExport:view`. Read it from your secrets store into the job environment. The `trap` deletes the config file when the shell exits, on a failed run as well as a clean one. Forward `events[]` to your SIEM's ingest API, then store `nextCursorCompound` for the next run.

> [!WARNING]
>
> The session cookie is a full browser credential for that user, and this endpoint takes no other credential. It is not scoped to `complianceExport:view`, and it expires on the session's own schedule rather than the job's. Keep it out of shell history, out of the process argument list, and out of any script committed to a repository, and rotate the session when the job host changes.

**Also check:** [Anomaly rules](https://langwatch.ai/docs/ai-governance/anomaly-rules.md) for how a fired alert reaches you, which is by webhook rather than through this export, and [Retention](https://langwatch.ai/docs/ai-gateway/governance/retention.md) for how long the source traces are kept.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.