# Configuration

Stripe's Node.js library provides comprehensive configuration options for authentication, request handling, error management, and advanced features. This documentation covers all configuration aspects from basic setup to advanced customization.

## Basic Configuration

### API Key Authentication

The primary method for authenticating with Stripe:

```typescript { .api }
import Stripe from 'stripe';

// Basic initialization with API key
const stripe = new Stripe('sk_test_...', {
  apiVersion: '2025-08-27.basil',
  typescript: true
});

// Environment-based configuration
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  typescript: true
});

// Different keys for different environments
const apiKey = process.env.NODE_ENV === 'production' 
  ? process.env.STRIPE_LIVE_SECRET_KEY 
  : process.env.STRIPE_TEST_SECRET_KEY;

const stripe = new Stripe(apiKey!, {
  apiVersion: '2025-08-27.basil',
  typescript: true
});
```

### Configuration Interface

Complete configuration options available:

```typescript { .api }
interface StripeConfig {
  // API Configuration
  apiVersion?: '2025-08-27.basil';          // Latest stable API version
  typescript?: true;                        // Enable TypeScript support
  
  // Network Configuration  
  maxNetworkRetries?: number;              // Default: 1, max: 10
  timeout?: number;                        // Request timeout in ms (default: 80000)
  httpAgent?: HttpAgent;                   // Custom HTTP agent for proxies
  httpClient?: HttpClient;                 // Custom HTTP client implementation
  
  // Host Configuration
  host?: string;                          // API host override (default: api.stripe.com)
  port?: string | number;                 // API port override (default: 443)
  protocol?: 'http' | 'https';           // Protocol override (default: https)
  
  // Feature Configuration
  telemetry?: boolean;                    // Enable/disable telemetry (default: true)
  appInfo?: AppInfo;                      // Plugin identification
  
  // Account Configuration
  stripeAccount?: string;                 // Connect account for all requests
  stripeContext?: string;                 // Context for all requests
}

// Advanced configuration example
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  typescript: true,
  maxNetworkRetries: 3,
  timeout: 30000, // 30 seconds
  telemetry: false,
  appInfo: {
    name: 'MyApp',
    version: '1.0.0',
    url: 'https://myapp.com'
  }
});
```

## Network Configuration

### HTTP Agents and Proxies

Configure HTTP agents for proxy support and connection pooling:

```typescript { .api }
import { HttpsAgent } from 'agentkeepalive';
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsProxyAgent } from 'https-proxy-agent';

// Keep-alive agent for better performance
const keepAliveAgent = new HttpsAgent({
  keepAlive: true,
  maxSockets: 100,
  maxFreeSockets: 10,
  timeout: 60000,
  freeSocketTimeout: 30000
});

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  httpAgent: keepAliveAgent,
  apiVersion: '2025-08-27.basil'
});

// Proxy configuration
const proxyAgent = new HttpsProxyAgent('http://proxy.company.com:8080');

const stripeWithProxy = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  httpAgent: proxyAgent,
  apiVersion: '2025-08-27.basil'
});

// Custom HTTP client implementation
class CustomHttpClient {
  makeRequest(
    host: string,
    port: number,
    path: string,
    method: string,
    headers: { [key: string]: string },
    requestData: string,
    protocol: string,
    timeout: number
  ): Promise<any> {
    // Custom implementation with logging, metrics, etc.
    return fetch(`${protocol}://${host}:${port}${path}`, {
      method,
      headers,
      body: requestData,
      signal: AbortSignal.timeout(timeout)
    }).then(response => ({
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      body: response.text()
    }));
  }
}

const stripeWithCustomClient = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  httpClient: new CustomHttpClient(),
  apiVersion: '2025-08-27.basil'
});
```

### Retry Configuration

Configure automatic retry behavior for failed requests:

```typescript { .api }
// Global retry configuration
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  maxNetworkRetries: 5, // Retry up to 5 times
  apiVersion: '2025-08-27.basil'
});

// Per-request retry override
const customer = await stripe.customers.create({
  email: 'customer@example.com'
}, {
  maxNetworkRetries: 2 // Override global setting
});

