or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

billing.mdcheckout.mdconfiguration.mdcore-resources.mdidentity.mdindex.mdissuing.mdradar.mdsubscriptions.mdtax.mdterminal.mdtreasury.mdwebhooks.md

configuration.mddocs/

0

# Configuration

1

2

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.

3

4

## Basic Configuration

5

6

### API Key Authentication

7

8

The primary method for authenticating with Stripe:

9

10

```typescript { .api }

11

import Stripe from 'stripe';

12

13

// Basic initialization with API key

14

const stripe = new Stripe('sk_test_...', {

15

apiVersion: '2025-08-27.basil',

16

typescript: true

17

});

18

19

// Environment-based configuration

20

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

21

apiVersion: '2025-08-27.basil',

22

typescript: true

23

});

24

25

// Different keys for different environments

26

const apiKey = process.env.NODE_ENV === 'production'

27

? process.env.STRIPE_LIVE_SECRET_KEY

28

: process.env.STRIPE_TEST_SECRET_KEY;

29

30

const stripe = new Stripe(apiKey!, {

31

apiVersion: '2025-08-27.basil',

32

typescript: true

33

});

34

```

35

36

### Configuration Interface

37

38

Complete configuration options available:

39

40

```typescript { .api }

41

interface StripeConfig {

42

// API Configuration

43

apiVersion?: '2025-08-27.basil'; // Latest stable API version

44

typescript?: true; // Enable TypeScript support

45

46

// Network Configuration

47

maxNetworkRetries?: number; // Default: 1, max: 10

48

timeout?: number; // Request timeout in ms (default: 80000)

49

httpAgent?: HttpAgent; // Custom HTTP agent for proxies

50

httpClient?: HttpClient; // Custom HTTP client implementation

51

52

// Host Configuration

53

host?: string; // API host override (default: api.stripe.com)

54

port?: string | number; // API port override (default: 443)

55

protocol?: 'http' | 'https'; // Protocol override (default: https)

56

57

// Feature Configuration

58

telemetry?: boolean; // Enable/disable telemetry (default: true)

59

appInfo?: AppInfo; // Plugin identification

60

61

// Account Configuration

62

stripeAccount?: string; // Connect account for all requests

63

stripeContext?: string; // Context for all requests

64

}

65

66

// Advanced configuration example

67

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

68

apiVersion: '2025-08-27.basil',

69

typescript: true,

70

maxNetworkRetries: 3,

71

timeout: 30000, // 30 seconds

72

telemetry: false,

73

appInfo: {

74

name: 'MyApp',

75

version: '1.0.0',

76

url: 'https://myapp.com'

77

}

78

});

79

```

80

81

## Network Configuration

82

83

### HTTP Agents and Proxies

84

85

Configure HTTP agents for proxy support and connection pooling:

86

87

```typescript { .api }

88

import { HttpsAgent } from 'agentkeepalive';

89

import { Agent as HttpAgent } from 'http';

90

import { Agent as HttpsProxyAgent } from 'https-proxy-agent';

91

92

// Keep-alive agent for better performance

93

const keepAliveAgent = new HttpsAgent({

94

keepAlive: true,

95

maxSockets: 100,

96

maxFreeSockets: 10,

97

timeout: 60000,

98

freeSocketTimeout: 30000

99

});

100

101

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

102

httpAgent: keepAliveAgent,

103

apiVersion: '2025-08-27.basil'

104

});

105

106

// Proxy configuration

107

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

108

109

const stripeWithProxy = new Stripe(process.env.STRIPE_SECRET_KEY!, {

110

httpAgent: proxyAgent,

111

apiVersion: '2025-08-27.basil'

112

});

113

114

// Custom HTTP client implementation

115

class CustomHttpClient {

116

makeRequest(

117

host: string,

118

port: number,

119

path: string,

120

method: string,

121

headers: { [key: string]: string },

122

requestData: string,

123

protocol: string,

124

timeout: number

125

): Promise<any> {

126

// Custom implementation with logging, metrics, etc.

127

return fetch(`${protocol}://${host}:${port}${path}`, {

