TypeScript Types

Copy these types into your project for type-safe SDK integration.

Installation

No package needed—just copy the types below into your project:

// types/fig1.ts

Core Types

API Response

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: string;
  pagination?: Pagination;
}

interface Pagination {
  total: number;
  limit: number;
  offset: number;
  hasMore: boolean;
}

Agent Chat

interface AgentRequest {
  message: string;
  sessionId?: string;
  personaId?: string;
  history?: ChatMessage[];
  preferences?: UserPreferences;
  context?: PageContext;
}

interface AgentResponse {
  message: string;
  sessionId: string;
  toolCalls?: ToolCall[];
  actions?: ClientAction[];
  intent?: ExtractedIntent;
  triggeredBy?: {
    type: 'keyword' | 'intent';
    value: string;
  };
  metadata: AgentMetadata;
}

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

interface UserPreferences {
  [category: string]: {
    likes?: string[];
    dislikes?: string[];
    priceRange?: { min: number; max: number };
    restrictions?: string[];
  };
}

interface PageContext {
  /** Current page/screen URL or identifier */
  page?: string;

  /** Referrer URL */
  referrer?: string;

  /** Product IDs currently being viewed */
  productIds?: string[];

  /** Content IDs currently being viewed (exercises, articles, lessons, etc.) */
  contentIds?: string[];

  /** Video context - when user is watching a video */
  video?: VideoContext;

  /** User authentication context */
  user?: UserContext;

  /** App-specific custom data */
  metadata?: Record<string, unknown>;
}

interface VideoContext {
  /** Video ID being watched (must match processed video ID) */
  videoId: string;
  /** Current playback position in seconds */
  currentTimestamp?: number;
  /** Video title for context */
  title?: string;
  /** Total duration in seconds */
  duration?: number;
}

interface UserContext {
  /** Firebase user ID */
  uid?: string;
  /** Whether user is authenticated */
  isAuthenticated?: boolean;
  /** User's active subscription IDs */
  subscriptions?: string[];
  /** Legacy membership tier */
  membershipTier?: 'free' | 'basic' | 'premium' | 'pro' | 'enterprise';
}

interface ToolCall {
  name: string;
  input: Record<string, unknown>;
  output: Record<string, unknown>;
}

interface AgentMetadata {
  tokensUsed: number;
  proxyLatencyMs: number;
}

Client Actions

type ClientActionType =
  | 'navigate'
  | 'open_content'
  | 'play_video'
  | 'show_product'
  | 'open_modal'
  | 'add_to_cart'
  | 'open_url'
  | 'trigger_event'
  | 'custom';

interface ClientAction {
  type: ClientActionType;
  payload: {
    route?: string;
    url?: string;
    params?: Record<string, string>;
    contentId?: string;
    videoId?: string;
    timestamp?: number;
    productId?: string;
    quantity?: number;
    modalId?: string;
    modalData?: Record<string, unknown>;
    eventName?: string;
    eventData?: Record<string, unknown>;
    customType?: string;
    customData?: Record<string, unknown>;
  };
  label?: string;
  priority?: number;
  immediate?: boolean;
}

interface ExtractedIntent {
  name: string;
  confidence: number;
}

Content

type ContentType =
  | 'post'
  | 'page'
  | 'product'
  | 'faq'
  | 'video'
  | 'article'
  | 'document'
  | 'course';

type ContentStatus = 'draft' | 'published' | 'archived';
type AccessLevel = 'public' | 'authenticated' | 'premium';

interface Content {
  _id: string;
  siteId: string;
  externalId: string;
  type: ContentType;
  title: string;
  content?: string;
  excerpt?: string;
  slug: string;
  url?: string;
  language: string;
  categories: string[];
  tags: string[];
  accessLevel: AccessLevel;
  status: ContentStatus;
  author?: string;
  featuredImage?: string;
  videoMetadata?: VideoMetadata;
  documentMetadata?: DocumentMetadata;
  courseMetadata?: CourseMetadata;
  metadata: Record<string, unknown>;
  publishedAt?: string;
  createdAt: string;
  updatedAt: string;
}

