Skip to main content
Configure the Voyage AI provider to customize API endpoints, authentication, request behavior, and model-specific settings.

Provider setup

Create a Voyage AI provider instance with your configuration:
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
});

Authentication

The provider requires an API key from Voyage AI:
1
Environment variable
2
Set your API key as an environment variable (recommended):
3
export VOYAGE_API_KEY="your-api-key-here"
4
The provider automatically reads from VOYAGE_API_KEY:
5
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage();
// API key loaded from VOYAGE_API_KEY environment variable
6
Direct configuration
7
Pass the API key directly when creating the provider:
8
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: 'your-api-key-here',
});
9
Never hardcode API keys in your source code. Use environment variables or secure configuration management.

Provider settings

Customize the provider with these settings:

baseURL

Override the default API endpoint:
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  baseURL: 'https://api.voyageai.com/v1',
});
Customize the base URL to:
  • Use a proxy server for API calls
  • Route requests through a custom gateway
  • Test against a staging environment
  • Use a different API version
The default is https://api.voyageai.com/v1.

headers

Add custom headers to all API requests:
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  headers: {
    'X-Custom-Header': 'custom-value',
    'User-Agent': 'my-app/1.0',
  },
});
Custom headers are included in every request to the Voyage AI API.

fetch

Provide a custom fetch implementation:
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  fetch: async (url, options) => {
    console.log('Making request to:', url);
    const response = await fetch(url, options);
    console.log('Response status:', response.status);
    return response;
  },
});
Use a custom fetch implementation to:
  • Add request/response logging
  • Implement retry logic
  • Add request timing metrics
  • Intercept and modify requests
  • Test with mocked responses
  • Add circuit breaker patterns

Complete configuration example

Combine all settings for full control:
import { createVoyage } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  baseURL: 'https://api.voyageai.com/v1',
  headers: {
    'X-Application': 'my-app',
    'X-Environment': process.env.NODE_ENV || 'development',
  },
  fetch: async (url, options) => {
    const startTime = Date.now();
    try {
      const response = await fetch(url, options);
      const duration = Date.now() - startTime;
      console.log(`Request completed in ${duration}ms`);
      return response;
    } catch (error) {
      console.error('Request failed:', error);
      throw error;
    }
  },
});

Model-specific configuration

Each model type accepts specific provider options:

Text embedding options

Configure text embedding behavior:
import { createVoyage } from 'voyage-ai-provider';
import { embed } from 'ai';
import type { VoyageEmbeddingOptions } from 'voyage-ai-provider';

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
});

const { embedding } = await embed({
  model: voyage.textEmbeddingModel('voyage-code-3'),
  value: 'Sample text',
  providerOptions: {
    voyage: {
      inputType: 'query',
      outputDimension: 512,
      outputDtype: 'float',
      truncation: true,
    } satisfies VoyageEmbeddingOptions,
  },
});
Available options:
  • inputType: 'query' or 'document' - Optimizes prompt for retrieval
  • outputDimension: Number - Reduces embedding dimensions (model-specific)
  • outputDtype: 'float' | 'int8' | 'uint8' | 'binary' | 'ubinary' - Output data type
  • truncation: Boolean - Automatically truncate long inputs

Default provider instance

Use the pre-configured default instance:
import { voyage } from 'voyage-ai-provider';
import { embed } from 'ai';

// Uses VOYAGE_API_KEY environment variable
const { embedding } = await embed({
  model: voyage.textEmbeddingModel('voyage-3-lite'),
  value: 'Sample text',
});
The default voyage instance reads configuration from environment variables and uses default settings.

Multiple provider instances

Create separate instances for different configurations:
import { createVoyage } from 'voyage-ai-provider';

// Production instance
const voyageProduction = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY_PROD,
  headers: {
    'X-Environment': 'production',
  },
});

// Development instance with logging
const voyageDevelopment = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY_DEV,
  headers: {
    'X-Environment': 'development',
  },
  fetch: async (url, options) => {
    console.log('Dev request:', url);
    return fetch(url, options);
  },
});