128

method,

129

headers,

130

body: requestData,

131

signal: AbortSignal.timeout(timeout)

132

}).then(response => ({

133

status: response.status,

134

headers: Object.fromEntries(response.headers.entries()),

135

body: response.text()

136

}));

137

}

138

}

139

140

const stripeWithCustomClient = new Stripe(process.env.STRIPE_SECRET_KEY!, {

141

httpClient: new CustomHttpClient(),

142

apiVersion: '2025-08-27.basil'

143

});

144

```

145

146

### Retry Configuration

147

148

Configure automatic retry behavior for failed requests:

149

150

```typescript { .api }

151

// Global retry configuration

152

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

153

maxNetworkRetries: 5, // Retry up to 5 times

154

apiVersion: '2025-08-27.basil'

155

});

156

157

// Per-request retry override

158

const customer = await stripe.customers.create({

159

email: 'customer@example.com'

160

}, {

161

maxNetworkRetries: 2 // Override global setting

162

});

163

164

// Custom retry logic with exponential backoff

165

class RetryableHttpClient {

166

async makeRequest(...args: any[]): Promise<any> {

167

const maxRetries = 3;

168

let attempt = 0;

169

170

while (attempt <= maxRetries) {

171

try {

172

return await this.performRequest(...args);

173

} catch (error) {

174

if (attempt === maxRetries || !this.shouldRetry(error)) {

175

throw error;

176

}

177

178

const delay = Math.pow(2, attempt) * 1000; // Exponential backoff

179

await new Promise(resolve => setTimeout(resolve, delay));

180

attempt++;

181

}

182

}

183

}

184

185

private shouldRetry(error: any): boolean {

186

// Retry on network errors and 5xx status codes

187

return error.code === 'ECONNRESET' ||

188

error.code === 'ENOTFOUND' ||

189

(error.statusCode >= 500 && error.statusCode < 600);

190

}

191

192

private async performRequest(...args: any[]): Promise<any> {

193

// Actual HTTP request implementation

194

}

195

}

196

```

197

198

### Timeout Configuration

199

200

Configure request timeouts at various levels:

201

202

```typescript { .api }

203

// Global timeout configuration

204

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

205

timeout: 15000, // 15 seconds for all requests

206

apiVersion: '2025-08-27.basil'

207

});

208

209

// Per-request timeout

210

const paymentIntent = await stripe.paymentIntents.create({

211

amount: 2000,

212

currency: 'usd'

213

}, {

214

timeout: 30000 // 30 seconds for this specific request

215

});

216

217

// Different timeouts for different operations

218

class TimeoutManager {

219

private readonly timeouts = {

220

create: 30000, // 30s for creates

221

update: 20000, // 20s for updates

222

list: 10000, // 10s for lists

223

retrieve: 5000 // 5s for retrievals

224

};

225

226

getTimeout(operation: keyof typeof this.timeouts): number {

227

return this.timeouts[operation];

228

}

229

}

230

231

const timeoutManager = new TimeoutManager();

232

233

// Use operation-specific timeouts

234

const customer = await stripe.customers.create({

235

email: 'customer@example.com'

236

}, {

237

timeout: timeoutManager.getTimeout('create')

238

});

239

```

240

241

## Request Options

242

243

### Per-Request Configuration

244

245

Override global settings for individual requests:

246

247

```typescript { .api }

248

interface RequestOptions {

249

apiKey?: string; // Override API key

250

idempotencyKey?: string; // Idempotency key for safe retries

251

stripeAccount?: string; // Connect account

252

stripeContext?: string; // Request context

253

apiVersion?: string; // API version override

254

maxNetworkRetries?: number; // Retry limit override

255

timeout?: number; // Timeout override

256

host?: string; // Host override

257

}

258

259

// API key override for multi-tenant applications

260

const platformCustomer = await stripe.customers.create({

261

email: 'platform@example.com'

262

}, {

263

apiKey: process.env.PLATFORM_SECRET_KEY

264

});

