DataZoom

SDK reference

SDK reference

Last updated 5/24/2026

DataZoom SDK Reference

Version: 1.0.0-beta
Base URL: https://your-instance.datazoom.com
Framework: Next.js 15 App Router
Auth Provider: Clerk (multi-tenant, organization-scoped)


Table of Contents

  1. Installation
  2. Authentication Setup
  3. Client Initialization
  4. TypeScript Type Definitions
  5. Method Reference
  6. Pagination Patterns
  7. Rate Limiting
  8. Error Handling

Installation

DataZoom does not yet publish a standalone SDK package. Integrate directly against the API using the typed client below. Copy datazoom-client.ts into your project.

# Required peer dependencies
npm install @clerk/nextjs @supabase/supabase-js

# Optional: Zod for runtime validation of API responses
npm install zod

For server-side usage in Node.js or non-Next.js environments:

npm install @clerk/backend node-fetch

Authentication Setup

DataZoom uses Clerk for multi-tenant authentication. Every API request must carry a valid Clerk session token scoped to an organization. Unauthenticated requests return 401. Requests from users without an active organization context return 403.

Client-Side (Browser / React)

import { useAuth } from "@clerk/nextjs";

function useDataZoomToken(): () => Promise<string | null> {
  const { getToken } = useAuth();
  return () => getToken(); // returns a short-lived JWT
}

Server-Side (Next.js Route Handler / Server Action)

import { auth } from "@clerk/nextjs/server";

export async function GET(request: Request) {
  const { userId, orgId } = await auth();
  if (!userId || !orgId) {
    return new Response("Unauthorized", { status: 401 });
  }
  // proceed with orgId-scoped database queries
}

Clerk Proxy

All Clerk telemetry and token refresh traffic is routed through the internal proxy at /api/clerk/proxy (product/app/api/clerk/proxy/route.ts) to avoid CORS issues and keep Clerk domain configuration minimal. Do not call Clerk's CDN endpoints directly from your embedded integration.


Client Initialization

// datazoom-client.ts

export interface DataZoomConfig {
  /** Base URL of your DataZoom deployment, no trailing slash */
  baseUrl: string;
  /** Async function that returns a valid Clerk JWT */
  getToken: () => Promise<string | null>;
  /** Default organization ID; overridable per-request */
  organizationId?: string;
  /** Fetch timeout in milliseconds (default: 30000) */
  timeoutMs?: number;
}

export class DataZoomClient {
  private config: Required<DataZoomConfig>;

  constructor(config: DataZoomConfig) {
    this.config = {
      organizationId: "",
      timeoutMs: 30_000,
      ...config,
    };
  }

  async request<T>(
    path: string,
    options: RequestInit & { params?: Record<string, string> } = {}
  ): Promise<T> {
    const token = await this.config.getToken();
    if (!token) throw new DataZoomAuthError("No Clerk session token available");

    const url = new URL(`${this.config.baseUrl}${path}`);
    if (options.params) {
      Object.entries(options.params).forEach(([k, v]) =>
        url.searchParams.set(k, v)
      );
    }

    const controller = new AbortController();
    const timer = setTimeout(
      () => controller.abort(),
      this.config.timeoutMs
    );

    let response: Response;
    try {
      response = await fetch(url.toString(), {
        ...options,
        signal: controller.signal,
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
          ...(this.config.organizationId && {
            "X-Organization-Id": this.config.organizationId,
          }),
          ...options.headers,
        },
      });
    } finally {
      clearTimeout(timer);
    }

    if (!response.ok) {
      await DataZoomClient.throwApiError(response);
    }

    return response.json() as Promise<T>;
  }

  private static async throwApiError(response: Response): Promise<never> {
    let body: unknown;
    try {
      body = await response.json();
    } catch {
      body = await response.text();
    }
    switch (response.status) {
      case 401:
        throw new DataZoomAuthError("Authentication failed", body);
      case 403:
        throw new DataZoomForbiddenError("Insufficient permissions", body);
      case 404:
        throw new DataZoomNotFoundError("Resource not found", body);
      case 429:
        throw new DataZoomRateLimitError("Rate limit exceeded", body);
      default:
        throw new DataZoomApiError(
          `API error ${response.status}`,
          response.status,
          body
        );
    }
  }
}

