Skip to content

Client Configuration ​

createTeamDynamixClient(config) ​

ts
function createTeamDynamixClient(
  config: TeamDynamixClientConfig
): Promise<{ client: TeamDynamixClient; onLoginError: Promise<string | undefined> }>

Creates the SDK client. Returns both the client object and an onLoginError promise that resolves with the error message if initial token acquisition fails.

Config options ​

ts
interface TeamDynamixClientConfig {
  tenant: string
  tokenProvider: () => string | Promise<string>
  environment?: 'production' | 'sandbox'
  baseUrl?: string
  timeoutMs?: number
  runtimeValidationMode?: 'fail-closed' | 'fail-open'
  specPath?: string
  unauthenticatedPaths?: string[]
  retryPolicy?: Partial<RetryPolicy>
  onRetry?: (context: {
    schemaPath: string
    method: string
    attempt: number
    delayMs: number
    reason: string
  }) => void
}

tenant (required) ​

Your TeamDynamix subdomain, or a full custom domain:

ts
// Subdomain slug → standard URL
// tenant: 'mytenant'        → baseUrl: 'https://mytenant.teamdynamix.com'

// Full FQDN → used directly
// tenant: 'td.myuniversity.edu'  → baseUrl: 'https://td.myuniversity.edu'

When tenant contains a dot, it's treated as a fully qualified domain name and used as-is. When it has no dot, it's treated as a subdomain slug on teamdynamix.com.

Note for auth helpers: The same tenant field works in loginWithPassword and loginWithServiceAccount. When using a FQDN, the environment option is ignored (there's no standard sandbox suffix for custom domains).

tokenProvider (required) ​

A function that returns a Bearer token string. Use the built-in auth helpers:

ts
// Username/password — logs in on every token request (simple, stateless)
tokenProvider: loginWithPassword({
  tenant: 'mytenant',
  username: process.env.TD_USERNAME!,
  password: process.env.TD_PASSWORD!,
})

// Service account — same pattern, different credentials
tokenProvider: loginWithServiceAccount({
  tenant: 'mytenant',
  beid: process.env.TD_BEID!,
  webServicesKey: process.env.TD_WSKEY!,
})

The client calls tokenProvider() before every request and automatically retries once with a fresh token if the API returns 401.

You can also supply a pre-acquired JWT using the convenience helper:

ts
import { createTokenProviderFromJWT } from 'teamdynamix-ts'

tokenProvider: createTokenProviderFromJWT('eyJhbGciOiJIUzI1NiIs...')

Or inline without the helper:

ts
tokenProvider: () => 'eyJhbGciOiJIUzI1NiIs...'

environment (optional, default: 'production') ​

  • 'production' — uses https://{tenant}.teamdynamix.com/TDWebApi
  • 'sandbox' — uses https://{tenant}.sandbox.teamdynamix.com/TDWebApi

Use the sandbox environment for development and testing. Overridden by baseUrl if set.

baseUrl (optional) ​

Override the full API base URL. Useful for proxies or local testing:

ts
baseUrl: 'http://localhost:8080/proxy'

timeoutMs (optional, default: 30000) ​

Request timeout in milliseconds.

runtimeValidationMode (optional, default: 'fail-open') ​

Controls AJV-based request/response validation against the OpenAPI spec:

  • 'fail-open' — validation errors are logged but never thrown (safe default for production)
  • 'fail-closed' — throws TeamDynamixClientError with code: 'REQUEST_VALIDATION_ERROR' or 'RESPONSE_VALIDATION_ERROR' when the payload doesn't match the spec

specPath (optional, default: resolved from src/generated/openapi.json) ​

Path to the dereferenced OpenAPI JSON spec used for runtime validation. Only needed if you customized the spec location.

unauthenticatedPaths (optional) ​

Array of URL path patterns that should be called without an auth header. The client matches these as prefixes:

ts
unauthenticatedPaths: ['/api/auth/login', '/api/health']

Retry policy ​

ts
interface RetryPolicy {
  maxRetries: number           // default: 3
  initialDelayMs: number      // default: 250
  maxDelayMs: number          // default: 5000
  backoffMultiplier: number   // default: 2 (exponential)
  jitterRatio: number         // default: 0.2 (±20% random jitter)
  retryOnStatuses: Set<number> // default: {429, 502, 503, 504}
  retryOnNetworkError: boolean // default: true
  retryUnsafeMethods: boolean  // default: false
}

Override individual fields:

ts
createTeamDynamixClient({
  // ...auth config...
  retryPolicy: {
    maxRetries: 5,
    retryOnStatuses: new Set([429, 500, 502, 503, 504]),
  },
})

By default, only safe HTTP methods (GET, HEAD, OPTIONS, TRACE) are retried. Set retryUnsafeMethods: true to also retry POST/PUT/PATCH/DELETE.

onRetry callback ​

Fired before each retry attempt. Useful for logging:

ts
createTeamDynamixClient({
  // ...config...
  onRetry: ({ schemaPath, method, attempt, delayMs, reason }) => {
    console.warn(`[${method} ${schemaPath}] retry #${attempt} in ${delayMs}ms — ${reason}`)
  },
})

Config presets ​

Use caseenvironmentruntimeValidationModeretryPolicy.maxRetries
Production'production''fail-open'3
Integration tests'sandbox''fail-closed'1
Script/CLI'production''fail-open'0 (no retry)

Examples ​

Minimal config (production, quick) ​

ts
const { client } = await createTeamDynamixClient({
  tenant: 'mytenant',
  tokenProvider: loginWithPassword({
    tenant: 'mytenant',
    username: process.env.TD_USERNAME!,
    password: process.env.TD_PASSWORD!,
  }),
})

Strict config (catch validation errors early) ​

ts
const { client, onLoginError } = await createTeamDynamixClient({
  tenant: 'mytenant',
  tokenProvider: loginWithServiceAccount({
    tenant: 'mytenant',
    beid: process.env.TD_BEID!,
    webServicesKey: process.env.TD_WSKEY!,
  }),
  runtimeValidationMode: 'fail-closed',
  timeoutMs: 10000,
  retryPolicy: {
    maxRetries: 1,
    jitterRatio: 0,
  },
  onRetry: (ctx) => console.warn('Retry:', ctx),
})