SIEM delivery
Control delivers the org's audit stream to your SIEM with checkpoints, deduplication and visible failures, so a missed event (for example an agent suspension) can be recovered without being counted twice.
Console: SIEM delivery at /control/orgs/:oid/siem. Creating, testing and replaying need org_admin; viewing needs org.read.
Create a destination
POST /v1/orgs/{oid}/siem
content-type: application/json
{
"name": "Splunk production",
"type": "splunk_hec",
"url": "https://splunk.acme.example:8088/services/collector/event",
"secret_ref": "env:SPLUNK_HEC_TOKEN",
"redaction": { "drop_fields": ["data.reason", "actor.id"] },
"scope": { "tenants": ["ten_…"], "projects": ["prj_…"] }
}| Field | Rule |
|---|---|
type | webhook, splunk_hec, sentinel or chronicle. |
url | HTTPS (localhost allowed for testing). |
secret_ref | A secret reference (env:, kms:, sm:). Sent as Authorization: Splunk … for HEC, Bearer … otherwise. |
redaction.drop_fields | Up to 50 dotted paths removed before delivery. id and seq cannot be dropped. |
scope | Optional: only these org tenants or enrolled projects. |
A new destination starts at the current head of the stream. Use replay to backfill.
Event format
{
"id": "evt_…",
"seq": 18233,
"occurred_at": "2026-11-14T18:10:00.000Z",
"org_id": "org_…",
"tenant_id": "ten_…",
"project_id": "prj_…",
"type": "action.approved",
"action_id": "act_…",
"actor": { "type": "system", "id": null },
"policy_version": "pol_…@3",
"evidence_ref": null,
"outcome": null,
"data": { "from": "pending_approval", "reason_code": "awaiting_agent_resume" }
}id is stable and seq is a global, increasing sequence. data is the minimised audit payload; it never contains prompts, payloads or credentials. Event types include every action transition (action.submitted, action.evaluated, action.approval_requested, action.decision_recorded, action.dispatched, action.succeeded, …), receipt.issued, receipt.exported, agent.suspended, agent.credential_revoked, grant.revoked, policy.published, emergency_deny.published, gateway.emergency_deny_acknowledged and incident.released.
| Type | Body |
|---|---|
webhook | { "events": [ … ] } |
chronicle | { "events": [ … ] } |
sentinel | a JSON array of events |
splunk_hec | newline-delimited HEC events |
Delivery behaviour
- Events are delivered in
seqorder in batches of 100, after a short settle time (30 seconds) so that concurrent writes are not skipped. Delivery runs on the periodic sweep and from the queue. - The checkpoint is the last
seqdelivered. It only advances after your endpoint accepts a batch, so delivery is at least once. - Receivers must deduplicate on
id. A retried or replayed batch can repeat events. - On failure the destination shows
status: "failing",last_error, growinglag, and the recent deliveries; it retries after 60 seconds.
The destination view: { id, name, type, url, has_secret, redaction, scope, status, checkpoint, lag, last_error, recent_deliveries[], created_at }.
Test and replay
POST /v1/siem/{id}/testsends one event of type siem.test (with seq: 0, redaction applied) and answers { ok, detail }. It does not move the checkpoint.
POST /v1/siem/{id}/replay
content-type: application/json
{ "from_seq": 18000 }rewinds the checkpoint to from_seq - 1 (it never moves the checkpoint forward), queues a flush and answers { queued, checkpoint }, where queued counts the in-scope events from there on. The replay request itself is audited (siem.replay_requested). Because receivers deduplicate on id, replaying an overlapping range never double-counts an event. See the SIEM recovery runbook.