Initialization Example

import { DataZoomClient } from "./datazoom-client";
import { useAuth } from "@clerk/nextjs";

// React hook usage
function useDataZoom() {
  const { getToken, orgId } = useAuth();
  return new DataZoomClient({
    baseUrl: process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000",
    getToken,
    organizationId: orgId ?? undefined,
  });
}

// Server-side / Node.js usage
import { createClerkClient } from "@clerk/backend";

const clerk = createClerkClient({
  secretKey: process.env.CLERK_SECRET_KEY,
});

const client = new DataZoomClient({
  baseUrl: "https://your-instance.datazoom.com",
  getToken: async () => {
    const token = await clerk.sessions.getToken(
      process.env.SESSION_ID!,
      "datazoom"
    );
    return token.jwt;
  },
  organizationId: "org_yourOrgId",
});

TypeScript Type Definitions

// ─── Shared Primitives ───────────────────────────────────────────────────────

export type UUID = string;
export type ISODateString = string; // "2024-01-15"
export type ISOTimestamp = string;  // "2024-01-15T10:30:00.000Z"

export type ImpactLevel = "critical" | "high" | "medium" | "low";
export type DocumentType =
  | "equity"
  | "ip_assignment"
  | "financial"
  | "healthcare"
  | "agreement";

export type EventType =
  | "equity_change"
  | "agreement_signed"
  | "ip_assignment"
  | string;

// ─── Error Classes ────────────────────────────────────────────────────────────

export class DataZoomApiError extends Error {
  constructor(
    message: string,
    public statusCode: number,
    public body?: unknown
  ) {
    super(message);
    this.name = "DataZoomApiError";
  }
}
export class DataZoomAuthError extends DataZoomApiError {
  constructor(message: string, body?: unknown) {
    super(message, 401, body);
    this.name = "DataZoomAuthError";
  }
}
export class DataZoomForbiddenError extends DataZoomApiError {
  constructor(message: string, body?: unknown) {
    super(message, 403, body);
    this.name = "DataZoomForbiddenError";
  }
}
export class DataZoomNotFoundError extends DataZoomApiError {
  constructor(message: string, body?: unknown) {
    super(message, 404, body);
    this.name = "DataZoomNotFoundError";
  }
}
export class DataZoomRateLimitError extends DataZoomApiError {
  constructor(message: string, body?: unknown) {
    super(message, 429, body);
    this.name = "DataZoomRateLimitError";
  }
}

// ─── Pagination ───────────────────────────────────────────────────────────────

export interface PaginatedResponse<T> {
  data: T[];
  total: number;
  page: number;
  pageSize: number;
  hasNextPage: boolean;
}

export interface PaginationParams {
  page?: number;
  pageSize?: number;
}

// ─── Activity ─────────────────────────────────────────────────────────────────

export type ActivityEventType =
  | "document_upload"
  | "document_delete"
  | "document_process"
  | "risk_analysis"
  | "strategic_analysis"
  | "query"
  | string;

export interface ActivityEvent {
  id: UUID;
  orgId: string;
  userId: string;
  eventType: ActivityEventType;
  resourceType: string;
  resourceId: UUID;
  resourceName: string;
  metadata: Record<string, unknown>;
  createdAt: ISOTimestamp;
}

export interface ActivityMetrics {
  totalEvents: number;
  documentUploads: number;
  documentsDeleted: number;
  queriesRun: number;
  analysesRun: number;
  activeUsers: number;
  periodStart: ISOTimestamp;
  periodEnd: ISOTimestamp;
}

export interface UnifiedCalendarDay {
  date: ISODateString;
  events: ActivityEvent[];
  count: number;
}

export interface UnifiedCalendarResponse {
  month: number;
  year: number;
  days: UnifiedCalendarDay[];
}

export interface UnifiedFeedResponse extends PaginatedResponse<ActivityEvent> {}

export interface ExportActivityParams {
  startDate?: ISODateString;
  endDate?: ISODateString;
  eventTypes?: ActivityEventType[];
  format?: "json" | "csv";
}

// ─── Admin Pipeline ───────────────────────────────────────────────────────────

