Skip to content

API Integration - Cursor IDE

Your company needs to integrate with Stripe for payments, SendGrid for emails, and Twilio for SMS notifications. The previous developer started but left incomplete code with no documentation. You need to build a unified notification system that handles payments, sends receipts via email, and notifies users via SMS - all with proper error handling and retry logic.

By completing this lesson, you’ll master:

  • Analyzing and integrating third-party APIs efficiently
  • Building robust error handling and retry mechanisms
  • Creating unified interfaces for multiple services
  • Implementing proper authentication and security
  • Testing external API integrations
  • Monitoring and debugging API issues
  • Basic understanding of REST APIs
  • Node.js and TypeScript knowledge
  • Completed previous lessons or equivalent experience
  • API keys for services (or use mock APIs)
  • Optional: MCP servers for GitHub, Linear, or Jira (see MCP setup)

Build a production-ready integration that:

  • Handles multiple API providers gracefully
  • Implements exponential backoff for retries
  • Provides fallback mechanisms
  • Maintains security best practices
  • Includes comprehensive logging
  • Supports both sync and async operations
  1. Analyze Existing Code

Start with Ask mode to understand what exists:

@src/integrations
"Analyze the existing integration code:
- What APIs are partially implemented?
- What's the current architecture?
- What error handling exists?
- What's missing for production use?
- Security vulnerabilities?"
  1. Research API Documentation
"Help me understand these APIs:
- Stripe: Payment processing flow
- SendGrid: Email API best practices
- Twilio: SMS delivery guarantees
Create a comparison of rate limits, auth methods, and error codes"
  1. Design Unified Architecture

Switch to Agent mode:

"Design a unified notification system architecture:
- Abstract interface for all notifications
- Provider-specific implementations
- Retry and fallback strategies
- Configuration management
- Error handling patterns
Create architecture diagram and interfaces"

Phase 1.5: Leveraging MCP Servers for API Integration

Section titled “Phase 1.5: Leveraging MCP Servers for API Integration”
  1. Available API MCP Servers

Many APIs already have MCP servers available:

Terminal window
# GitHub MCP - Full GitHub API access
claude mcp add --transport sse github https://api.githubcopilot.com/mcp/
# Linear MCP - Issue tracking
claude mcp add --transport sse linear https://mcp.linear.app/sse
# Jira MCP - Atlassian integration
# Note: Atlassian's official endpoint is https://mcp.atlassian.com/v1/sse (Beta)
# For local setup, use community packages:
claude mcp add jira -- npx -y @mcp-devtools/jira
# Slack MCP - Messaging integration
claude mcp add slack -- npx -y @modelcontextprotocol/server-slack
  1. Using MCP for API Discovery

With GitHub MCP installed:

"Using GitHub MCP, show me:
- How to create issues programmatically
- Webhook setup for PR events
- Rate limit handling
- GraphQL query examples"
// MCP provides direct API access:
"Create a GitHub issue in repo 'myorg/myrepo' with:
- Title: 'Payment integration failing'
- Labels: ['bug', 'high-priority']
- Assignee: '@username'"
  1. MCP vs Direct API Integration
// Direct tool usage via MCP
"Using Linear MCP:
- Create issue in project 'API Integration'
- Set priority to urgent
- Add to current sprint"
// MCP handles:
// - Authentication
// - Rate limiting
// - Error retry
// - Response parsing
  1. Orchestrating Multiple MCPs
"Coordinate between multiple MCP servers:
1. When a Stripe payment succeeds (using our integration)
2. Create a Linear issue for fulfillment (Linear MCP)
3. Post to #sales Slack channel (Slack MCP)
4. Update customer record in database"
// The AI can use multiple MCPs in sequence
  1. MCP for API Documentation
"Using Context7 MCP, get the latest docs for:
- Stripe Node.js SDK
- SendGrid API v3
- Twilio webhooks
Compare with our current implementation"

