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.
Installation
Requirements: Node.js 18+ (uses native fetch)
Setup
import { ImmutableClient } from "getimmutable";
const client = new ImmutableClient({
apiKey: "imk_your_api_key_here",
baseUrl: "https://getimmutable.dev",
// timeout: 30000, // optional, in milliseconds
});
| Option | Type | Required | Description |
|---|
apiKey | string | Yes | Your imk_ prefixed API key |
baseUrl | string | Yes | Base domain (SDK appends /api/v1/...) |
timeout | number | No | Request timeout in milliseconds |
Tracking Events
Direct Tracking
const result = await client.track({
actor_id: "user_2hG9kLm",
actor_name: "Sarah Chen",
actor_type: "user",
action: "document.created",
action_category: "documents",
resource_id: "doc_8nXpQr3",
resource_name: "Q4 Financial Report",
resource: "document",
metadata: { folder: "reports", template: "quarterly" },
targets: [
{ type: "folder", id: "folder_3mK9pLq", name: "Shared Reports" },
],
session_id: "sess_4kN8pLm",
tenant_id: "org_7rT2xBc",
idempotency_key: "unique_key_123",
});
console.log(result.id); // "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
console.log(result.status); // "queued"
Fluent Builder
The PendingEvent class provides a chainable API:
import { ImmutableClient, PendingEvent } from "getimmutable";
const client = new ImmutableClient({
apiKey: "imk_your_api_key_here",
baseUrl: "https://getimmutable.dev",
});
const event = new PendingEvent(client, {
id: "user_2hG9kLm",
name: "Sarah Chen",
type: "user",
});
const result = await event
.idempotencyKey("unique_key_123")
.version(1)
.session("sess_4kN8pLm")
.actionCategory("documents")
.target("folder", "folder_3mK9pLq", "Shared Reports")
.target("team", "team_5bR7cNx", "Engineering")
.track("document.created", "document", {
folder: "reports",
template: "quarterly",
});
PendingEvent Methods
| Method | Parameters | Description |
|---|
idempotencyKey(key) | string | Set deduplication key |
version(v) | number | Set event schema version |
session(id) | string | Set session identifier |
actionCategory(cat) | string | Set action category |
target(type, id?, name?, metadata?) | string, string?, string?, object? | Add a single target |
targets(arr) | array | Set all targets at once |
track(action, resource?, metadata?) | string, string?, object? | Send the event |
Batch Ingestion
Send up to 100 events in a single request:
const results = await client.trackBatch([
{
actor_id: "user_2hG9kLm",
actor_name: "Sarah Chen",
action: "document.created",
resource_id: "doc_8nXpQr3",
resource_name: "Q4 Financial Report",
},
{
actor_id: "user_2hG9kLm",
actor_name: "Sarah Chen",
action: "document.shared",
resource_id: "doc_8nXpQr3",
targets: [
{ type: "team", id: "team_5bR7cNx", name: "Engineering" },
],
},
]);
// results.events = [{ id: "...", status: "queued" }, ...]
Querying Events
const response = await client.getEvents({
actor_id: "user_2hG9kLm",
action: "document.*",
from: "2026-03-01T00:00:00Z",
to: "2026-03-31T23:59:59Z",
limit: 25,
});
console.log(response.data); // Event[]
console.log(response.pagination.has_more); // boolean
console.log(response.pagination.total); // number
// Cursor pagination
if (response.pagination.has_more) {
const nextPage = await client.getEvents({
cursor: response.pagination.next_cursor,
});
}
Retrieving a Single Event
const event = await client.getEvent("9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d");
console.log(event.actor.id); // "user_2hG9kLm"
console.log(event.integrity.event_hash); // "a3f2c8d1..."
console.log(event.integrity.previous_event_hash); // "7b9e1d3f..."
Verification
const result = await client.verify();
console.log(result.data.valid); // true
console.log(result.data.events_checked); // 4821
// With date range
const ranged = await client.verify(
"2026-03-01T00:00:00Z",
"2026-03-31T23:59:59Z"
);
// With a custom limit (default: 10000)
const limited = await client.verify(undefined, undefined, 1000);
Viewer Tokens
const token = await client.createViewerToken({
tenantId: "org_7rT2xBc",
actorId: "user_2hG9kLm",
ttl: 7200, // 2 hours (min 60, max 86400, default 3600)
});
console.log(token.token); // "eyJhbGciOiJIUzI1NiIs..."
console.log(token.expires_at); // 1774540500 (Unix timestamp)
Alerts
const alerts = await client.getAlerts({
rule_type: "new_country",
limit: 25,
});
Exports
// Create export
const exp = await client.createExport({
actor_id: "user_2hG9kLm",
from: "2026-03-01T00:00:00Z",
});
// Check status
const status = await client.getExport(exp.data.id);
console.log(status.data.status); // "pending" | "processing" | "completed" | "failed"
Anchors
// List blockchain anchors
const anchors = await client.getAnchors(10);
for (const anchor of anchors.data) {
console.log(`${anchor.merkle_root} — ${anchor.status} — ${anchor.explorer_url}`);
}
// Get anchor details
const anchor = await client.getAnchor("anchor-uuid");
console.log(anchor.data.first_event_hash);
console.log(anchor.data.last_event_hash);
// Verify anchor integrity
const result = await client.verifyAnchor("anchor-uuid");
console.log(result.data.valid); // Merkle root matches events
console.log(result.data.chain_valid); // Anchor chain is intact
Error Handling
The SDK throws ImmutableError for API failures:
import { ImmutableClient } from "getimmutable";
try {
await client.track({ action: "document.created" }); // missing actor_id
} catch (error) {
if (error instanceof Error) {
console.error(error.message); // "The actor_id field is required."
}
}
TypeScript Support
The SDK is written in TypeScript with strict mode. All request payloads and response types are fully typed.
import type { Event, TrackPayload, PaginatedResponse } from "getimmutable";