Skip to content

Push Capsule detections, findings, and policy violations to any OpenTelemetry (OTLP) logs endpoint: your own OpenTelemetry Collector, or an observability or SIEM backend that accepts OTLP directly. Put a Collector in front to route events anywhere it can export.

Overview

Capsule sends each event as an OTLP log record as it is produced, over OTLP/HTTP with JSON encoding, gzip-compressed.

Event typeWhat gets exported
DetectionsReal-time detections raised on agent activity, with full event context
FindingsPosture and configuration findings across your AI inventory
Policy violationsGuardrail and policy breaches, with the full evidence the decision was made on
Capsule event (detection / finding / policy violation)
  → OTLP log record, body = the full Capsule event envelope
  → POST <endpoint>/v1/logs, gzipped JSON, with your headers
  → your OpenTelemetry Collector or OTLP-compatible backend

This is separate from Settings → Notifications. Notifications push individual alerts to a channel; the SIEM integration streams the full, verbose event record for ingestion and long-term correlation.

OTLP/HTTP JSON only. Protobuf encoding and OTLP/gRPC are not supported. An endpoint that only accepts protobuf answers with HTTP 415. Put a Collector in front of it: the Collector receives JSON and re-exports in whatever protocol the backend needs.

Prerequisites

  • A Capsule account with admin access, and the SIEM tab visible under Settings
  • An OTLP/HTTP logs endpoint reachable from the internet over HTTPS
  • The credentials your endpoint expects, as one or more request headers

Step 1: Prepare your endpoint

Endpoint URL

Capsule accepts either shape:

  • A collector base URL, the value you would put in OTEL_EXPORTER_OTLP_ENDPOINT. Capsule appends /v1/logs. For example https://otel-collector.acme.com:4318 is posted to https://otel-collector.acme.com:4318/v1/logs.
  • The full logs URL, the value you would put in OTEL_EXPORTER_OTLP_LOGS_ENDPOINT. A URL that already ends in /v1/logs is used as is.

The endpoint must be https. Redirects are not followed, so point Capsule at the receiver itself rather than at a URL that forwards to it.

Headers

Headers are sent with every request, and are usually how the endpoint authenticates Capsule. They are write-only: Capsule stores them encrypted and never shows the values again. You can add up to 20. Content-Type, Content-Encoding, Content-Length, Host, Transfer-Encoding and Connection are set by Capsule and cannot be overridden.

DestinationEndpointHeader
OpenTelemetry Collector with bearertokenauthhttps://<your-collector>:4318Authorization: Bearer <token>
Grafana Cloud OTLPhttps://otlp-gateway-<zone>.grafana.net/otlpAuthorization: Basic <base64 of instanceId:token>
Honeycombhttps://api.honeycomb.iox-honeycomb-team: <api key>

For Grafana Cloud, the instance ID, zone, and a token with write access are on the OpenTelemetry tile of your Grafana Cloud stack. Encode the pair with echo -n '<instanceId>:<token>' | base64.

A collector that authenticates by network rather than by header, for example one behind an IP allow-list, needs no headers at all.

Example: OpenTelemetry Collector

A minimal OpenTelemetry Collector Contrib config that accepts Capsule's events with a bearer token and prints them. Replace the debug exporter with the exporter for your backend once you have seen events arrive.

extensions:
  bearertokenauth:
    token: ${env:CAPSULE_OTLP_TOKEN}

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
        auth:
          authenticator: bearertokenauth
        tls:
          cert_file: /etc/otelcol/tls/server.crt
          key_file: /etc/otelcol/tls/server.key

exporters:
  debug:
    verbosity: detailed

service:
  extensions: [bearertokenauth]
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [debug]

In Capsule, add the header Authorization with the value Bearer <the CAPSULE_OTLP_TOKEN value>. If TLS terminates at a load balancer in front of the Collector, drop the tls block and give Capsule the load balancer's https URL.

Step 2: Create the SIEM integration in Capsule

  1. In Capsule, go to Settings → SIEM and click Add integration.
  2. Set Destination to OpenTelemetry (OTLP).
  3. Enable the event types you want: Detections, Findings, Policy violations.
  4. Choose an Event detail level:
    • Full sends the whole envelope, matching the S3 and Splunk exports.
    • Compact omits activity message bodies. Use it where your backend bills by ingested volume and the transcript is not what you search on.
  5. Paste the Endpoint from Step 1.
  6. Under Headers, click Add header for each header your endpoint needs, and enter its name and value.
  7. Click Save, then enable the integration. A new integration starts disabled and exports nothing until you turn it on.

When you edit the integration later, saved header values stay hidden. Leave Headers empty to keep them. Entering any header replaces the whole saved set, so enter every header the endpoint needs, not only the one you are changing.

Step 3: Verify