export type PipelineStatus =
  | "idle"
  | "queued"
  | "processing"
  | "completed"
  | "failed";

export interface PipelineJob {
  id: UUID;
  documentId: UUID;
  documentName: string;
  status: PipelineStatus;
  stage: string;
  attempt: number;
  error?: string;
  createdAt: ISOTimestamp;
  updatedAt: ISOTimestamp;
}

export interface PipelineHealthResponse {
  status: "healthy" | "degraded" | "down";
  queueDepth: number;
  activeWorkers: number;
  failedLast24h: number;
  avgProcessingMs: number;
  cloudStatus: "provisioning" | "warming" | "ready" | "unavailable";
}

export interface PipelineRoutingStats {
  localJobs: number;
  cloudJobs: number;
  failoverCount: number;
  avgCloudLatencyMs: number;
}

export interface RetryPipelineRequest {
  jobIds: UUID[];
}

export interface RetryPipelineResponse {
  queued: UUID[];
  failed: UUID[];
}

// ─── Advisor ─────────────────────────────────────────────────────────────────

export interface AdvisorQuery {
  question: string;
  documentIds?: UUID[];
  threadId?: UUID;
}

export interface AdvisorResponse {
  answer: string;
  citations: Citation[];
  threadId: UUID;
  messageId: UUID;
  tokensUsed: number;
  modelUsed: string;
}

export interface Citation {
  documentId: UUID;
  documentName: string;
  chunkIndex: number;
  excerpt: string;
  relevanceScore: number;
}

export interface RiskMemoRequest {
  documentIds: UUID[];
  focus?: string;
}

export interface RiskMemoResponse {
  memo: string;
  riskItems: RiskItem[];
  generatedAt: ISOTimestamp;
}

export interface RiskItem {
  category: string;
  severity: ImpactLevel;
  description: string;
  documentRef?: UUID;
}

export interface StrategicOptionsRequest {
  context: string;
  documentIds?: UUID[];
  constraints?: string[];
}

export interface StrategicOptionsResponse {
  options: StrategicOption[];
  summary: string;
  generatedAt: ISOTimestamp;
}

export interface StrategicOption {
  title: string;
  description: string;
  pros: string[];
  cons: string[];
  feasibility: "high" | "medium" | "low";
}

export interface BatchAdvisorRequest {
  queries: AdvisorQuery[];
}

export interface BatchAdvisorResponse {
  results: Array<{ query: AdvisorQuery; response: AdvisorResponse }>;
}

// ─── Analysis ─────────────────────────────────────────────────────────────────

export interface PartyAnalysisRequest {
  partyName: string;
  documentIds?: UUID[];
}

export interface PartyAnalysisResponse {
  party: string;
  appearances: PartyAppearance[];
  summary: string;
  relatedParties: string[];
}

export interface PartyAppearance {
  documentId: UUID;
  documentName: string;
  role: string;
  sections: string[];
}

export interface RegenerateAnalysisRequest {
  documentId: UUID;
  analysisType: "summary" | "timeline" | "risk" | "parties";
}

export interface RegenerateAnalysisResponse {
  documentId: UUID;
  analysisType: string;
  result: Record<string, unknown>;
  regeneratedAt: ISOTimestamp;
}

// ─── Business Types ───────────────────────────────────────────────────────────

export interface BusinessType {
  key: string;
  label: string;
  description: string;
  documentCategories: string[];
}

export interface BusinessTypeProfile {
  profileKey: string;
  businessTypeKey: string;
  name: string;
  description: string;
  checklistTemplate: ChecklistTemplate;
  riskWeights: Record<string, number>;
}

export interface ChecklistTemplate {
  id: UUID;
  name: string;
  items: ChecklistItem[];
}

export interface ChecklistItem {
  id: UUID;
  category: string;
  requirement: string;
  priority: ImpactLevel;
  documentTypes: DocumentType[];
  completed: boolean;
  notes?: string;
}

// ─── Cap Table ────────────────────────────────────────────────────────────────

export interface CapTableSnapshot {
  asOf: ISOTimestamp;
  totalShares: number;
  holders: ShareHolder[];
  shareClasses: ShareClass[];
  fullyDilutedShares: number;
}