265

266

// Connect account operations

267

const connectedAccountCharge = await stripe.charges.create({

268

amount: 2000,

269

currency: 'usd',

270

source: 'tok_visa'

271

}, {

272

stripeAccount: 'acct_connected_account_id'

273

});

274

275

// Idempotency for safe retries

276

const idempotentPayment = await stripe.paymentIntents.create({

277

amount: 2000,

278

currency: 'usd'

279

}, {

280

idempotencyKey: `payment_${orderId}_${timestamp}`

281

});

282

283

// Context for request tracking

284

const contextualRequest = await stripe.customers.create({

285

email: 'customer@example.com'

286

}, {

287

stripeContext: 'signup_flow_step_3'

288

});

289

```

290

291

### Idempotency Management

292

293

Implement robust idempotency for reliable operations:

294

295

```typescript { .api }

296

class IdempotencyManager {

297

private generateKey(prefix: string, data: any): string {

298

const hash = require('crypto')

299

.createHash('sha256')

300

.update(JSON.stringify(data))

301

.digest('hex')

302

.substring(0, 16);

303

304

return `${prefix}_${Date.now()}_${hash}`;

305

}

306

307

async createPaymentIntent(params: Stripe.PaymentIntentCreateParams): Promise<Stripe.PaymentIntent> {

308

const idempotencyKey = this.generateKey('pi', params);

309

310

return stripe.paymentIntents.create(params, {

311

idempotencyKey

312

});

313

}

314

315

async createCustomer(params: Stripe.CustomerCreateParams): Promise<Stripe.Customer> {

316

// Use email as part of idempotency key for customers

317

const keyData = { email: params.email, name: params.name };

318

const idempotencyKey = this.generateKey('cus', keyData);

319

320

return stripe.customers.create(params, {

321

idempotencyKey

322

});

323

}

324

}

325

```

326

327

## Error Handling

328

329

### Error Types and Handling

330

331

Comprehensive error handling for different Stripe error types:

332

333

```typescript { .api }

334

// All Stripe error types

335

interface StripeErrorTypes {

336

StripeError: typeof Stripe.errors.StripeError;

337

StripeCardError: typeof Stripe.errors.StripeCardError;

338

StripeInvalidRequestError: typeof Stripe.errors.StripeInvalidRequestError;

339

StripeAPIError: typeof Stripe.errors.StripeAPIError;

340

StripeAuthenticationError: typeof Stripe.errors.StripeAuthenticationError;

341

StripePermissionError: typeof Stripe.errors.StripePermissionError;

342

StripeRateLimitError: typeof Stripe.errors.StripeRateLimitError;

343

StripeConnectionError: typeof Stripe.errors.StripeConnectionError;

344

StripeSignatureVerificationError: typeof Stripe.errors.StripeSignatureVerificationError;

345

StripeIdempotencyError: typeof Stripe.errors.StripeIdempotencyError;

346

StripeInvalidGrantError: typeof Stripe.errors.StripeInvalidGrantError;

347

StripeUnknownError: typeof Stripe.errors.StripeUnknownError;

348

}

349

350

// Comprehensive error handling function

351

async function handleStripeOperation<T>(operation: () => Promise<T>): Promise<T> {

352

try {

353

return await operation();

354

} catch (error) {

355

if (error instanceof stripe.errors.StripeCardError) {

356

// Card was declined

357

throw new PaymentError(

358

'Card declined',

359

error.decline_code,

360

error.code,

361

error.payment_intent?.id

362

);

363

} else if (error instanceof stripe.errors.StripeInvalidRequestError) {

364

// Invalid parameters

365

throw new ValidationError(

366

'Invalid request',

367

error.param,

368

error.code

369

);

370

} else if (error instanceof stripe.errors.StripeAuthenticationError) {

371

// Authentication failed

372

throw new AuthError('Authentication failed', error.code);

373

} else if (error instanceof stripe.errors.StripePermissionError) {

374

// Insufficient permissions

375

throw new AuthorizationError('Insufficient permissions', error.code);

376

} else if (error instanceof stripe.errors.StripeRateLimitError) {

377

// Rate limited

378

throw new RateLimitError('Rate limit exceeded', error.code);

379

} else if (error instanceof stripe.errors.StripeConnectionError) {

380

// Network error

381

throw new NetworkError('Network error', error.code);

382

} else if (error instanceof stripe.errors.StripeAPIError) {

383

// API error

384

throw new APIError('API error', error.code, error.statusCode);

385

} else {

386

// Unknown error

387

throw new UnknownError('Unknown error', error);

388

}

389

}

390

}