When to Use MCP Servers vs Custom Integration

Section titled “When to Use MCP Servers vs Custom Integration”

Use MCP Servers when:

  • Official MCP server exists for the API
  • You need quick prototyping
  • Standard API operations suffice
  • You want maintained integrations

Build Custom when:

  • No MCP server available
  • Need custom error handling
  • Complex orchestration required
  • Performance optimization critical
  1. Create Base Integration Class
"Create a base integration class with:
- Retry logic with exponential backoff
- Circuit breaker pattern
- Request/response logging
- Error standardization
- Metrics collection
- Rate limiting support"

Example base class:

integrations/base.ts
export abstract class BaseIntegration {
protected abstract readonly name: string;
protected abstract readonly baseURL: string;
protected abstract readonly maxRetries: number;
private circuitBreaker: CircuitBreaker;
private metrics: MetricsCollector;
constructor(protected config: IntegrationConfig) {
this.circuitBreaker = new CircuitBreaker({
timeout: config.timeout || 30000,
errorThreshold: config.errorThreshold || 50,
resetTimeout: config.resetTimeout || 60000
});
this.metrics = new MetricsCollector(this.name);
}
protected async makeRequest<T>(
method: string,
endpoint: string,
data?: any,
options: RequestOptions = {}
): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
return this.circuitBreaker.execute(async () => {
const startTime = Date.now();
try {
const response = await this.executeWithRetry(
method,
url,
data,
options
);
this.metrics.recordSuccess(Date.now() - startTime);
return response;
} catch (error) {
this.metrics.recordError(error);
throw this.standardizeError(error);
}
});
}
private async executeWithRetry<T>(
method: string,
url: string,
data?: any,
options: RequestOptions = {}
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
if (attempt > 0) {
await this.delay(this.calculateBackoff(attempt));
}
return await this.executeRequest<T>(method, url, data, options);
} catch (error) {
lastError = error;
if (!this.isRetryable(error) || attempt === this.maxRetries) {
throw error;
}
logger.warn(`Retry attempt ${attempt + 1} for ${url}`, { error });
}
}
throw lastError!;
}
private calculateBackoff(attempt: number): number {
const baseDelay = 1000;
const maxDelay = 32000;
const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
return delay + Math.random() * 1000; // Add jitter
}
protected abstract isRetryable(error: any): boolean;
protected abstract standardizeError(error: any): IntegrationError;
}
  1. Implement Provider-Specific Classes
@integrations/base.ts
"Create provider implementations for:
1. StripeIntegration extending BaseIntegration
2. SendGridIntegration extending BaseIntegration
3. TwilioIntegration extending BaseIntegration
Include proper auth, error handling, and API-specific features"
  1. Create Unified Notification Service
"Create a NotificationService that:
- Orchestrates all three services
- Handles payment → email → SMS flow
- Implements fallback strategies
- Provides transaction-like behavior
- Supports bulk operations"
  1. Implement Secure Configuration
"Create secure configuration management:
- Environment-based config loading
- Encrypted API key storage
- Key rotation support
- Configuration validation
- Runtime config updates"

Example configuration:

config/integrations.ts
export class IntegrationConfig {
private static instance: IntegrationConfig;
private configs: Map<string, ProviderConfig> = new Map();
private constructor() {
this.loadConfigurations();
this.validateConfigurations();
this.setupKeyRotation();
}
static getInstance(): IntegrationConfig {
if (!IntegrationConfig.instance) {
IntegrationConfig.instance = new IntegrationConfig();
}
return IntegrationConfig.instance;
}
getConfig(provider: string): ProviderConfig {
const config = this.configs.get(provider);
if (!config) {
throw new Error(`Configuration not found for provider: ${provider}`);
}
// Decrypt API keys on demand
return {
...config,
apiKey: this.decryptKey(config.encryptedApiKey)
};
}
private loadConfigurations() {
// Load from environment variables or secure storage
this.configs.set('stripe', {
encryptedApiKey: process.env.STRIPE_API_KEY_ENCRYPTED!,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
apiVersion: '2023-10-16',
timeout: 30000,
maxRetries: 3
});
// Similar for SendGrid and Twilio
}
private decryptKey(encryptedKey: string): string {
// Implement secure decryption
return decrypt(encryptedKey, process.env.MASTER_KEY!);
}
}
  1. Add Request Signing and Validation