interface VideoMetadata {
  duration: number;
  streamUrl?: string;
  thumbnailUrl?: string;
  resolution?: string;
}

interface DocumentMetadata {
  pageCount?: number;
  fileSize?: number;
  format?: string;
}

interface CourseMetadata {
  lessons?: number;
  totalDuration?: number;
  difficulty?: string;
  prerequisites?: string[];
}

Personas

type PersonaStatus = 'draft' | 'active' | 'archived';

interface Persona {
  _id: string;
  siteId: string;
  name: string;
  slug: string;
  description?: string;
  avatar?: string;
  isDefault: boolean;
  systemPrompt: string;
  expertise: string[];
  limitations?: string;
  voice: VoiceSettings;
  behavior: BehaviorSettings;
  model?: string;
  welcomeMessage?: string;
  suggestedQuestions: string[];
  status: PersonaStatus;
  createdAt: string;
  updatedAt: string;
}

interface VoiceSettings {
  tone: 'professional' | 'friendly' | 'casual' | 'formal' | 'playful' | 'empathetic';
  verbosity: 'concise' | 'balanced' | 'detailed';
  formality: 'formal' | 'neutral' | 'informal';
  personality?: string;
}

interface BehaviorSettings {
  showCitations: boolean;
  proactiveEngagement: boolean;
  askClarifyingQuestions: boolean;
  maxResponseLength?: number;
}

RAG Search

interface RAGSearchRequest {
  query: string;
  searchType?: 'hybrid' | 'standard' | 'expanded';
  maxResults?: number;
  threshold?: number;
  useReranking?: boolean;
  contentTypes?: string[];
}

interface RAGSearchResponse {
  results: SearchResult[];
  totalResults: number;
  query: string;
  searchType: string;
  latencyMs: number;
}

interface SearchResult {
  id: string;
  content: string;
  score: number;
  rank: number;
  source: string;
  metadata: {
    fileName?: string;
    fileType?: string;
    contentType?: string;
    [key: string]: unknown;
  };
}

Assets

interface AssetUploadRequest {
  filename: string;
  contentType: string;
  folder?: string;
}

interface AssetUploadResponse {
  uploadUrl: string;
  cdnUrl: string;
  key: string;
  expiresIn: number;
}

Usage Example

import type { AgentRequest, AgentResponse, ApiResponse } from './types/fig1';

async function chat(request: AgentRequest): Promise<AgentResponse> {
  const response = await fetch('https://app.fig1.ai/api/sdk/agent/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Fig1-API-Key': process.env.FIG1_API_KEY!
    },
    body: JSON.stringify(request)
  });

  const result: ApiResponse<AgentResponse> = await response.json();

  if (!result.success || !result.data) {
    throw new Error(result.error || 'Chat request failed');
  }

  return result.data;
}

// Fully typed usage
const response = await chat({
  message: 'What products do you recommend?',
  preferences: {
    products: {
      likes: ['organic'],
      priceRange: { min: 10, max: 50 }
    }
  }
});

console.log(response.message);
console.log(response.sessionId);

if (response.actions) {
  for (const action of response.actions) {
    if (action.type === 'navigate' && action.payload.route) {
      // TypeScript knows action.payload.route is string
      router.push(action.payload.route);
    }
  }
}

Video Training Example

// Video training app with exercise context
const response = await chat({
  message: 'What technique is being shown here?',
  sessionId,
  context: {
    page: '/exercises/rear-naked-choke',
    contentIds: ['exercise_123'],  // CMS content ID for this exercise
    video: {
      videoId: 'video_abc123',      // Must match processed video ID
      currentTimestamp: 40,          // User is at 0:40
      title: 'Rear Naked Choke Tutorial',
      duration: 360                  // 6 minute video
    },
    user: {
      isAuthenticated: true,
      subscriptions: ['premium']
    }
  }
});

// The AI will search video content near timestamp 40s
// and respond with context-aware technique explanations

// Handle video navigation actions
if (response.actions) {
  for (const action of response.actions) {
    if (action.type === 'play_video' && action.payload.timestamp) {
      videoPlayer.seekTo(action.payload.timestamp);
    }
  }
}