Skip to main content
All types below are exported from the package root:
import type {
  SpekoClientOptions,
  KeySource,
  Vertical,
  OptimizeFor,
  RoutingIntent,
  PipelineConstraints,
  TranscribeOptions,
  TranscribeResult,
  SynthesizeOptions,
  SynthesizeResult,
  ChatMessage,
  CompleteParams,
  CompleteResult,
  UsageSummary,
  UsageByProvider,
  UsageQueryParams,
  OrganizationBalance,
  CreditLedgerEntry,
  CreditLedgerKind,
  CreditLedgerPage,
  CreditLedgerQueryParams,
  RealtimeProvider,
  RealtimeToolSpec,
  RealtimeConnectParams,
  RealtimeFrame,
  RealtimeEventHandler,
  RealtimeSessionHandle,
} from '@spekoai/sdk';

Routing primitives

Vertical

type Vertical = 'general' | 'healthcare' | 'finance' | 'legal';
Vertical labels the router uses to pick a provider. Each vertical has its own benchmark set.

OptimizeFor

type OptimizeFor = 'balanced' | 'accuracy' | 'latency' | 'cost';
Biases the weighted score the router uses to rank candidates. balanced is the default.

RoutingIntent

interface RoutingIntent {
  language: string;       // BCP-47, e.g. "en" or "es-MX"
  vertical: Vertical;
  optimizeFor?: OptimizeFor;
}
Every proxy call takes one. TranscribeOptions and SynthesizeOptions extend it directly.

PipelineConstraints

interface PipelineConstraints {
  allowedProviders?: {
    stt?: string[];
    llm?: string[];
    tts?: string[];
  };
}
Optional allow-list layered on top of RoutingIntent. When set, the router still ranks by benchmark score but considers only candidates in the allow-list for that modality.

Transcribe

interface TranscribeOptions extends RoutingIntent {
  contentType?: string;          // default "audio/wav"
  constraints?: PipelineConstraints;
}

interface TranscribeResult {
  text: string;
  provider: string;
  model: string;
  confidence: number | null;
  failoverCount: number;
  scoresRunId: string | null;
}

Synthesize

interface SynthesizeOptions extends RoutingIntent {
  voice?: string;
  speed?: number;
  constraints?: PipelineConstraints;
}

interface SynthesizeResult {
  audio: Uint8Array;
  contentType: string;           // e.g. "audio/pcm;rate=24000" or "audio/mpeg"
  provider: string;
  model: string;
  failoverCount: number;
  scoresRunId: string | null;
}

Complete

interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

interface CompleteParams {
  messages: ChatMessage[];
  intent: RoutingIntent;
  systemPrompt?: string;
  temperature?: number;
  maxTokens?: number;
  constraints?: PipelineConstraints;
}

interface CompleteResult {
  text: string;
  provider: string;
  model: string;
  usage: {
    promptTokens: number;
    completionTokens: number;
  };
  failoverCount: number;
  scoresRunId: string | null;
}

Usage

type KeySource = 'BYOK' | 'MANAGED';

interface UsageQueryParams {
  from?: string;                 // ISO-8601
  to?: string;                   // ISO-8601
}

interface UsageSummary {
  totalSessions: number;
  totalMinutes: number;
  totalCost: number;
  breakdown: UsageByProvider[];
  balanceMicroUsd: string;       // µ$ as string so values > 2^53 survive JSON
  balanceUsd: number;
}

interface UsageByProvider {
  provider: string;
  type: 'stt' | 'llm' | 'tts';
  metric: string;
  keySource: KeySource;
  quantity: number;
  cost: number;
}

Credits

interface OrganizationBalance {
  balanceMicroUsd: string;
  balanceUsd: number;
  updatedAt: string;
}

type CreditLedgerKind =
  | 'grant'
  | 'debit'
  | 'topup'
  | 'refund'
  | 'adjustment';

interface CreditLedgerEntry {
  id: string;
  kind: CreditLedgerKind;
  /** Signed. Positive for grants/topups/refunds, negative for debits. */
  amountMicroUsd: string;
  metric: string | null;
  provider: string | null;
  sessionId: string | null;
  createdAt: string;
}

interface CreditLedgerPage {
  entries: CreditLedgerEntry[];
  nextCursor: string | null;
}

interface CreditLedgerQueryParams {
  limit?: number;
  cursor?: string;
}

Realtime (S2S)

type RealtimeProvider = 'openai' | 'google' | 'xai';

interface RealtimeToolSpec {
  name: string;
  description: string;
  parameters: Record<string, unknown>;
}

interface RealtimeConnectParams {
  provider: RealtimeProvider;
  model: string;
  voice?: string;
  systemPrompt?: string;
  temperature?: number;
  inputSampleRate?: 16000 | 24000;
  outputSampleRate?: 16000 | 24000;
  tools?: RealtimeToolSpec[];
  metadata?: Record<string, unknown>;
  /** Max session duration in seconds. Server-capped at 1800 (30 min). */
  ttlSeconds?: number;
}

type RealtimeFrame =
  | { type: 'audio'; pcm: Uint8Array; sampleRate: number }
  | {
      type: 'transcript';
      role: 'user' | 'assistant';
      text: string;
      final: boolean;
    }
  | {
      type: 'tool_call';
      callId: string;
      name: string;
      arguments: string;
    }
  | {
      type: 'usage';
      inputAudioTokens: number;
      outputAudioTokens: number;
    }
  | { type: 'error'; code: string; message: string }
  | { type: 'close'; code: number; reason: string };

type RealtimeEventHandler = (frame: RealtimeFrame) => void;

interface RealtimeSessionHandle {
  readonly sessionId: string;
  readonly expiresAt: string;

  sendAudio(pcm: Uint8Array): void;
  commit(): void;
  interrupt(): void;
  sendToolResult(callId: string, output: string): void;
  on(handler: RealtimeEventHandler): () => void;
  close(code?: number, reason?: string): void;
}

Client

interface SpekoClientOptions {
  apiKey: string;
  baseUrl?: string;              // default "https://api.speko.ai"
  timeout?: number;              // default 30000
}