// Custom retry logic with exponential backoff
class RetryableHttpClient {
  async makeRequest(...args: any[]): Promise<any> {
    const maxRetries = 3;
    let attempt = 0;
    
    while (attempt <= maxRetries) {
      try {
        return await this.performRequest(...args);
      } catch (error) {
        if (attempt === maxRetries || !this.shouldRetry(error)) {
          throw error;
        }
        
        const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, delay));
        attempt++;
      }
    }
  }
  
  private shouldRetry(error: any): boolean {
    // Retry on network errors and 5xx status codes
    return error.code === 'ECONNRESET' || 
           error.code === 'ENOTFOUND' ||
           (error.statusCode >= 500 && error.statusCode < 600);
  }
  
  private async performRequest(...args: any[]): Promise<any> {
    // Actual HTTP request implementation
  }
}
```

### Timeout Configuration

Configure request timeouts at various levels:

```typescript { .api }
// Global timeout configuration
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  timeout: 15000, // 15 seconds for all requests
  apiVersion: '2025-08-27.basil'
});

// Per-request timeout
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd'
}, {
  timeout: 30000 // 30 seconds for this specific request
});

// Different timeouts for different operations
class TimeoutManager {
  private readonly timeouts = {
    create: 30000,   // 30s for creates
    update: 20000,   // 20s for updates
    list: 10000,     // 10s for lists
    retrieve: 5000   // 5s for retrievals
  };
  
  getTimeout(operation: keyof typeof this.timeouts): number {
    return this.timeouts[operation];
  }
}

const timeoutManager = new TimeoutManager();

// Use operation-specific timeouts
const customer = await stripe.customers.create({
  email: 'customer@example.com'
}, {
  timeout: timeoutManager.getTimeout('create')
});
```

## Request Options

### Per-Request Configuration

Override global settings for individual requests:

```typescript { .api }
interface RequestOptions {
  apiKey?: string;                        // Override API key
  idempotencyKey?: string;               // Idempotency key for safe retries
  stripeAccount?: string;                // Connect account
  stripeContext?: string;                // Request context
  apiVersion?: string;                   // API version override
  maxNetworkRetries?: number;            // Retry limit override
  timeout?: number;                      // Timeout override
  host?: string;                         // Host override
}

// API key override for multi-tenant applications
const platformCustomer = await stripe.customers.create({
  email: 'platform@example.com'
}, {
  apiKey: process.env.PLATFORM_SECRET_KEY
});

// Connect account operations
const connectedAccountCharge = await stripe.charges.create({
  amount: 2000,
  currency: 'usd',
  source: 'tok_visa'
}, {
  stripeAccount: 'acct_connected_account_id'
});

// Idempotency for safe retries
const idempotentPayment = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd'
}, {
  idempotencyKey: `payment_${orderId}_${timestamp}`
});

// Context for request tracking
const contextualRequest = await stripe.customers.create({
  email: 'customer@example.com'
}, {
  stripeContext: 'signup_flow_step_3'
});
```

### Idempotency Management

Implement robust idempotency for reliable operations:

```typescript { .api }
class IdempotencyManager {
  private generateKey(prefix: string, data: any): string {
    const hash = require('crypto')
      .createHash('sha256')
      .update(JSON.stringify(data))
      .digest('hex')
      .substring(0, 16);
    
    return `${prefix}_${Date.now()}_${hash}`;
  }
  
  async createPaymentIntent(params: Stripe.PaymentIntentCreateParams): Promise<Stripe.PaymentIntent> {
    const idempotencyKey = this.generateKey('pi', params);
    
    return stripe.paymentIntents.create(params, {
      idempotencyKey
    });
  }
  