export interface ShareHolder {
  id: UUID;
  name: string;
  type: "individual" | "entity";
  shares: number;
  shareClass: string;
  percentage: number;
  options: number;
  warrants: number;
}

export interface ShareClass {
  name: string;
  authorized: number;
  issued: number;
  liquidationPreference?: number;
  isPreferred: boolean;
}

export interface CapTableTransaction {
  id: UUID;
  type:
    | "issuance"
    | "transfer"
    | "cancellation"
    | "exercise"
    | "conversion"
    | "repurchase";
  date: ISODateString;
  shares: number;
  pricePerShare?: number;
  fromHolder?: string;
  toHolder: string;
  shareClass: string;
  documentId?: UUID;
  status: "pending" | "approved" | "rejected" | "void";
  notes?: string;
}

export interface CreateTransactionRequest {
  type: CapTableTransaction["type"];
  date: ISODateString;
  shares: number;
  pricePerShare?: number;
  fromHolder?: string;
  toHolder: string;
  shareClass: string;
  documentId?: UUID;
  notes?: string;
}

export interface CapTableReviewItem {
  id: UUID;
  transaction: CapTableTransaction;
  extractedFrom: UUID;
  confidence: number;
  flags: string[];
  reviewedBy?: string;
  reviewedAt?: ISOTimestamp;
}

export interface ExtractCapTableRequest {
  documentId: UUID;
}

export interface ExtractCapTableResponse {
  jobId: UUID;
  status: "queued" | "processing";
  estimatedMs: number;
}

export interface CapTableHealthResponse {
  status: "healthy" | "degraded";
  totalHolders: number;
  totalTransactions: number;
  pendingReview: number;
  lastRecalculatedAt: ISOTimestamp;
}

// ─── Clauses ─────────────────────────────────────────────────────────────────

export interface ClauseCompareRequest {
  clauseText: string;
  documentIds?: UUID[];
  clauseType?: string;
}

export interface ClauseCompareResponse {
  matches: ClauseMatch[];
  summary: string;
}

export interface ClauseMatch {
  documentId: UUID;
  documentName: string;
  matchedClause: string;
  similarityScore: number;
  differences: string[];
}

// ─── Collaboration ────────────────────────────────────────────────────────────

export interface CollaborationTokenRequest {
  documentId: UUID;
  permissions?: ("read" | "comment" | "edit")[];
}

export interface CollaborationTokenResponse {
  token: string;
  wsUrl: string;
  expiresAt: ISOTimestamp;
}

// ─── Company Settings ─────────────────────────────────────────────────────────

export interface CompanySettings {
  orgId: string;
  companyName: string;
  businessType?: string;
  incorporationState?: string;
  foundedDate?: ISODateString;
  employeeCount?: number;
  linkedDocumentIds: UUID[];
  updatedAt: ISOTimestamp;
}

export interface UpdateCompanySettingsRequest {
  companyName?: string;
  businessType?: string;
  incorporationState?: string;
  foundedDate?: ISODateString;
  employeeCount?: number;
}

export interface LinkageMismatch {
  field: string;
  settingsValue: string;
  documentValue: string;
  documentId: UUID;
  documentName: string;
  severity: ImpactLevel;
}

export interface LinkageMismatchesResponse {
  mismatches: LinkageMismatch[];
  totalChecked: number;
  lastCheckedAt: ISOTimestamp;
}

// ─── AI Tracking ─────────────────────────────────────────────────────────────

export interface TrackAIInteractionRequest {
  interactionType: string;
  modelUsed: string;
  promptTokens: number;
  completionTokens: number;
  latencyMs: number;
  success: boolean;
  documentIds?: UUID[];
  metadata?: Record<string, unknown>;
}

export interface TrackAIInteractionResponse {
  tracked: boolean;
  interactionId: UUID;
}

Method Reference

All methods are presented as static typed functions that call DataZoomClient.request. Import and bind them to your initialized client.


Activity API

Routes implemented in product/app/api/activity/.


getActivityFeed

Retrieves a paginated stream of activity events for the authenticated organization.

Signature