391

392

// Usage example with proper error handling

393

async function processPayment(paymentIntentId: string): Promise<PaymentResult> {

394

return handleStripeOperation(async () => {

395

const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId);

396

397

if (paymentIntent.status === 'requires_payment_method') {

398

throw new Error('Payment method required');

399

}

400

401

const confirmed = await stripe.paymentIntents.confirm(paymentIntentId);

402

403

return {

404

success: true,

405

paymentIntent: confirmed

406

};

407

});

408

}

409

```

410

411

### Retry Logic for Errors

412

413

Implement intelligent retry logic based on error types:

414

415

```typescript { .api }

416

class StripeRetryHandler {

417

private readonly retryableErrors = [

418

'rate_limit',

419

'api_connection_error',

420

'api_error'

421

];

422

423

async withRetry<T>(

424

operation: () => Promise<T>,

425

maxRetries: number = 3

426

): Promise<T> {

427

let attempt = 0;

428

429

while (attempt <= maxRetries) {

430

try {

431

return await operation();

432

} catch (error) {

433

if (!this.shouldRetry(error) || attempt === maxRetries) {

434

throw error;

435

}

436

437

const delay = this.calculateDelay(attempt, error);

438

await this.delay(delay);

439

attempt++;

440

}

441

}

442

443

throw new Error('Max retries exceeded');

444

}

445

446

private shouldRetry(error: any): boolean {

447

if (error instanceof stripe.errors.StripeRateLimitError) {

448

return true;

449

}

450

451

if (error instanceof stripe.errors.StripeAPIError) {

452

return error.statusCode >= 500;

453

}

454

455

if (error instanceof stripe.errors.StripeConnectionError) {

456

return true;

457

}

458

459

return false;

460

}

461

462

private calculateDelay(attempt: number, error: any): number {

463

// Use Stripe's Retry-After header if available

464

if (error instanceof stripe.errors.StripeRateLimitError) {

465

const retryAfter = error.headers?.['retry-after'];

466

if (retryAfter) {

467

return parseInt(retryAfter) * 1000;

468

}

469

}

470

471

// Exponential backoff with jitter

472

const baseDelay = Math.pow(2, attempt) * 1000;

473

const jitter = Math.random() * 1000;

474

return baseDelay + jitter;

475

}

476

477

private delay(ms: number): Promise<void> {

478

return new Promise(resolve => setTimeout(resolve, ms));

479

}

480

}

481

482

// Usage

483

const retryHandler = new StripeRetryHandler();

484

485

const customer = await retryHandler.withRetry(() =>

486

stripe.customers.create({

487

email: 'customer@example.com'

488

})

489

);

490

```

491

492

## Advanced Configuration

493

494

### App Information

495

496

Configure application metadata for better support:

497

498

```typescript { .api }

499

interface AppInfo {

500

name: string;

501

version?: string;

502

url?: string;

503

partner_id?: string;

504

}

505

506

// Plugin/framework identification

507

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

508

apiVersion: '2025-08-27.basil',

509

appInfo: {

510

name: 'MyEcommercePlugin',

511

version: '2.1.0',

512

url: 'https://github.com/mycompany/ecommerce-plugin',

513

partner_id: 'pp_partner_123'

514

}

515

});

516

517

// Dynamic app info based on environment

518

const getAppInfo = (): AppInfo => {

519

const packageJson = require('./package.json');

520

521

return {

522

name: packageJson.name,

523

version: packageJson.version,

524

url: packageJson.homepage

525

};

526

};