  async createCustomer(params: Stripe.CustomerCreateParams): Promise<Stripe.Customer> {
    // Use email as part of idempotency key for customers
    const keyData = { email: params.email, name: params.name };
    const idempotencyKey = this.generateKey('cus', keyData);
    
    return stripe.customers.create(params, {
      idempotencyKey
    });
  }
}
```

## Error Handling

### Error Types and Handling

Comprehensive error handling for different Stripe error types:

```typescript { .api }
// All Stripe error types
interface StripeErrorTypes {
  StripeError: typeof Stripe.errors.StripeError;
  StripeCardError: typeof Stripe.errors.StripeCardError;
  StripeInvalidRequestError: typeof Stripe.errors.StripeInvalidRequestError;
  StripeAPIError: typeof Stripe.errors.StripeAPIError;
  StripeAuthenticationError: typeof Stripe.errors.StripeAuthenticationError;
  StripePermissionError: typeof Stripe.errors.StripePermissionError;
  StripeRateLimitError: typeof Stripe.errors.StripeRateLimitError;
  StripeConnectionError: typeof Stripe.errors.StripeConnectionError;
  StripeSignatureVerificationError: typeof Stripe.errors.StripeSignatureVerificationError;
  StripeIdempotencyError: typeof Stripe.errors.StripeIdempotencyError;
  StripeInvalidGrantError: typeof Stripe.errors.StripeInvalidGrantError;
  StripeUnknownError: typeof Stripe.errors.StripeUnknownError;
}

// Comprehensive error handling function
async function handleStripeOperation<T>(operation: () => Promise<T>): Promise<T> {
  try {
    return await operation();
  } catch (error) {
    if (error instanceof stripe.errors.StripeCardError) {
      // Card was declined
      throw new PaymentError(
        'Card declined',
        error.decline_code,
        error.code,
        error.payment_intent?.id
      );
    } else if (error instanceof stripe.errors.StripeInvalidRequestError) {
      // Invalid parameters
      throw new ValidationError(
        'Invalid request',
        error.param,
        error.code
      );
    } else if (error instanceof stripe.errors.StripeAuthenticationError) {
      // Authentication failed
      throw new AuthError('Authentication failed', error.code);
    } else if (error instanceof stripe.errors.StripePermissionError) {
      // Insufficient permissions
      throw new AuthorizationError('Insufficient permissions', error.code);
    } else if (error instanceof stripe.errors.StripeRateLimitError) {
      // Rate limited
      throw new RateLimitError('Rate limit exceeded', error.code);
    } else if (error instanceof stripe.errors.StripeConnectionError) {
      // Network error
      throw new NetworkError('Network error', error.code);
    } else if (error instanceof stripe.errors.StripeAPIError) {
      // API error
      throw new APIError('API error', error.code, error.statusCode);
    } else {
      // Unknown error
      throw new UnknownError('Unknown error', error);
    }
  }
}

// Usage example with proper error handling
async function processPayment(paymentIntentId: string): Promise<PaymentResult> {
  return handleStripeOperation(async () => {
    const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId);
    
    if (paymentIntent.status === 'requires_payment_method') {
      throw new Error('Payment method required');
    }
    
    const confirmed = await stripe.paymentIntents.confirm(paymentIntentId);
    
    return {
      success: true,
      paymentIntent: confirmed
    };
  });
}
```

### Retry Logic for Errors

Implement intelligent retry logic based on error types:

```typescript { .api }
class StripeRetryHandler {
  private readonly retryableErrors = [
    'rate_limit',
    'api_connection_error',
    'api_error'
  ];
  
  async withRetry<T>(
    operation: () => Promise<T>,
    maxRetries: number = 3
  ): Promise<T> {
    let attempt = 0;
    
    while (attempt <= maxRetries) {
      try {
        return await operation();
      } catch (error) {
        if (!this.shouldRetry(error) || attempt === maxRetries) {
          throw error;
        }
        
        const delay = this.calculateDelay(attempt, error);
        await this.delay(delay);
        attempt++;
      }
    }
    
    throw new Error('Max retries exceeded');
  }
  
  private shouldRetry(error: any): boolean {
    if (error instanceof stripe.errors.StripeRateLimitError) {
      return true;
    }
    
    if (error instanceof stripe.errors.StripeAPIError) {
      return error.statusCode >= 500;
    }
    
    if (error instanceof stripe.errors.StripeConnectionError) {
      return true;
    }
    
    return false;
  }
  
