Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.flowsbuilt.com/llms.txt

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

ChurnKitError

All SDK methods throw ChurnKitError on failure. It extends Error and adds status (HTTP status code) and code (typed error constant).
import { ChurnKitError, ErrorCode } from '@vgpprasad91/churnkit-sdk'

try {
  await churn.score('user_123')
} catch (err) {
  if (err instanceof ChurnKitError) {
    console.log(err.message)  // human-readable description
    console.log(err.status)   // HTTP status code (or undefined for network errors)
    console.log(err.code)     // 'TIMEOUT' | 'UNAUTHORIZED' | etc.
  }
}

Error codes

CodeHTTPWhen
ABORTEDThe caller’s AbortSignal fired
TIMEOUTRequest exceeded configured timeout
NETWORK_ERRORDNS failure, connection refused, etc.
VALIDATION_ERROR400Invalid input (empty userId, bad threshold, etc.)
UNAUTHORIZED401API key is missing, invalid, or revoked
FORBIDDEN403API key lacks permission for this operation
NOT_FOUND404Resource doesn’t exist (user not tracked, no watch, etc.)
RATE_LIMITED429Too many requests — back off and retry
SERVER_ERROR5xxChurnKit server error
PAYLOAD_TOO_LARGE413bulkEvent() exceeded 500 items

Handling patterns

Ignore cancellations

try {
  const risk = await churn.score(userId, { signal })
  return risk
} catch (err) {
  if (err instanceof ChurnKitError && err.code === ErrorCode.ABORTED) {
    return null // user navigated away — ignore
  }
  throw err
}

Exhaustive switch with type narrowing

import { ChurnKitError, ErrorCode, isKnownErrorCode } from '@vgpprasad91/churnkit-sdk'

try {
  await churn.identify(userId, traits)
} catch (err) {
  if (err instanceof ChurnKitError && isKnownErrorCode(err.code)) {
    switch (err.code) {
      case ErrorCode.UNAUTHORIZED:
        logger.error('ChurnKit API key invalid — check CHURNKIT_API_KEY')
        break
      case ErrorCode.RATE_LIMITED:
        logger.warn('ChurnKit rate limited — consider batching')
        break
      case ErrorCode.TIMEOUT:
        logger.warn('ChurnKit timeout — request took too long')
        break
      case ErrorCode.VALIDATION_ERROR:
        logger.error('ChurnKit validation error', err.message)
        break
      default:
        logger.error('ChurnKit error', err.code, err.message)
    }
  }
}

Non-blocking with error logging

async function trackSafe(userId: string, event: string) {
  try {
    await churn.event(userId, event)
  } catch (err) {
    // Never let tracking failures break the main flow
    if (err instanceof ChurnKitError) {
      logger.warn('ChurnKit track failed', { code: err.code, event })
    }
  }
}

isKnownErrorCode()

Type guard that narrows err.code to a well-known ErrorCode constant — useful for exhaustive switch statements.
import { isKnownErrorCode } from '@vgpprasad91/churnkit-sdk'

if (err instanceof ChurnKitError && isKnownErrorCode(err.code)) {
  // err.code is now typed as ErrorCode — IDE autocomplete works
  switch (err.code) { ... }
}