or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

audio

audio-processing.mdrealtime-transcription.mdspeech-to-speech.mdspeech-to-text.mdtext-to-speech.md
index.md
tile.json

responses.mddocs/core/

Response Handling

Access both parsed API responses and raw HTTP responses for advanced use cases. All API methods return HttpResponsePromise which provides transparent access to underlying response data.

Quick Reference

import { HttpResponsePromise } from "@elevenlabs/elevenlabs-js";

// All API methods return HttpResponsePromise<T>

HttpResponsePromise

All API methods return HttpResponsePromise<T> which extends Promise<T> with additional functionality for accessing raw HTTP responses.

/**
 * A promise that returns parsed response and provides access to raw HTTP response
 */
class HttpResponsePromise<T> extends Promise<T> {
  /**
   * Retrieves both the parsed data and the raw HTTP response
   * @returns Promise resolving to data and rawResponse
   */
  async withRawResponse(): Promise<{ data: T; rawResponse: Response }>;
}

Usage Examples

Basic Response Access

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const client = new ElevenLabsClient({ apiKey: "your-api-key" });

// Standard usage - get parsed data only
const audio = await client.textToSpeech.convert("voice-id", {
  text: "Hello, world!",
});

// Process audio stream
for await (const chunk of audio) {
  // Handle audio chunks
}

Access Raw Response

// Get both parsed data and raw HTTP response
const { data, rawResponse } = await client.textToSpeech
  .convert("voice-id", { text: "Hello" })
  .withRawResponse();

// Access HTTP response properties
console.log("Status:", rawResponse.status);
console.log("Status Text:", rawResponse.statusText);
console.log("Headers:", rawResponse.headers);
console.log("URL:", rawResponse.url);

// Process parsed data
for await (const chunk of data) {
  // Handle audio chunks
}

Check Response Headers

// Inspect response headers
const { data, rawResponse } = await client.voices
  .getAll()
  .withRawResponse();

// Access specific headers
const rateLimit = rawResponse.headers.get("X-RateLimit-Limit");
const remaining = rawResponse.headers.get("X-RateLimit-Remaining");
const requestId = rawResponse.headers.get("X-Request-ID");

console.log(`Rate limit: ${remaining}/${rateLimit}`);
console.log(`Request ID: ${requestId}`);

// Process voice data
console.log("Voices:", data.voices);

Response Status Handling

// Check response status code
const { data, rawResponse } = await client.user
  .get()
  .withRawResponse();

if (rawResponse.status === 200) {
  console.log("User data:", data);
} else if (rawResponse.status === 304) {
  console.log("Not modified - use cached data");
}

Content Type Validation

// Verify response content type
const { data, rawResponse } = await client.textToSpeech
  .convert("voice-id", { text: "Hello" })
  .withRawResponse();

const contentType = rawResponse.headers.get("Content-Type");
console.log("Content-Type:", contentType);

if (contentType?.includes("audio/mpeg")) {
  console.log("Received MP3 audio");
  // Process audio stream
  for await (const chunk of data) {
    // Handle MP3 chunks
  }
}

Response Timing

// Measure response time
const startTime = Date.now();

const { data, rawResponse } = await client.textToSpeech
  .convert("voice-id", { text: "Performance test" })
  .withRawResponse();

const endTime = Date.now();
const duration = endTime - startTime;

console.log(`Request completed in ${duration}ms`);
console.log(`Status: ${rawResponse.status}`);

Cache Headers

// Check caching headers
const { data, rawResponse } = await client.voices
  .get("voice-id")
  .withRawResponse();

const cacheControl = rawResponse.headers.get("Cache-Control");
const etag = rawResponse.headers.get("ETag");
const expires = rawResponse.headers.get("Expires");

console.log("Cache-Control:", cacheControl);
console.log("ETag:", etag);
console.log("Expires:", expires);

Custom Response Processing

// Process response based on headers
async function generateWithMetadata(
  voiceId: string,
  text: string
): Promise<{
  audio: ReadableStream<Uint8Array>;
  metadata: Record<string, string>;
}> {
  const { data, rawResponse } = await client.textToSpeech
    .convert(voiceId, { text })
    .withRawResponse();

  // Extract metadata from headers
  const metadata: Record<string, string> = {};
  rawResponse.headers.forEach((value, key) => {
    if (key.startsWith("x-")) {
      metadata[key] = value;
    }
  });

  return { audio: data, metadata };
}

const result = await generateWithMetadata("voice-id", "Hello");
console.log("Audio metadata:", result.metadata);

Conditional Request Handling