  private calculateDelay(attempt: number, error: any): number {
    // Use Stripe's Retry-After header if available
    if (error instanceof stripe.errors.StripeRateLimitError) {
      const retryAfter = error.headers?.['retry-after'];
      if (retryAfter) {
        return parseInt(retryAfter) * 1000;
      }
    }
    
    // Exponential backoff with jitter
    const baseDelay = Math.pow(2, attempt) * 1000;
    const jitter = Math.random() * 1000;
    return baseDelay + jitter;
  }
  
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const retryHandler = new StripeRetryHandler();

const customer = await retryHandler.withRetry(() => 
  stripe.customers.create({
    email: 'customer@example.com'
  })
);
```

## Advanced Configuration

### App Information

Configure application metadata for better support:

```typescript { .api }
interface AppInfo {
  name: string;
  version?: string;
  url?: string;
  partner_id?: string;
}

// Plugin/framework identification
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  appInfo: {
    name: 'MyEcommercePlugin',
    version: '2.1.0',
    url: 'https://github.com/mycompany/ecommerce-plugin',
    partner_id: 'pp_partner_123'
  }
});

// Dynamic app info based on environment
const getAppInfo = (): AppInfo => {
  const packageJson = require('./package.json');
  
  return {
    name: packageJson.name,
    version: packageJson.version,
    url: packageJson.homepage
  };
};

const stripeWithDynamicInfo = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  appInfo: getAppInfo()
});
```

### Telemetry Configuration

Control telemetry data collection:

```typescript { .api }
// Disable telemetry for privacy-sensitive applications
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  telemetry: false
});

// Conditional telemetry based on environment
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2025-08-27.basil',
  telemetry: process.env.NODE_ENV === 'production'
});
```

### Event Monitoring

Set up request/response monitoring:

```typescript { .api }
// Request monitoring
stripe.on('request', (event: Stripe.RequestEvent) => {
  console.log('Request made:', {
    method: event.method,
    url: event.url,
    requestId: event.request_id
  });
  
  // Log to monitoring service
  monitoring.logRequest({
    method: event.method,
    path: event.path,
    requestId: event.request_id,
    timestamp: new Date()
  });
});

// Response monitoring
stripe.on('response', (event: Stripe.ResponseEvent) => {
  console.log('Response received:', {
    status: event.status_code,
    requestId: event.request_id,
    elapsed: event.elapsed
  });
  
  // Track performance metrics
  metrics.timing('stripe.request_duration', event.elapsed, {
    status_code: event.status_code.toString(),
    method: event.method
  });
  
  // Alert on errors
  if (event.status_code >= 400) {
    alerting.notifyError('Stripe API Error', {
      statusCode: event.status_code,
      requestId: event.request_id,
      elapsed: event.elapsed
    });
  }
});

// One-time event listeners
stripe.once('request', (event) => {
  console.log('First request made:', event.request_id);
});

// Remove event listeners
const requestHandler = (event: Stripe.RequestEvent) => {
  console.log('Request:', event.request_id);
};

stripe.on('request', requestHandler);
// Later...
stripe.off('request', requestHandler);
```

## Environment-Specific Configuration

### Multi-Environment Setup

Configure Stripe for different environments:

```typescript { .api }
interface StripeEnvironmentConfig {
  apiKey: string;
  webhookSecret: string;
  publishableKey: string;
  connectClientId?: string;
}

class StripeConfigManager {
  private configs: Record<string, StripeEnvironmentConfig> = {
    development: {
      apiKey: process.env.STRIPE_TEST_SECRET_KEY!,
      webhookSecret: process.env.STRIPE_TEST_WEBHOOK_SECRET!,
      publishableKey: process.env.STRIPE_TEST_PUBLISHABLE_KEY!,
      connectClientId: process.env.STRIPE_TEST_CONNECT_CLIENT_ID
    },
    staging: {
      apiKey: process.env.STRIPE_STAGING_SECRET_KEY!,
      webhookSecret: process.env.STRIPE_STAGING_WEBHOOK_SECRET!,
      publishableKey: process.env.STRIPE_STAGING_PUBLISHABLE_KEY!,
      connectClientId: process.env.STRIPE_STAGING_CONNECT_CLIENT_ID
    },
    production: {
      apiKey: process.env.STRIPE_LIVE_SECRET_KEY!,
      webhookSecret: process.env.STRIPE_LIVE_WEBHOOK_SECRET!,
      publishableKey: process.env.STRIPE_LIVE_PUBLISHABLE_KEY!,
      connectClientId: process.env.STRIPE_LIVE_CONNECT_CLIENT_ID
    }
  };
  
