or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

audio-processing.mdconversational-ai.mdhistory.mdindex.mdprojects-studio.mdstreaming.mdtext-to-speech.mdutilities.mdvoice-management.md
tile.json

history.mddocs/

Audio Generation History

Overview

The History API provides comprehensive management of your audio generation history, allowing you to retrieve, download, and manage previously generated audio files with detailed metadata and search capabilities.

Core Imports

import { 
  ElevenLabsClient,
  type HistoryGetAllRequest,
  type GetSpeechHistoryResponse,
  type HistoryItemResponse,
  type DeleteHistoryItemResponse,
  type HistoryDownloadRequest,
  type HistoryGetAllRequestSource
} from 'elevenlabs';

Retrieving History

Get All History Items

const client = new ElevenLabsClient();

// Get recent audio generation history
const historyResponse = await client.history.getAll();

console.log(`Total history items: ${historyResponse.has_more ? 'More than ' : ''}${historyResponse.history.length}`);

historyResponse.history.forEach((item, index) => {
  console.log(`${index + 1}. ${item.text?.substring(0, 50)}...`);
  console.log(`   Voice: ${item.voice_name} (${item.voice_id})`);
  console.log(`   Created: ${new Date(item.date_unix * 1000).toLocaleString()}`);
  console.log(`   Character count: ${item.character_count_change_from}, ${item.character_count_change_to}`);
});

Filtered History Retrieval

// Get history with filters and pagination
const filteredHistory = await client.history.getAll({
  page_size: 50,
  voice_id: "21m00Tcm4TlvDq8ikWAM", // Filter by specific voice
  search: "important announcement", // Search in text content
  source: "tts" // Filter by generation source
});

console.log('Filtered results:', filteredHistory.history.length);

Paginated History Access

// Paginate through large history collections
let allHistoryItems = [];
let startAfter: string | undefined;
let hasMore = true;

while (hasMore) {
  const batch = await client.history.getAll({
    page_size: 100,
    start_after_history_item_id: startAfter
  });
  
  allHistoryItems.push(...batch.history);
  
  if (batch.history.length > 0) {
    startAfter = batch.history[batch.history.length - 1].history_item_id;
    hasMore = batch.has_more;
  } else {
    hasMore = false;
  }
  
  console.log(`Loaded ${allHistoryItems.length} history items...`);
}

console.log(`Total history items: ${allHistoryItems.length}`);

Request Interfaces

HistoryGetAllRequest

interface HistoryGetAllRequest {
  /** 
   * Maximum items to return (max 1000, default 100)
   */
  page_size?: number;
  
  /** 
   * Pagination cursor - ID to start fetching after
   * Used for paginating through large collections
   */
  start_after_history_item_id?: string;
  
  /** 
   * Filter by specific voice ID
   * Use voices.getAll() to list available voice IDs
   */
  voice_id?: string;
  
  /** 
   * Search term for filtering history items
   * Searches in text content and metadata
   * Requires 'source' parameter when provided
   */
  search?: string;
  
  /** 
   * Source of the generated history item
   * Used to filter by generation method
   */
  source?: HistoryGetAllRequestSource;
}

History Source Types

type HistoryGetAllRequestSource = 
  | "tts"           // Text-to-speech generations
  | "sts"           // Speech-to-speech conversions  
  | "dubbing"       // Dubbing projects
  | "sound_effects" // Sound effects generation
  | "voice_clone"   // Voice cloning operations
  | "instant_voice_cloning"; // Instant voice cloning

Individual History Items

Get Specific History Item

// Get detailed information for a specific history item
const historyItem = await client.history.get("history_item_id_here");

console.log('History item details:', {
  id: historyItem.history_item_id,
  text: historyItem.text,
  voice: {
    id: historyItem.voice_id,
    name: historyItem.voice_name,
    category: historyItem.voice_category
  },
  generation: {
    date: new Date(historyItem.date_unix * 1000),
    characterCount: historyItem.character_count_change_from,
    model: historyItem.model_id,
    settings: historyItem.settings
  },
  metadata: {
    source: historyItem.source,
    state: historyItem.state,
    feedbackThumbsUp: historyItem.feedback?.thumbs_up,
    feedbackIssues: historyItem.feedback?.feedback,
    shareLink: historyItem.share_link_id
  }
});

HistoryItemResponse Interface

interface HistoryItemResponse {
  /** Unique identifier for the history item */
  history_item_id: string;
  
  /** Generated text content */
  text?: string;
  
  /** Voice information */
  voice_id: string;
  voice_name?: string;
  voice_category?: string;
  
  /** Generation metadata */
  date_unix: number;
  character_count_change_from: number;
  character_count_change_to: number;
  content_type?: string;
  state?: string;
  
  /** Generation settings */
  model_id?: string;
  settings?: VoiceSettings;
  
