SdkServer

API Client

TypeScript API client for REST API access

API Client

The @entrolytics/api-client package provides a comprehensive TypeScript client for accessing the Entrolytics REST API with full type safety, authentication, and rate limiting.

Installation

pnpm add @entrolytics/api-client

Quick Start

Initialize Client

import { EntrolyticsApiClient } from '@entrolytics/api-client'

const client = new EntrolyticsApiClient({
  websiteId: 'your-website-id',
  apiKey: 'your-api-key',
  host: 'https://entrolytics.dev'
})

Track Events

// Track a custom event
await client.events.track({
  event: 'signup',
  properties: {
    plan: 'pro',
    source: 'landing-page'
  }
})

// Track a page view
await client.events.page({
  url: '/dashboard',
  properties: {
    title: 'Dashboard'
  }
})

Get Analytics Data

// Get overview statistics
const overview = await client.analytics.overview({
  startDate: new Date('2025-01-01'),
  endDate: new Date('2025-01-31')
})

// Get top pages
const topPages = await client.analytics.topPages({
  startDate: new Date('2025-01-01'),
  endDate: new Date('2025-01-31'),
  limit: 10
})

Configuration

Client Options

interface EntrolyticsApiClientConfig {
  /** Website ID (required) */
  websiteId: string
  /** API key for authentication */
  apiKey?: string
  /** JWT token for server-to-server auth */
  jwt?: string
  /** Custom API host */
  host?: string
  /** Request timeout in milliseconds */
  timeout?: number
  /** Enable debug logging */
  debug?: boolean
  /** Custom fetch implementation */
  fetch?: typeof fetch
  /** Rate limiting configuration */
  rateLimit?: {
    requests: number
    window: number // in milliseconds
  }
  /** Retry configuration */
  retry?: {
    attempts: number
    delay: number // in milliseconds
  }
}

Environment Variables

# .env
ENTROLYTICS_WEBSITE_ID=your-website-id
ENTROLYTICS_API_KEY=your-api-key
ENTROLYTICS_HOST=https://entrolytics.dev
ENTROLYTICS_TIMEOUT=10000

API Reference

Events API

Track Event

await client.events.track({
  event: string,
  properties?: Record<string, any>,
  timestamp?: Date,
  userId?: string,
  sessionId?: string
})

Track Page View

await client.events.page({
  url: string,
  properties?: Record<string, any>,
  timestamp?: Date,
  userId?: string,
  sessionId?: string
})

Track Batch Events

await client.events.batch({
  events: Array<{
    event: string
    properties?: Record<string, any>
    timestamp?: Date
  }>
})

Identify User

await client.events.identify({
  userId: string,
  traits?: Record<string, any>
})

Analytics API

Overview Statistics

const overview = await client.analytics.overview({
  startDate: Date,
  endDate: Date,
  timezone?: string
})

// Returns:
interface AnalyticsOverview {
  visitors: number
  pageviews: number
  events: number
  sessions: number
  bounceRate: number
  avgSessionDuration: number
}

Top Pages

const pages = await client.analytics.topPages({
  startDate: Date,
  endDate: Date,
  limit?: number,
  timezone?: string
})

// Returns:
interface TopPage {
  path: string
  pageviews: number
  uniquePageviews: number
  avgTimeOnPage: number
  bounceRate: number
}

Event Analytics

const events = await client.analytics.events({
  startDate: Date,
  endDate: Date,
  event?: string,
  limit?: number,
  timezone?: string
})

// Returns:
interface EventAnalytics {
  event: string
  total: number
  uniqueUsers: number
  properties: Record<string, any>
}

Funnel Analysis

const funnel = await client.analytics.funnel({
  startDate: Date,
  endDate: Date,
  steps: Array<{
    event: string
    properties?: Record<string, any>
  }>,
  timezone?: string
})

// Returns:
interface FunnelAnalysis {
  steps: Array<{
    event: string
    users: number
    conversionRate: number
  }>
  overallConversionRate: number
}

Websites API

Get Website Info

const website = await client.websites.get(websiteId)

List Websites

const websites = await client.websites.list({
  limit?: number,
  offset?: number
})

Update Website