  createStripeInstance(environment: string = process.env.NODE_ENV || 'development'): Stripe {
    const config = this.configs[environment];
    
    if (!config) {
      throw new Error(`No Stripe configuration found for environment: ${environment}`);
    }
    
    return new Stripe(config.apiKey, {
      apiVersion: '2025-08-27.basil',
      typescript: true,
      maxNetworkRetries: environment === 'production' ? 3 : 1,
      timeout: environment === 'production' ? 30000 : 10000,
      telemetry: environment === 'production',
      appInfo: {
        name: 'MyApp',
        version: process.env.APP_VERSION || '1.0.0'
      }
    });
  }
  
  getConfig(environment: string = process.env.NODE_ENV || 'development'): StripeEnvironmentConfig {
    return this.configs[environment];
  }
}

// Usage
const configManager = new StripeConfigManager();
const stripe = configManager.createStripeInstance();
const config = configManager.getConfig();
```

### Security Best Practices

Implement security best practices for configuration:

```typescript { .api }
// Secure configuration loading
class SecureStripeConfig {
  private static instance: SecureStripeConfig;
  private stripe: Stripe;
  
  private constructor() {
    // Validate required environment variables
    this.validateEnvironment();
    
    // Create Stripe instance with security measures
    this.stripe = new Stripe(this.getSecureApiKey(), {
      apiVersion: '2025-08-27.basil',
      typescript: true,
      telemetry: this.isTelemetryEnabled(),
      timeout: this.getTimeout(),
      maxNetworkRetries: this.getMaxRetries()
    });
    
    // Set up security monitoring
    this.setupSecurityMonitoring();
  }
  
  static getInstance(): SecureStripeConfig {
    if (!SecureStripeConfig.instance) {
      SecureStripeConfig.instance = new SecureStripeConfig();
    }
    return SecureStripeConfig.instance;
  }
  
  getStripe(): Stripe {
    return this.stripe;
  }
  
  private validateEnvironment(): void {
    const required = ['STRIPE_SECRET_KEY'];
    const missing = required.filter(key => !process.env[key]);
    
    if (missing.length > 0) {
      throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
    }
    
    // Validate API key format
    const apiKey = process.env.STRIPE_SECRET_KEY!;
    if (!apiKey.startsWith('sk_')) {
      throw new Error('Invalid Stripe API key format');
    }
    
    // Warn about test keys in production
    if (process.env.NODE_ENV === 'production' && apiKey.includes('test')) {
      throw new Error('Test API key detected in production environment');
    }
  }
  
  private getSecureApiKey(): string {
    const apiKey = process.env.STRIPE_SECRET_KEY!;
    
    // Additional security checks
    if (apiKey.length < 32) {
      throw new Error('API key appears to be invalid');
    }
    
    return apiKey;
  }
  
  private setupSecurityMonitoring(): void {
    // Monitor for suspicious patterns
    this.stripe.on('request', (event) => {
      // Log all API requests for security audit
      securityLogger.log('stripe_request', {
        method: event.method,
        url: event.url,
        requestId: event.request_id,
        timestamp: new Date(),
        userAgent: event.user_agent
      });
    });
  }
  
  private isTelemetryEnabled(): boolean {
    return process.env.STRIPE_TELEMETRY !== 'false';
  }
  
  private getTimeout(): number {
    return parseInt(process.env.STRIPE_TIMEOUT || '30000');
  }
  
  private getMaxRetries(): number {
    return parseInt(process.env.STRIPE_MAX_RETRIES || '3');
  }
}

// Usage
const secureConfig = SecureStripeConfig.getInstance();
const stripe = secureConfig.getStripe();
```

This comprehensive configuration system provides the foundation for robust, secure, and maintainable Stripe integrations across all environments and use cases.