  /** Source and classification */
  source?: HistoryGetAllRequestSource;
  
  /** User feedback */
  feedback?: {
    thumbs_up?: boolean;
    feedback?: string;
    emotions?: boolean;
    inaccurate_clone?: boolean;
    glitches?: boolean;
    audio_quality?: boolean;
    other?: boolean;
  };
  
  /** Sharing information */
  share_link_id?: string;
}

Audio Download and Playback

Get History Audio Stream

// Download audio for a specific history item
const audioStream = await client.history.getAudio("history_item_id_here");

// Play the audio
import { play } from 'elevenlabs';
await play(audioStream);

Save History Audio to File

import * as fs from 'fs';
import { pipeline } from 'stream';
import { promisify } from 'util';

const pipelineAsync = promisify(pipeline);

// Download and save history audio
const audioStream = await client.history.getAudio("history_item_id_here");
const outputPath = 'downloaded_audio.mp3';

await pipelineAsync(
  audioStream,
  fs.createWriteStream(outputPath)
);

console.log(`Audio saved to ${outputPath}`);

Bulk Audio Download

// Download multiple history items as an archive
const archiveStream = await client.history.downloadHistory({
  history_item_ids: [
    "history_item_1",
    "history_item_2", 
    "history_item_3"
  ]
});

// Save the archive
await pipelineAsync(
  archiveStream,
  fs.createWriteStream('history_archive.zip')
);

History Management

Delete History Items

// Delete a specific history item
const deleteResult = await client.history.delete("history_item_id_here");

console.log('Deletion successful:', deleteResult.success);

Bulk History Management

// Delete multiple items based on criteria
const oldHistory = await client.history.getAll({
  page_size: 1000
});

const thirtyDaysAgo = Date.now() / 1000 - (30 * 24 * 60 * 60);
const itemsToDelete = oldHistory.history.filter(
  item => item.date_unix < thirtyDaysAgo
);

console.log(`Deleting ${itemsToDelete.length} old history items...`);

for (const item of itemsToDelete) {
  try {
    await client.history.delete(item.history_item_id);
    console.log(`Deleted: ${item.text?.substring(0, 30)}...`);
  } catch (error) {
    console.error(`Failed to delete ${item.history_item_id}:`, error);
  }
}

Advanced History Queries

Search and Filter Examples

// Search for specific content
const searchResults = await client.history.getAll({
  search: "customer announcement",
  source: "tts",
  page_size: 100
});

// Filter by voice and date range (client-side filtering)
const voiceHistory = await client.history.getAll({
  voice_id: "pNInz6obpgDQGcFmaJgB",
  page_size: 1000
});

const lastWeek = Date.now() / 1000 - (7 * 24 * 60 * 60);
const recentVoiceHistory = voiceHistory.history.filter(
  item => item.date_unix > lastWeek
);

console.log(`Recent items for this voice: ${recentVoiceHistory.length}`);

History Analytics

// Analyze history usage patterns
const fullHistory = await client.history.getAll({
  page_size: 1000
});

const analytics = {
  totalItems: fullHistory.history.length,
  totalCharacters: fullHistory.history.reduce(
    (sum, item) => sum + (item.character_count_change_to - item.character_count_change_from), 
    0
  ),
  voiceUsage: new Map<string, number>(),
  modelUsage: new Map<string, number>(),
  sourceBreakdown: new Map<string, number>()
};

fullHistory.history.forEach(item => {
  // Voice usage
  const voiceKey = `${item.voice_name} (${item.voice_id})`;
  analytics.voiceUsage.set(voiceKey, (analytics.voiceUsage.get(voiceKey) || 0) + 1);
  
  // Model usage
  if (item.model_id) {
    analytics.modelUsage.set(item.model_id, (analytics.modelUsage.get(item.model_id) || 0) + 1);
  }
  
  // Source breakdown
  if (item.source) {
    analytics.sourceBreakdown.set(item.source, (analytics.sourceBreakdown.get(item.source) || 0) + 1);
  }
});

console.log('History Analytics:', analytics);

History Organization

Export History Data

// Export history metadata to JSON
const historyExport = await client.history.getAll({
  page_size: 1000
});

const exportData = {
  exportDate: new Date().toISOString(),
  totalItems: historyExport.history.length,
  items: historyExport.history.map(item => ({
    id: item.history_item_id,
    text: item.text,
    voiceId: item.voice_id,
    voiceName: item.voice_name,
    date: new Date(item.date_unix * 1000).toISOString(),
    characterCount: item.character_count_change_to - item.character_count_change_from,
    model: item.model_id,
    source: item.source,
    settings: item.settings
  }))
};

fs.writeFileSync('history_export.json', JSON.stringify(exportData, null, 2));
console.log('History exported to history_export.json');

History Backup Strategy