await client.websites.update(websiteId, {
  name?: string,
  domain?: string,
  settings?: Record<string, any>
})

Users API

Get User Profile

const user = await client.users.get(userId)

Update User Traits

await client.users.update(userId, {
  traits: Record<string, any>
})

List User Events

const events = await client.users.events(userId, {
  startDate: Date,
  endDate: Date,
  limit?: number
})

Advanced Usage

Custom Fetch Implementation

import { fetch } from 'undici'

const client = new EntrolyticsApiClient({
  websiteId: 'your-website-id',
  apiKey: 'your-api-key',
  fetch // Custom fetch implementation
})

Rate Limiting

const client = new EntrolyticsApiClient({
  websiteId: 'your-website-id',
  apiKey: 'your-api-key',
  rateLimit: {
    requests: 100,
    window: 60000 // 100 requests per minute
  }
})

Retry Logic

const client = new EntrolyticsApiClient({
  websiteId: 'your-website-id',
  apiKey: 'your-api-key',
  retry: {
    attempts: 3,
    delay: 1000 // Retry 3 times with 1s delay
  }
})

Request Interceptors

client.addRequestInterceptor((config) => {
  // Add custom headers
  config.headers['X-Custom-Header'] = 'value'
  return config
})

client.addResponseInterceptor((response) => {
  // Log responses
  console.log('Response:', response.status)
  return response
})

Error Handling

Error Types

try {
  await client.events.track({ event: 'test' })
} catch (error) {
  if (error instanceof EntrolyticsValidationError) {
    console.error('Validation failed:', error.errors)
  } else if (error instanceof EntrolyticsAuthError) {
    console.error('Authentication failed:', error.message)
  } else if (error instanceof EntrolyticsRateLimitError) {
    console.error('Rate limit exceeded:', error.retryAfter)
  } else if (error instanceof EntrolyticsNetworkError) {
    console.error('Network error:', error.message)
  }
}

Global Error Handler

client.onError((error) => {
  console.error('API Error:', error)

  // Send to error tracking service
  Sentry.captureException(error)
})

Real-time Data

WebSocket Connection

const ws = client.realtime.connect(websiteId)

ws.on('event', (data) => {
  console.log('Real-time event:', data)
})

ws.on('pageview', (data) => {
  console.log('Real-time pageview:', data)
})

ws.on('error', (error) => {
  console.error('WebSocket error:', error)
})

Server-Sent Events

const events = client.realtime.events(websiteId)

for await (const event of events) {
  console.log('SSE event:', event)
}

Testing

Mock Client

import { EntrolyticsApiMockClient } from '@entrolytics/api-client/testing'

const mockClient = new EntrolyticsApiMockClient()

// Configure mock responses
mockClient.events.track.mockResolvedValue({ success: true })

// Use in tests
const result = await mockClient.events.track({ event: 'test' })
expect(result).toEqual({ success: true })

Jest Integration

import { EntrolyticsApiClient } from '@entrolytics/api-client'

jest.mock('@entrolytics/api-client')

const mockClient =
  new EntrolyticsApiClient() as jest.Mocked<EntrolyticsApiClient>

mockClient.events.track.mockResolvedValue({ success: true })

Best Practices

Examples

Express.js Integration

import express from 'express'
import { EntrolyticsApiClient } from '@entrolytics/api-client'

const app = express()
const client = new EntrolyticsApiClient({
  websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,
  apiKey: process.env.ENTROLYTICS_API_KEY!
})

app.post('/track', async (req, res) => {
  try {
    await client.events.track(req.body)
    res.json({ success: true })
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
})

Next.js API Route

// pages/api/analytics/track.ts
import { NextApiRequest, NextApiResponse } from 'next'
import { EntrolyticsApiClient } from '@entrolytics/api-client'

const client = new EntrolyticsApiClient({
  websiteId: process.env.ENTROLYTICS_WEBSITE_ID!,
  apiKey: process.env.ENTROLYTICS_API_KEY!
})

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' })
  }

  try {
    await client.events.track(req.body)
    res.status(200).json({ success: true })
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
}

TypeScript API client for Entrolytics - First-party growth analytics for the edge