"Implement request security:
- Webhook signature validation
- Request signing for APIs that require it
- API key rotation without downtime
- OAuth token refresh logic
- Rate limit header parsing"
  1. Create Security Middleware
"Create middleware for:
- Input sanitization
- Output filtering (remove sensitive data)
- Request ID tracking
- Audit logging
- Threat detection"
  1. Implement Comprehensive Error Handling
"Create error handling system:
- Categorize errors (rate limit, auth, network, etc.)
- Implement appropriate retry strategies per type
- Create fallback mechanisms
- Dead letter queue for failed requests
- Error recovery procedures"

Example error handling:

errors/integration-errors.ts
export class IntegrationError extends Error {
constructor(
message: string,
public code: string,
public provider: string,
public isRetryable: boolean,
public originalError?: any,
public context?: Record<string, any>
) {
super(message);
this.name = 'IntegrationError';
}
static fromStripeError(error: any): IntegrationError {
const retryableCodes = ['rate_limit', 'api_connection_error'];
return new IntegrationError(
error.message || 'Stripe API error',
error.code || 'unknown_error',
'stripe',
retryableCodes.includes(error.code),
error,
{
type: error.type,
param: error.param,
requestId: error.requestId
}
);
}
static fromSendGridError(error: any): IntegrationError {
const isRetryable = error.code >= 500 || error.code === 429;
return new IntegrationError(
error.message || 'SendGrid API error',
`sendgrid_${error.code}`,
'sendgrid',
isRetryable,
error,
{
response: error.response?.body
}
);
}
}
  1. Build Circuit Breaker Implementation
"Implement circuit breaker pattern:
- Track failure rates per service
- Open circuit on threshold breach
- Half-open state for testing recovery
- Configurable thresholds
- Metrics and alerting"
  1. Create Fallback Strategies
"Implement fallback mechanisms:
- Secondary email provider if SendGrid fails
- SMS queue for Twilio outages
- Cached responses for read operations
- Graceful degradation strategies
- User notification preferences"
  1. Create Comprehensive Test Suite
@integrations
"Generate tests for:
- Unit tests with mocked APIs
- Integration tests with sandbox APIs
- Error scenario testing
- Rate limit simulation
- Circuit breaker behavior
- Webhook handling"

Example test structure:

__tests__/integrations/stripe.test.ts
describe('StripeIntegration', () => {
let stripe: StripeIntegration;
let mockServer: MockServer;
beforeAll(async () => {
mockServer = await createMockStripeServer();
stripe = new StripeIntegration({
apiKey: 'test_key',
baseURL: mockServer.url
});
});
describe('Payment Processing', () => {
it('should handle successful payment', async () => {
mockServer.onPost('/charges').reply(200, {
id: 'ch_test123',
status: 'succeeded'
});
const result = await stripe.createCharge({
amount: 1000,
currency: 'usd'
});
expect(result.status).toBe('succeeded');
});
it('should retry on network errors', async () => {
let attempts = 0;
mockServer.onPost('/charges').reply(() => {
attempts++;
if (attempts < 3) {
throw new NetworkError('Connection reset');
}
return [200, { status: 'succeeded' }];
});
const result = await stripe.createCharge({
amount: 1000,
currency: 'usd'
});
expect(attempts).toBe(3);
expect(result.status).toBe('succeeded');
});
});
});
  1. Implement Monitoring and Alerting
"Create monitoring system:
- API response time tracking
- Success/failure rates per endpoint
- Rate limit usage monitoring
- Error rate alerting
- Cost tracking per service"
  1. Build Debug Tools