// Use appropriate instance based on environment
const voyage = process.env.NODE_ENV === 'production'
  ? voyageProduction
  : voyageDevelopment;

Environment-based configuration

Manage configuration across environments:
import { createVoyage } from 'voyage-ai-provider';

interface Config {
  apiKey: string;
  baseURL?: string;
  environment: string;
}

const configs: Record<string, Config> = {
  development: {
    apiKey: process.env.VOYAGE_API_KEY_DEV!,
    environment: 'development',
  },
  staging: {
    apiKey: process.env.VOYAGE_API_KEY_STAGING!,
    baseURL: 'https://staging-api.voyageai.com/v1',
    environment: 'staging',
  },
  production: {
    apiKey: process.env.VOYAGE_API_KEY_PROD!,
    environment: 'production',
  },
};

const env = process.env.NODE_ENV || 'development';
const config = configs[env];

const voyage = createVoyage({
  apiKey: config.apiKey,
  baseURL: config.baseURL,
  headers: {
    'X-Environment': config.environment,
  },
});

Request interceptor pattern

Implement request/response interceptors:
import { createVoyage } from 'voyage-ai-provider';

interface RequestMetrics {
  url: string;
  duration: number;
  status: number;
}

const metrics: RequestMetrics[] = [];

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  fetch: async (url, options) => {
    // Pre-request hook
    const startTime = Date.now();
    console.log('Starting request:', url);
    
    try {
      // Make request
      const response = await fetch(url, options);
      
      // Post-response hook
      const duration = Date.now() - startTime;
      metrics.push({
        url: url.toString(),
        duration,
        status: response.status,
      });
      
      console.log(`Request completed: ${response.status} (${duration}ms)`);
      return response;
    } catch (error) {
      // Error hook
      const duration = Date.now() - startTime;
      console.error(`Request failed after ${duration}ms:`, error);
      throw error;
    }
  },
});

// Access metrics
setInterval(() => {
  const avgDuration = metrics.reduce((sum, m) => sum + m.duration, 0) / metrics.length;
  console.log(`Average request duration: ${avgDuration.toFixed(2)}ms`);
}, 60000);

Retry logic

Implement automatic retries for failed requests:
import { createVoyage } from 'voyage-ai-provider';

async function fetchWithRetry(
  url: RequestInfo,
  options: RequestInit,
  maxRetries = 3,
): Promise<Response> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      // Retry on server errors
      if (response.status >= 500 && attempt < maxRetries) {
        console.log(`Server error, retrying (${attempt}/${maxRetries})...`);
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
        continue;
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      console.log(`Network error, retrying (${attempt}/${maxRetries})...`);
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
  
  throw new Error('Max retries exceeded');
}

const voyage = createVoyage({
  apiKey: process.env.VOYAGE_API_KEY,
  fetch: fetchWithRetry,
});
Use exponential backoff when implementing retry logic to avoid overwhelming the API during outages.

Testing configuration

Configure the provider for testing:
import { createVoyage } from 'voyage-ai-provider';

// Mock fetch for testing
const mockFetch = async (url: RequestInfo, options?: RequestInit) => {
  return new Response(
    JSON.stringify({
      data: [{ embedding: new Array(1024).fill(0.1) }],
      usage: { total_tokens: 10 },
    }),
    {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    },
  );
};

const voyageTest = createVoyage({
  apiKey: 'test-key',
  fetch: mockFetch,
});

Best practices

1
Use environment variables
2
Store API keys and configuration in environment variables, never in source code.
3
Create reusable instances
4
Create provider instances once and reuse them throughout your application.
5
Implement monitoring
6
Use custom fetch functions to add logging, metrics, and error tracking.
7
Handle errors gracefully
8
Implement retry logic and proper error handling for production applications.
9
Separate environments
10
Use different API keys and configurations for development, staging, and production.

Next steps

Text embeddings

Generate embeddings from text

Multimodal embeddings

Combine text and images

Reranking

Improve search results

API Reference

Explore the complete API

Build docs developers (and LLMs) love