527

528

const stripeWithDynamicInfo = new Stripe(process.env.STRIPE_SECRET_KEY!, {

529

apiVersion: '2025-08-27.basil',

530

appInfo: getAppInfo()

531

});

532

```

533

534

### Telemetry Configuration

535

536

Control telemetry data collection:

537

538

```typescript { .api }

539

// Disable telemetry for privacy-sensitive applications

540

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

541

apiVersion: '2025-08-27.basil',

542

telemetry: false

543

});

544

545

// Conditional telemetry based on environment

546

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {

547

apiVersion: '2025-08-27.basil',

548

telemetry: process.env.NODE_ENV === 'production'

549

});

550

```

551

552

### Event Monitoring

553

554

Set up request/response monitoring:

555

556

```typescript { .api }

557

// Request monitoring

558

stripe.on('request', (event: Stripe.RequestEvent) => {

559

console.log('Request made:', {

560

method: event.method,

561

url: event.url,

562

requestId: event.request_id

563

});

564

565

// Log to monitoring service

566

monitoring.logRequest({

567

method: event.method,

568

path: event.path,

569

requestId: event.request_id,

570

timestamp: new Date()

571

});

572

});

573

574

// Response monitoring

575

stripe.on('response', (event: Stripe.ResponseEvent) => {

576

console.log('Response received:', {

577

status: event.status_code,

578

requestId: event.request_id,

579

elapsed: event.elapsed

580

});

581

582

// Track performance metrics

583

metrics.timing('stripe.request_duration', event.elapsed, {

584

status_code: event.status_code.toString(),

585

method: event.method

586

});

587

588

// Alert on errors

589

if (event.status_code >= 400) {

590

alerting.notifyError('Stripe API Error', {

591

statusCode: event.status_code,

592

requestId: event.request_id,

593

elapsed: event.elapsed

594

});

595

}

596

});

597

598

// One-time event listeners

599

stripe.once('request', (event) => {

600

console.log('First request made:', event.request_id);

601

});

602

603

// Remove event listeners

604

const requestHandler = (event: Stripe.RequestEvent) => {

605

console.log('Request:', event.request_id);

606

};

607

608

stripe.on('request', requestHandler);

609

// Later...

610

stripe.off('request', requestHandler);

611

```

612

613

## Environment-Specific Configuration

614

615

### Multi-Environment Setup

616

617

Configure Stripe for different environments:

618

619

```typescript { .api }

620

interface StripeEnvironmentConfig {

621

apiKey: string;

622

webhookSecret: string;

623

publishableKey: string;

624

connectClientId?: string;

625

}

626

627

class StripeConfigManager {

628

private configs: Record<string, StripeEnvironmentConfig> = {

629

development: {

630

apiKey: process.env.STRIPE_TEST_SECRET_KEY!,

631

webhookSecret: process.env.STRIPE_TEST_WEBHOOK_SECRET!,

632

publishableKey: process.env.STRIPE_TEST_PUBLISHABLE_KEY!,

633

connectClientId: process.env.STRIPE_TEST_CONNECT_CLIENT_ID

634

},

635

staging: {

636

apiKey: process.env.STRIPE_STAGING_SECRET_KEY!,

637

webhookSecret: process.env.STRIPE_STAGING_WEBHOOK_SECRET!,

638

publishableKey: process.env.STRIPE_STAGING_PUBLISHABLE_KEY!,

639

connectClientId: process.env.STRIPE_STAGING_CONNECT_CLIENT_ID

640

},

641

production: {

642

apiKey: process.env.STRIPE_LIVE_SECRET_KEY!,

643

webhookSecret: process.env.STRIPE_LIVE_WEBHOOK_SECRET!,

644

publishableKey: process.env.STRIPE_LIVE_PUBLISHABLE_KEY!,

645

connectClientId: process.env.STRIPE_LIVE_CONNECT_CLIENT_ID

646

}

647

};

648

649

createStripeInstance(environment: string = process.env.NODE_ENV || 'development'): Stripe {

650

const config = this.configs[environment];

651

652

if (!config) {

653

throw new Error(`No Stripe configuration found for environment: ${environment}`);

654

}

655

656

return new Stripe(config.apiKey, {

657

apiVersion: '2025-08-27.basil',

658

typescript: true,

659

maxNetworkRetries: environment === 'production' ? 3 : 1,

660

timeout: environment === 'production' ? 30000 : 10000,

661

telemetry: environment === 'production',

662

appInfo: {

663

name: 'MyApp',

664

version: process.env.APP_VERSION || '1.0.0'

665

}

666

});

667

}

668

669

getConfig(environment: string = process.env.NODE_ENV || 'development'): StripeEnvironmentConfig {

670

return this.configs[environment];

671

}

672

}