"Create debugging utilities:
- Request/response replay tool
- API call timeline visualization
- Error pattern analysis
- Performance profiling
- Test data generators"

Let AI analyze API docs efficiently:

// Method 1: Using MCP servers (if available)
"Using GitHub MCP, show me:
- Repository API endpoints
- Authentication patterns
- Rate limiting details
- Webhook configuration"
// Method 2: Using Context7 MCP for documentation
"Using Context7 MCP, get the latest:
- Stripe API reference
- Best practices for idempotency
- Webhook security guidelines"
// Method 3: Manual documentation analysis
@stripe-api-docs.md
"Extract key information:
- Authentication method
- Rate limits
- Error codes and meanings
- Idempotency support
- Webhook events
Create a quick reference guide"

Ensure API compatibility:

"Generate contract tests from API documentation:
- Request/response schemas
- Required vs optional fields
- Type definitions
- Validation rules
- Breaking change detection"

Implement smart retries:

// Different strategies for different errors
const retryStrategies = {
rate_limit: {
shouldRetry: true,
backoffMultiplier: 1,
maxRetries: 10,
respectRetryAfter: true
},
network_error: {
shouldRetry: true,
backoffMultiplier: 2,
maxRetries: 3,
addJitter: true
},
invalid_request: {
shouldRetry: false
}
};

Problem: Hitting API rate limits during bulk operations

Solution:

// Implement token bucket algorithm
class RateLimiter {
async executeWithRateLimit<T>(
operation: () => Promise<T>
): Promise<T> {
await this.acquireToken();
return operation();
}
}

Enhance your integration system:

  1. Multi-Provider Redundancy

    • Add backup providers for each service
    • Implement intelligent provider selection
    • Load balance across providers
    • Track provider reliability metrics
  2. Advanced Features

    • Batch API operations
    • Webhook event streaming
    • Real-time synchronization
    • Offline queue with sync
  3. Performance Optimization

    • Connection pooling
    • Response caching
    • Predictive prefetching
    • GraphQL aggregation layer
  4. MCP Server Orchestration

    • Build workflows combining multiple MCP servers
    • Create a GitHub→Linear→Slack automation
    • Implement MCP-based monitoring dashboard
    • Design fallback chains using MCP alternatives

Your integration is production-ready when:

  • ✅ All APIs integrated with less than 1% error rate
  • ✅ Average response time under 200ms
  • ✅ Zero security vulnerabilities
  • ✅ 100% webhook delivery rate
  • ✅ Automatic recovery from outages
  • ✅ Cost optimization achieved
  • ✅ Comprehensive monitoring in place
  • ✅ Full test coverage including edge cases

Teams using these patterns report:

  • 95% reduction in integration-related incidents
  • 60% faster API integration development
  • 80% decrease in failed transactions
  • 99.9% message delivery rate achieved

Before deploying:

  • All API keys securely stored
  • Rate limits implemented
  • Retry logic tested
  • Webhooks secured
  • Monitoring configured
  • Error handling complete
  • Documentation updated
  • Load testing performed
  1. Abstract Common Patterns: Build reusable base classes for integrations
  2. Plan for Failure: Every external call can fail - be prepared
  3. Security First: Never compromise on API security
  4. Monitor Everything: You can’t fix what you can’t measure
  5. Test Realistically: Include network issues and API limits in tests
  • Initial architecture: 2 hours
  • Base implementation: 3 hours
  • Provider integrations: 2 hours each
  • Testing and hardening: 4 hours
  • Total: ~13 hours (vs 40+ hours traditional)

You’ve mastered API integration patterns. Ready for more?

Build an API Gateway

Create a unified API gateway for all your integrations

Add GraphQL Layer

Build a GraphQL layer over REST APIs

Create SDK

Package your integrations as reusable SDKs

Continue to Database Design →