Use the row menu's Send test event. Capsule posts a single connection-test log record to your endpoint and reports whether it was accepted, with the endpoint's error if it was not. The record is a capsule.detection.created event whose detection type is CAPSULE_CONNECTION_TEST, so it is easy to filter out. With the Collector example above, the record appears in the Collector's output.

The Delivery column on the SIEM list shows the outcome of the most recent attempt, and the details drawer shows the last error in full.

What arrives at your endpoint

Each request is one OTLP ExportLogsServiceRequest carrying one resource, one scope, and a batch of log records.

Log record mapping

OTLP fieldValue
Resource attribute service.namecapsule
Resource attribute capsule.tenant.idYour Capsule tenant ID
Scope name / versioncapsule.siem-export / 2, the envelope schema version
timeUnixNanoWhen the detection, finding, or policy violation was created
observedTimeUnixNanoWhen Capsule exported the event
severityNumber, severityTextPolicy violations only, see below
Attribute event.namecapsule.detection.created, capsule.finding.created, or capsule.policy_violation.created
Attribute capsule.event.idThe ID of the detection, finding, or policy violation
Attribute capsule.schema_version2
bodyThe full Capsule event envelope, as a structured map

Severity

Policy violations carry Capsule's severity. severityNumber maps it onto the OTLP severity ranges, and severityText carries Capsule's own value.

Capsule severityseverityNumberOTLP range
critical21FATAL
high17ERROR
medium13WARN
low9INFO

Capsule does not rank detections or findings, so those records have no severity fields rather than an invented one.

Body

The body is the same envelope the S3 and Splunk destinations receive, with the record under event:

{ "schemaVersion": 2, "eventType": "policy_violation.created", "tenantId": "...", "exportedAt": "...", "event": { ... } }

It is sent as a structured OTLP value rather than a JSON string, so a backend can query its fields directly. Objects become kvlistValue, arrays become arrayValue, integers become intValue, other numbers become doubleValue, and null becomes an empty value.

Every event carries its anchor resource in full - id, name, type, external id, parent, and the environment and connector it was discovered through - so events correlate against the rest of your inventory without a lookup.

  • policy_violation.created is self-contained: the violation, the policy that raised it including its conditions, and the complete finding, detection and activity records the decision was made on.
  • detection.created carries the detection, its evidence, and the session activities it was raised on.
  • finding.created carries the finding, its evidence, and its remediation steps.

Triage state is exported on all three. Secrets Capsule identified in evidence are masked to a short prefix before export, in evidence text and activity message bodies alike.

One violation, one event. A violation is exported once, when it is first raised. If it is later resolved and the same condition re-triggers, Capsule reuses the existing violation and does not emit a second policy_violation.created.

Delivery behaviour

  • Batching - records are gzipped and split so each request stays under 1 MB compressed, a limit every common OTLP backend accepts.
  • Oversized events - a single event that still exceeds the limit after compression is rejected and surfaced on the integration, never truncated. Switching Event detail to Compact is the fix.
  • Retries - Capsule retries the statuses the OTLP/HTTP specification marks retryable (429, 502, 503, 504), timeouts, and network errors, with exponential backoff, honouring Retry-After. Every other failure is a configuration error and is reported instead.
  • Timeouts - each request has 10 seconds to complete.
  • Visibility - the outcome of the most recent attempt is shown per integration in Settings → SIEM, with the full error in the details drawer.
  • Backfill - export begins when the integration is enabled. Events raised before that are not sent.

Troubleshooting

rejected the credentials in the configured headers (HTTP 401 or 403)

The endpoint did not accept the headers. Check the header name your backend expects and the value's format, for example the Bearer or Basic prefix. Saved values are hidden, so enter every header again and save.

no logs receiver at this URL (HTTP 404)

The path is wrong. Give Capsule the collector base URL and let it append /v1/logs, or the full logs URL. A base URL that already includes a different signal path, such as /v1/traces, will not work.

does not accept OTLP/HTTP JSON (HTTP 415)

The endpoint only accepts protobuf. Capsule sends JSON only. Route the events through an OpenTelemetry Collector, which accepts JSON and exports protobuf or gRPC to the backend.

accepted the request but rejected N log record(s)

The endpoint returned success but reported a partial success, dropping some records. Capsule shows this as a failed delivery with the endpoint's own message, since the dropped records were not stored. The message usually names the limit or field the backend objected to.

Timeouts or nothing arrives

  • Confirm the integration is enabled and at least one event type is turned on.
  • Use Send test event - it reports the exact error from the endpoint.
  • Confirm the endpoint is reachable from the internet over https on the port in the URL. If it sits behind an IP allow-list, Capsule's egress addresses need to be on it. Contact support for the current list.
  • A request that takes longer than 10 seconds is retried and then reported as failed. Check the endpoint's load and anything between it and the internet, such as a proxy or load balancer.

Support

For help with this integration, contact support@capsule.security.