673

674

// Usage

675

const configManager = new StripeConfigManager();

676

const stripe = configManager.createStripeInstance();

677

const config = configManager.getConfig();

678

```

679

680

### Security Best Practices

681

682

Implement security best practices for configuration:

683

684

```typescript { .api }

685

// Secure configuration loading

686

class SecureStripeConfig {

687

private static instance: SecureStripeConfig;

688

private stripe: Stripe;

689

690

private constructor() {

691

// Validate required environment variables

692

this.validateEnvironment();

693

694

// Create Stripe instance with security measures

695

this.stripe = new Stripe(this.getSecureApiKey(), {

696

apiVersion: '2025-08-27.basil',

697

typescript: true,

698

telemetry: this.isTelemetryEnabled(),

699

timeout: this.getTimeout(),

700

maxNetworkRetries: this.getMaxRetries()

701

});

702

703

// Set up security monitoring

704

this.setupSecurityMonitoring();

705

}

706

707

static getInstance(): SecureStripeConfig {

708

if (!SecureStripeConfig.instance) {

709

SecureStripeConfig.instance = new SecureStripeConfig();

710

}

711

return SecureStripeConfig.instance;

712

}

713

714

getStripe(): Stripe {

715

return this.stripe;

716

}

717

718

private validateEnvironment(): void {

719

const required = ['STRIPE_SECRET_KEY'];

720

const missing = required.filter(key => !process.env[key]);

721

722

if (missing.length > 0) {

723

throw new Error(`Missing required environment variables: ${missing.join(', ')}`);

724

}

725

726

// Validate API key format

727

const apiKey = process.env.STRIPE_SECRET_KEY!;

728

if (!apiKey.startsWith('sk_')) {

729

throw new Error('Invalid Stripe API key format');

730

}

731

732

// Warn about test keys in production

733

if (process.env.NODE_ENV === 'production' && apiKey.includes('test')) {

734

throw new Error('Test API key detected in production environment');

735

}

736

}

737

738

private getSecureApiKey(): string {

739

const apiKey = process.env.STRIPE_SECRET_KEY!;

740

741

// Additional security checks

742

if (apiKey.length < 32) {

743

throw new Error('API key appears to be invalid');

744

}

745

746

return apiKey;

747

}

748

749

private setupSecurityMonitoring(): void {

750

// Monitor for suspicious patterns

751

this.stripe.on('request', (event) => {

752

// Log all API requests for security audit

753

securityLogger.log('stripe_request', {

754

method: event.method,

755

url: event.url,

756

requestId: event.request_id,

757

timestamp: new Date(),

758

userAgent: event.user_agent

759

});

760

});

761

}

762

763

private isTelemetryEnabled(): boolean {

764

return process.env.STRIPE_TELEMETRY !== 'false';

765

}

766

767

private getTimeout(): number {

768

return parseInt(process.env.STRIPE_TIMEOUT || '30000');

769

}

770

771

private getMaxRetries(): number {

772

return parseInt(process.env.STRIPE_MAX_RETRIES || '3');

773

}

774

}

775

776

// Usage

777

const secureConfig = SecureStripeConfig.getInstance();

778

const stripe = secureConfig.getStripe();

779

```

780

781

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