async function getActivityFeed(
  client: DataZoomClient,
  params?: PaginationParams & {
    eventTypes?: ActivityEventType[];
    userId?: string;
    startDate?: ISODateString;
    endDate?: ISODateString;
  }
): Promise<UnifiedFeedResponse>

Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number, 1-indexed. Default: 1
pageSizenumberNoRecords per page, max 100. Default: 25
eventTypesActivityEventType[]NoFilter to specific event types
userIdstringNoFilter to a specific Clerk user ID
startDateISODateStringNoISO date lower bound (inclusive)
endDateISODateStringNoISO date upper bound (inclusive)

Returns: Promise<UnifiedFeedResponse>

Example

const feed = await getActivityFeed(client, {
  page: 1,
  pageSize: 50,
  eventTypes: ["document_upload", "risk_analysis"],
  startDate: "2024-01-01",
});

console.log(`${feed.total} total events`);
feed.data.forEach((event) => {
  console.log(`[${event.eventType}] ${event.resourceName} at ${event.createdAt}`);
});

Error handling

try {
  const feed = await getActivityFeed(client);
} catch (err) {
  if (err instanceof DataZoomAuthError) {
    // Redirect to sign-in
  }
  if (err instanceof DataZoomApiError) {
    console.error(`API error ${err.statusCode}:`, err.body);
  }
}

getActivityMetrics

Returns aggregate metrics for the organization over a time window.

Signature

async function getActivityMetrics(
  client: DataZoomClient,
  params?: {
    startDate?: ISODateString;
    endDate?: ISODateString;
  }
): Promise<ActivityMetrics>

Parameters

ParameterTypeRequiredDescription
startDateISODateStringNoMetrics window start (inclusive)
endDateISODateStringNoMetrics window end (inclusive)

Returns: Promise<ActivityMetrics>

Example

const metrics = await getActivityMetrics(client, {
  startDate: "2024-01-01",
  endDate: "2024-01-31",
});

console.log(`${metrics.documentUploads} uploads, ${metrics.queriesRun} queries`);

exportActivity

Exports activity data as JSON or CSV. Returns raw text for CSV or a JSON array for JSON.

Signature

async function exportActivity(
  client: DataZoomClient,
  params?: ExportActivityParams
): Promise<ActivityEvent[] | string>

Parameters

ParameterTypeRequiredDescription
startDateISODateStringNoExport window start
endDateISODateStringNoExport window end
eventTypesActivityEventType[]NoFilter to specific event types
format"json" | "csv"NoOutput format. Default: "json"

Returns: Promise<ActivityEvent[] | string>

Example

// Export last 30 days as CSV
const csv = await exportActivity(client, {
  startDate: "2024-01-01",
  endDate: "2024-01-31",
  format: "csv",
});

const blob = new Blob([csv as string], { type: "text/csv" });
const url = URL.createObjectURL(blob);

getUnifiedCalendar

Returns a month-view calendar with activity events grouped by day.

Signature

async function getUnifiedCalendar(
  client: DataZoomClient,
  params: { year: number; month: number }
): Promise<UnifiedCalendarResponse>

Parameters

ParameterTypeRequiredDescription
yearnumberYesFour-digit year, e.g. 2024
monthnumberYesMonth number, 1–12

Returns: Promise<UnifiedCalendarResponse>

Example

const calendar = await getUnifiedCalendar(client, { year: 2024, month: 1 });

calendar.days.forEach((day) => {
  if (day.count > 0) {
    console.log(`${day.date}: ${day.count} events`);
  }
});

getUnifiedDayActivity

Returns all activity events for a specific calendar day.

Signature

async function getUnifiedDayActivity(
  client: DataZoomClient,
  params: { year: number; month: number; day: number }
): Promise<ActivityEvent[]>

Parameters

ParameterTypeRequiredDescription
yearnumberYesFour-digit year
monthnumberYesMonth 1–12
daynumberYesDay 1–31

Returns: Promise<ActivityEvent[]>

Example

const events = await getUnifiedDayActivity(client, {
  year: 2024,
  month: 1,
  day: 15,
});

refreshUnifiedActivity

Triggers a background refresh of the unified activity materialized views.

Signature

