Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.getimmutable.dev/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Log streams fan out your audit events to external destinations as they are ingested. Immutable supports two destination types: HTTPS webhooks and S3-compatible storage. Log streams are quota-gated, not plan-gated — every plan can use them.

Destination Types

HTTPS Webhook

Events are POSTed to your endpoint as JSON with HMAC signature verification.

S3 Storage

Events are written to your S3-compatible bucket (AWS S3, Cloudflare R2, MinIO, etc.).

HTTPS Webhooks

Payload Format

Each event is sent as a POST request with:
  • Content-Type: application/json
  • X-Immutable-Signature: sha256={hmac_hash}
{
  "event_type": "event.created",
  "data": {
    "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
    "actor_id": "user_2hG9kLm",
    "action": "document.created",
    "resource_id": "doc_8nXpQr3"
  },
  "workspace_id": "ws_1a2b3c4d",
  "timestamp": "2026-03-26T10:15:00.000000Z"
}

Verifying Signatures

import { createHmac, timingSafeEqual } from "crypto";

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = "sha256=" + createHmac("sha256", secret).update(payload).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

// In your webhook handler
const payload = req.body; // raw string body
const signature = req.headers["x-immutable-signature"];
if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
  return res.status(401).send("Invalid signature");
}

Failure Handling

If your endpoint returns a non-2xx status code, Immutable retries with exponential backoff. After 3 consecutive failures, the stream is automatically moved to an error state and stops delivering events. Re-enable the stream from the dashboard after resolving the issue.

S3 Storage

Configure a stream with your S3-compatible credentials:
FieldDescription
BucketTarget bucket name
RegionBucket region (e.g. us-east-1)
Access Key IDYour storage access key
Secret Access KeyYour storage secret key
EndpointCustom endpoint for non-AWS providers (e.g. Cloudflare R2)
PrefixOptional path prefix for objects
Immutable uses Laravel’s Storage::build() to connect to your bucket at runtime with your credentials. Credentials are encrypted at rest.

Cached Fanout

Log stream delivery uses cached configuration to minimize database lookups during high-throughput ingestion. Stream configuration is cached and refreshed periodically.

Plan Quotas

PlanStream Limit
Free1
Starter3
Pro10
EnterpriseUnlimited