Skip to content

Node.js SDK

The official TypeScript SDK for SealTrail. Zero dependencies, full type safety, works everywhere.

Installation

terminal
npm install sealtrail

Also works with yarn, pnpm, and bun:

terminal
yarn add sealtrail
pnpm add sealtrail
bun add sealtrail

Quick start

app.ts
import { SealTrail } from "sealtrail";

const st = new SealTrail({ apiKey: "stl_live_..." });

// Log an event
const event = await st.events.log({
  actor: "user_123",
  action: "document.signed",
  resource: "doc_456",
  context: { ip: "203.0.113.42" },
});
console.log(event.id);   // "evt_..."
console.log(event.hash); // "sha256:..."

// Verify integrity
const result = await st.events.verify(event.id);
console.log(result.valid);       // true
console.log(result.chainIntact); // true

Configuration

The SealTrail constructor accepts the following options:

Option Type Default Description
apiKey string Required. Your API key (stl_live_... or stl_test_...)
baseUrl string https://api.sealtrail.dev API base URL
timeout number 30000 Request timeout in milliseconds
maxRetries number 3 Max retry attempts on 429/5xx/409 errors
debug boolean false Log requests to console.debug
fetch typeof fetch globalThis.fetch Custom fetch for edge runtimes

Resources

Events

All event operations are available on st.events.

Log an event

sdk.ts
const event = await st.events.log({
  actor: "user_123",
  action: "invoice.approved",
  resource: "inv_456",
  context: { ip: "192.168.1.1", amount: 1500 },
  chain: "billing", // optional — defaults to "default"
});

List events with filters

sdk.ts
const { data, nextCursor } = await st.events.list({
  actor: "user_123",
  action: "invoice.approved",
  after: "2026-03-01T00:00:00Z",
  limit: 50,
});

// Manual pagination
if (nextCursor) {
  const page2 = await st.events.list({ cursor: nextCursor });
}

Auto-pagination

Use listAutoPaginate() to iterate over all events without managing cursors. It returns an AsyncIterable that fetches pages on demand.

sdk.ts
for await (const event of st.events.listAutoPaginate({ actor: "user_123" })) {
  console.log(event.action, event.timestamp);
}
Auto-pagination respects the limit parameter as page size but iterates through all matching events. It's ideal for exports and batch processing.

Get a single event

sdk.ts
const event = await st.events.get("evt_abc123");

Verify event integrity

sdk.ts
const result = await st.events.verify("evt_abc123");

if (result.valid) {
  console.log("Event integrity confirmed");
} else {
  console.error("Tamper detected:", result.errors);
}

Chains

Hash chain operations are available on st.chains.

List chains

sdk.ts
const chains = await st.chains.list();
for (const chain of chains) {
  console.log(`${chain.name}: ${chain.eventCount} events`);
}

Get chain status

sdk.ts
const chain = await st.chains.status("chn_abc123");
console.log(chain.lastHash);
console.log(chain.lastPosition);

Error handling

The SDK throws typed errors that map to HTTP status codes. All errors extend SealTrailError.

sdk.ts
import {
  SealTrail,
  SealTrailError,
  ValidationError,
  RateLimitError,
  QuotaExceededError,
  NotFoundError,
} from "sealtrail";

try {
  await st.events.log({ actor: "", action: "" });
} catch (err) {
  if (err instanceof ValidationError) {
    console.error("Invalid input:", err.message);
    console.error("Details:", err.details); // field-level errors
  } else if (err instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${err.retryAfter}s`);
  } else if (err instanceof QuotaExceededError) {
    console.error("Monthly quota exceeded — upgrade your plan");
  } else if (err instanceof NotFoundError) {
    console.error("Resource not found");
  } else if (err instanceof SealTrailError) {
    console.error(`API error [${err.code}]: ${err.message}`);
  }
}
The SDK automatically retries on 429 (rate limit), 409 (conflict), and 5xx errors with exponential backoff. QuotaExceededError (429) is not retried since it requires a plan upgrade.

Error classes

Class HTTP When
ValidationError 400 Invalid request body or query params
AuthenticationError 401 Missing or invalid API key
ForbiddenError 403 Insufficient permissions
NotFoundError 404 Resource does not exist
ConflictError 409 Chain write conflict (auto-retried)
RateLimitError 429 Too many requests (auto-retried)
QuotaExceededError 429 Monthly event quota exceeded (not retried)
InternalError 500 Server error (auto-retried)

Supported runtimes

The SDK works in any JavaScript runtime with fetch support:

  • Node.js 18+ (native fetch)
  • Bun
  • Deno
  • Cloudflare Workers / Vercel Edge / other edge runtimes
For runtimes without native fetch, pass a custom implementation via the fetch config option (e.g. node-fetch or undici).

TypeScript

The SDK ships with full TypeScript declarations. All request params and response types are exported:

types.ts
import type {
  SealTrailConfig,
  LogEventParams,
  ListEventsParams,
  AuditEvent,
  VerifyResult,
  Chain,
  EventListResponse,
} from "sealtrail";