async function refreshUnifiedActivity(
  client: DataZoomClient
): Promise<{ refreshed: boolean; triggeredAt: ISOTimestamp }>

Returns: Promise<{ refreshed: boolean; triggeredAt: ISOTimestamp }>

Example

const result = await refreshUnifiedActivity(client);
console.log(`Refresh triggered at ${result.triggeredAt}`);

Admin Pipeline API

Routes implemented in product/app/api/admin/pipeline/. These endpoints require admin-level organization permissions.


getPipelineJobs

Lists document processing pipeline jobs with optional status filtering.

Signature

async function getPipelineJobs(
  client: DataZoomClient,
  params?: PaginationParams & { status?: PipelineStatus }
): Promise<PaginatedResponse<PipelineJob>>

Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number. Default: 1
pageSizenumberNoRecords per page. Default: 25
statusPipelineStatusNoFilter by job status

Returns: Promise<PaginatedResponse<PipelineJob>>

Example

const failedJobs = await getPipelineJobs(client, {
  status: "failed",
  pageSize: 50,
});

console.log(`${failedJobs.total} failed jobs`);

getPipelineHealth

Returns the current health status of the document processing pipeline, including cloud worker pod state.

Signature

async function getPipelineHealth(
  client: DataZoomClient
): Promise<PipelineHealthResponse>

Returns: Promise<PipelineHealthResponse>

Example

const health = await getPipelineHealth(client);

if (health.status !== "healthy") {
  console.warn(`Pipeline degraded. Cloud status: ${health.cloudStatus}`);
  console.warn(`Queue depth: ${health.queueDepth}`);
}

retryPipelineJobs

Re-queues one or more failed pipeline jobs.

Signature

async function retryPipelineJobs(
  client: DataZoomClient,
  body: RetryPipelineRequest
): Promise<RetryPipelineResponse>

Parameters

ParameterTypeRequiredDescription
jobIdsUUID[]YesArray of pipeline job IDs to retry

Returns: Promise<RetryPipelineResponse>

Example

const result = await retryPipelineJobs(client, {
  jobIds: ["job-uuid-1", "job-uuid-2"],
});

console.log(`Queued: ${result.queued.length}, could not retry: ${result.failed.length}`);

getCloudPipelineStatus

Returns the current RunPod cloud worker fleet status as tracked by the orchestrator.

Signature

async function getCloudPipelineStatus(
  client: DataZoomClient
): Promise<{ cloudStatus: string; pods: unknown[]; lastUpdatedAt: ISOTimestamp }>

Returns: Promise<{ cloudStatus: string; pods: unknown[]; lastUpdatedAt: ISOTimestamp }>

Example

const cloud = await getCloudPipelineStatus(client);
console.log(`Cloud fleet: ${cloud.cloudStatus}`);

getRoutingStats

Returns statistics on local vs. cloud job routing decisions made by the model router.

Signature

async function getRoutingStats(
  client: DataZoomClient
): Promise<PipelineRoutingStats>

Returns: Promise<PipelineRoutingStats>

Example

const stats = await getRoutingStats(client);
console.log(
  `Local: ${stats.localJobs}, Cloud: ${stats.cloudJobs}, Failovers: ${stats.failoverCount}`
);

Advisor API

Routes implemented in product/app/api/advisor/. The advisor uses RAG over your organization's documents to answer questions and generate strategic analysis.


queryAdvisor

Sends a natural language question to the AI advisor. Uses RAG over embedded document chunks with pgvector similarity search.

Signature

async function queryAdvisor(
  client: DataZoomClient,
  body: AdvisorQuery
): Promise<AdvisorResponse>

Parameters

ParameterTypeRequiredDescription
questionstringYesNatural language question
documentIdsUUID[]NoScope retrieval to specific documents
threadIdUUIDNoContinue an existing conversation thread

Returns: Promise<AdvisorResponse>

Example

const response = await queryAdvisor(client, {
  question: "What are the vesting cliff dates across all equity agreements?",
  documentIds: ["doc-uuid-1", "doc-uuid-2"],
});

console.log(response.answer);
response.citations.forEach((c) => {
  console.log(`Source: ${c.documentName} (score: ${c.relevanceScore.toFixed(2)})`