// Handle different response scenarios
const { data, rawResponse } = await client.history
  .list()
  .withRawResponse();

if (rawResponse.status === 200) {
  console.log("History items:", data.history);
} else if (rawResponse.status === 204) {
  console.log("No history items available");
} else {
  console.log("Unexpected status:", rawResponse.status);
}

Response Logging

// Log response details for debugging
async function generateWithLogging(
  voiceId: string,
  text: string
): Promise<ReadableStream<Uint8Array>> {
  const { data, rawResponse } = await client.textToSpeech
    .convert(voiceId, { text })
    .withRawResponse();

  // Log response details
  console.log("Response Details:");
  console.log("  Status:", rawResponse.status, rawResponse.statusText);
  console.log("  URL:", rawResponse.url);
  console.log("  Headers:");
  rawResponse.headers.forEach((value, key) => {
    console.log(`    ${key}: ${value}`);
  });

  return data;
}

Error Response Analysis

// Analyze error responses
try {
  const audio = await client.textToSpeech.convert("invalid-voice", {
    text: "Test",
  });
} catch (error) {
  if (error.rawResponse) {
    console.log("Error response status:", error.rawResponse.status);
    console.log("Error response headers:");
    error.rawResponse.headers.forEach((value, key) => {
      console.log(`  ${key}: ${value}`);
    });

    // Check for retry-after header
    const retryAfter = error.rawResponse.headers.get("Retry-After");
    if (retryAfter) {
      console.log(`Retry after ${retryAfter} seconds`);
    }
  }
}

Pagination with Raw Response

// Track pagination metadata
async function getAllVoicesWithMetadata(): Promise<{
  voices: Voice[];
  requestId: string;
  timestamp: string;
}> {
  const { data, rawResponse } = await client.voices
    .search({ page_size: 100 })
    .withRawResponse();

  return {
    voices: data.voices,
    requestId: rawResponse.headers.get("X-Request-ID") || "",
    timestamp: rawResponse.headers.get("Date") || "",
  };
}

Response Cloning

// Clone raw response for multiple processing
const { data, rawResponse } = await client.voices
  .getAll()
  .withRawResponse();

// Clone response for separate processing
const clonedResponse = rawResponse.clone();

// Process original data
console.log("Voices:", data.voices);

// Use cloned response for additional processing
const bodyText = await clonedResponse.text();
console.log("Raw response body length:", bodyText.length);

Custom Header Extraction

// Extract custom headers into structured format
interface ResponseMetadata {
  requestId: string;
  rateLimit: {
    limit: number;
    remaining: number;
    reset: number;
  };
  server: string;
}

async function fetchWithMetadata<T>(
  promise: HttpResponsePromise<T>
): Promise<{ data: T; metadata: ResponseMetadata }> {
  const { data, rawResponse } = await promise.withRawResponse();

  const metadata: ResponseMetadata = {
    requestId: rawResponse.headers.get("X-Request-ID") || "",
    rateLimit: {
      limit: parseInt(rawResponse.headers.get("X-RateLimit-Limit") || "0"),
      remaining: parseInt(rawResponse.headers.get("X-RateLimit-Remaining") || "0"),
      reset: parseInt(rawResponse.headers.get("X-RateLimit-Reset") || "0"),
    },
    server: rawResponse.headers.get("Server") || "",
  };

  return { data, metadata };
}

// Usage
const result = await fetchWithMetadata(
  client.voices.getAll()
);

console.log("Rate limit:", result.metadata.rateLimit);
console.log("Request ID:", result.metadata.requestId);

Best Practices

When to Use withRawResponse()

// Use withRawResponse() when you need:

// 1. Response headers
const { rawResponse } = await client.voices.getAll().withRawResponse();
const requestId = rawResponse.headers.get("X-Request-ID");

// 2. Status code information
const { rawResponse } = await client.user.get().withRawResponse();
console.log("Status:", rawResponse.status);

// 3. Rate limit tracking
const { rawResponse } = await client.textToSpeech
  .convert("voice-id", { text: "Hello" })
  .withRawResponse();
const remaining = rawResponse.headers.get("X-RateLimit-Remaining");

// 4. Debugging
const { data, rawResponse } = await client.voices
  .get("voice-id")
  .withRawResponse();
console.log("Response URL:", rawResponse.url);
console.log("Response type:", rawResponse.type);

Standard Usage Pattern

// For most use cases, direct await is sufficient
const voices = await client.voices.getAll();
const audio = await client.textToSpeech.convert("voice-id", { text: "Hello" });
const user = await client.user.get();

// Only use withRawResponse() when you specifically need HTTP response details