// Comprehensive backup of audio and metadata
async function backupHistory(client: ElevenLabsClient, outputDir: string) {
  const history = await client.history.getAll({ page_size: 1000 });
  
  // Create backup directory
  fs.mkdirSync(outputDir, { recursive: true });
  
  // Save metadata
  fs.writeFileSync(
    path.join(outputDir, 'metadata.json'),
    JSON.stringify(history, null, 2)
  );
  
  // Download all audio files
  for (let i = 0; i < history.history.length; i++) {
    const item = history.history[i];
    try {
      const audioStream = await client.history.getAudio(item.history_item_id);
      const filename = `${item.history_item_id}_${item.voice_name?.replace(/\s+/g, '_') || 'unknown'}.mp3`;
      
      await pipelineAsync(
        audioStream,
        fs.createWriteStream(path.join(outputDir, filename))
      );
      
      console.log(`Backed up ${i + 1}/${history.history.length}: ${filename}`);
    } catch (error) {
      console.error(`Failed to backup ${item.history_item_id}:`, error);
    }
  }
  
  console.log(`Backup completed in ${outputDir}`);
}

// Usage
await backupHistory(client, './history_backup');

Error Handling

import { ElevenLabsError, ElevenLabsTimeoutError } from 'elevenlabs';

try {
  const history = await client.history.getAll({
    page_size: 100,
    search: "specific content"
  });
  
  for (const item of history.history) {
    try {
      const audio = await client.history.getAudio(item.history_item_id);
      await processAudio(audio);
    } catch (audioError) {
      console.error(`Failed to get audio for ${item.history_item_id}:`, audioError);
      continue; // Continue with other items
    }
  }
  
} catch (error) {
  if (error instanceof ElevenLabsError) {
    console.error('History API error:', error.statusCode);
    
    if (error.statusCode === 401) {
      console.error('Authentication error - check API key');
    } else if (error.statusCode === 404) {
      console.error('History item not found');
    } else if (error.statusCode === 429) {
      console.error('Rate limit exceeded');
    }
  } else if (error instanceof ElevenLabsTimeoutError) {
    console.error('Request timed out:', error.message);
  }
}

Performance Optimization

Efficient History Processing

// Process history in chunks to avoid memory issues
async function processHistoryInBatches(
  client: ElevenLabsClient,
  batchSize: number = 50,
  processor: (items: HistoryItemResponse[]) => Promise<void>
) {
  let startAfter: string | undefined;
  let hasMore = true;
  
  while (hasMore) {
    const batch = await client.history.getAll({
      page_size: batchSize,
      start_after_history_item_id: startAfter
    });
    
    if (batch.history.length > 0) {
      await processor(batch.history);
      startAfter = batch.history[batch.history.length - 1].history_item_id;
      hasMore = batch.has_more;
    } else {
      hasMore = false;
    }
  }
}

// Usage
await processHistoryInBatches(client, 25, async (items) => {
  console.log(`Processing batch of ${items.length} items`);
  // Process items...
});

History Caching

// Cache frequently accessed history items
class HistoryCache {
  private cache = new Map<string, HistoryItemResponse>();
  private audioCache = new Map<string, Buffer>();
  
  async getHistoryItem(client: ElevenLabsClient, id: string): Promise<HistoryItemResponse> {
    if (!this.cache.has(id)) {
      const item = await client.history.get(id);
      this.cache.set(id, item);
    }
    return this.cache.get(id)!;
  }
  
  async getHistoryAudio(client: ElevenLabsClient, id: string): Promise<stream.Readable> {
    if (!this.audioCache.has(id)) {
      const audioStream = await client.history.getAudio(id);
      const chunks: Buffer[] = [];
      
      return new Promise((resolve, reject) => {
        audioStream.on('data', chunk => chunks.push(chunk));
        audioStream.on('end', () => {
          const buffer = Buffer.concat(chunks);
          this.audioCache.set(id, buffer);
          resolve(stream.Readable.from(buffer));
        });
        audioStream.on('error', reject);
      });
    }
    
    return stream.Readable.from(this.audioCache.get(id)!);
  }
  
  clear() {
    this.cache.clear();
    this.audioCache.clear();
  }
}

Best Practices

  1. Pagination: Always use pagination for large history collections to avoid memory issues
  2. Filtering: Use server-side filters (voice_id, source, search) to reduce data transfer
  3. Batch Processing: Process history items in batches to manage memory usage
  4. Error Handling: Handle individual item failures gracefully in batch operations
  5. Caching: Cache frequently accessed history data to reduce API calls
  6. Cleanup: Regularly delete old history items to manage storage costs
  7. Backup: Implement regular backups of important audio generations
  8. Search: Use specific search terms to quickly find relevant history items
  9. Metadata Export: Export metadata for analysis and reporting purposes
  10. Rate Limiting: Respect API rate limits when processing large history collections