> ## Documentation Index
> Fetch the complete documentation index at: https://docs-ts.playservices.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing & Debugging

> Comprehensive testing strategies, debugging tools, and troubleshooting guide for tournament platform integration

# Testing & Debugging

This guide provides comprehensive testing strategies, debugging tools, and troubleshooting techniques to ensure reliable integration with the Tournament Platform.

## Testing Environment Setup

### Production Environment

Use the production Tournament Platform API for testing and development:

**Production Endpoints:**

```
Base URL: https://ts.playservices.tech/api
WebSocket: wss://ts.playservices.tech/ws
Documentation: https://ts.playservices.tech/docs
```

### Test Credentials

```json theme={null}
{
  "operatorId": "op_test_1234567890",
  "apiKey": "sk_live_test_abcdef123456789",
  "testPlayerPrefix": "test_player_",
  "defaultCurrency": "USD",
  "environment": "production"
}
```

### Test Data Creation

Create test tournaments and players for integration testing:

```javascript theme={null}
// Create test tournament
const createTestTournament = async () => {
  const response = await fetch('https://ts.playservices.tech/api/tournaments', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_test_abcdef123456789',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'Test Tournament - ' + new Date().toISOString(),
      gameSlug: 'crash-classic',
      scheduledStart: new Date(Date.now() + 300000).toISOString(), // 5 minutes from now
      maxPlayers: 10,
      entryFee: 1.00,
      currency: 'USD',
      gameConfig: {
        maxRounds: 3,
        roundDuration: 180,
        eliminationRate: 0.5
      },
      prizeDistribution: [70, 20, 10],
      rebuyConfig: {
        enabled: true,
        maxRebuys: 2,
        rebuyFee: 1.00
      }
    })
  });
  
  const tournament = await response.json();
  console.log('Test tournament created:', tournament.tournamentId);
  return tournament;
};

// Register test player
const registerTestPlayer = async (tournamentId, playerData) => {
  const response = await fetch(`https://ts.playservices.tech/api/tournaments/${tournamentId}/players`, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_test_abcdef123456789',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      playerId: `test_player_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`,
      displayName: playerData.displayName || 'Test Player',
      entryFee: 1.00,
      currency: 'USD',
      playerMetadata: {
        isTestPlayer: true,
        testScenario: playerData.scenario || 'basic'
      }
    })
  });
  
  const registration = await response.json();
  console.log('Test player registered:', registration.playerId);
  return registration;
};
```

## Integration Testing Framework

### API Testing Suite

```javascript theme={null}
const assert = require('assert');

class TournamentAPITest {
  constructor(apiKey, baseUrl) {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
    this.testResults = [];
  }
  
  async runAllTests() {
    console.log('Starting Tournament API integration tests...');
    
    const tests = [
      { name: 'Tournament Creation', fn: this.testTournamentCreation },
      { name: 'Player Registration', fn: this.testPlayerRegistration },
      { name: 'Player Rebuy', fn: this.testPlayerRebuy },
      { name: 'Tournament Cancellation', fn: this.testTournamentCancellation },
      { name: 'Results Retrieval', fn: this.testResultsRetrieval },
      { name: 'Webhook Delivery', fn: this.testWebhookDelivery },
      { name: 'Error Handling', fn: this.testErrorHandling }
    ];
    
    for (const test of tests) {
      try {
        console.log(`Running test: ${test.name}`);
        await test.fn.call(this);
        this.testResults.push({ name: test.name, status: 'PASS' });
        console.log(` ${test.name} PASSED`);
      } catch (error) {
        this.testResults.push({ 
          name: test.name, 
          status: 'FAIL', 
          error: error.message 
        });
        console.error(`L ${test.name} FAILED:`, error.message);
      }
    }
    
    this.generateTestReport();
  }
  
  async testTournamentCreation() {
    const tournament = await this.createTestTournament({
      name: 'API Test Tournament',
      gameSlug: 'crash-classic',
      maxPlayers: 5,
      entryFee: 2.00
    });
    
    assert(tournament.tournamentId, 'Tournament ID should be present');
    assert(tournament.status === 'scheduled', 'Tournament should be scheduled');
    assert(tournament.maxPlayers === 5, 'Max players should match input');
    assert(tournament.entryFee === 2.00, 'Entry fee should match input');
    
    return tournament;
  }
  
  async testPlayerRegistration() {
    const tournament = await this.createTestTournament();
    
    const registration = await this.registerTestPlayer(tournament.tournamentId, {
      displayName: 'API Test Player',
      entryFee: tournament.entryFee
    });
    
    assert(registration.playerId, 'Player ID should be present');
    assert(registration.jwtToken, 'JWT token should be provided');
    assert(registration.gameUrl, 'Game URL should be provided');
    assert(registration.status === 'registered', 'Player should be registered');
    
    return registration;
  }
  
  async testPlayerRebuy() {
    const tournament = await this.createTestTournament();
    const registration = await this.registerTestPlayer(tournament.tournamentId);
    
    const rebuy = await this.processRebuy(tournament.tournamentId, registration.playerId);
    
    assert(rebuy.rebuyProcessed === true, 'Rebuy should be processed');
    assert(rebuy.newEntryCount === 2, 'Entry count should be updated');
    assert(rebuy.remainingRebuys >= 0, 'Remaining rebuys should be valid');
    
    return rebuy;
  }
  
  async testTournamentCancellation() {
    const tournament = await this.createTestTournament();
    
    const cancellation = await this.cancelTournament(tournament.tournamentId, 'test_cancellation');
    
    assert(cancellation.cancelled === true, 'Tournament should be cancelled');
    assert(cancellation.reason === 'test_cancellation', 'Cancellation reason should match');
    
    return cancellation;
  }
  
  async testResultsRetrieval() {
    // Use completed test tournament
    const completedTournamentId = 'test_completed_tournament_123';
    
    const results = await this.getTournamentResults(completedTournamentId);
    
    assert(results.tournamentId === completedTournamentId, 'Tournament ID should match');
    assert(results.status === 'completed', 'Tournament should be completed');
    assert(Array.isArray(results.winners), 'Winners should be an array');
    assert(results.winners.length > 0, 'Should have at least one winner');
    
    return results;
  }
  
  async testWebhookDelivery() {
    // Test webhook endpoint
    const webhook = await this.createTestWebhook();
    
    const test = await this.testWebhookEndpoint(webhook.webhookId);
    
    assert(test.deliveryStatus === 'success', 'Webhook should deliver successfully');
    assert(test.httpStatus === 200, 'Should receive 200 OK response');
    
    return test;
  }
  
  async testErrorHandling() {
    // Test various error scenarios
    const errorTests = [
      { name: 'Invalid API Key', test: this.testInvalidAPIKey },
      { name: 'Tournament Not Found', test: this.testTournamentNotFound },
      { name: 'Invalid Player Data', test: this.testInvalidPlayerData },
      { name: 'Rate Limiting', test: this.testRateLimiting }
    ];
    
    for (const errorTest of errorTests) {
      try {
        await errorTest.test.call(this);
        throw new Error(`Expected ${errorTest.name} to throw an error`);
      } catch (error) {
        // Expected error - verify error format
        assert(error.message || error.error, 'Error should have message');
      }
    }
  }
  
  // Helper methods
  async createTestTournament(config = {}) {
    const response = await fetch(`${this.baseUrl}/api/tournaments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: 'Test Tournament',
        gameSlug: 'crash-classic',
        scheduledStart: new Date(Date.now() + 300000).toISOString(),
        maxPlayers: 10,
        entryFee: 1.00,
        currency: 'USD',
        ...config
      })
    });
    
    if (!response.ok) {
      throw new Error(`Tournament creation failed: ${response.status}`);
    }
    
    return await response.json();
  }
  
  generateTestReport() {
    const passed = this.testResults.filter(r => r.status === 'PASS').length;
    const failed = this.testResults.filter(r => r.status === 'FAIL').length;
    const total = this.testResults.length;
    
    console.log('\n=== Test Report ===');
    console.log(`Total Tests: ${total}`);
    console.log(`Passed: ${passed}`);
    console.log(`Failed: ${failed}`);
    console.log(`Success Rate: ${((passed / total) * 100).toFixed(1)}%`);
    
    if (failed > 0) {
      console.log('\nFailed Tests:');
      this.testResults
        .filter(r => r.status === 'FAIL')
        .forEach(r => console.log(`- ${r.name}: ${r.error}`));
    }
    
    return {
      total,
      passed,
      failed,
      successRate: (passed / total) * 100,
      results: this.testResults
    };
  }
}

// Usage
const testSuite = new TournamentAPITest(
  'sk_live_test_abcdef123456789',
  'https://ts.playservices.tech/api'
);

testSuite.runAllTests();
```

### Load Testing

```javascript theme={null}
// Load testing with multiple concurrent requests
const loadTest = async (concurrent = 10, requests = 100) => {
  const apiKey = 'sk_live_test_abcdef123456789';
  const baseUrl = 'https://ts.playservices.tech/api';
  
  console.log(`Starting load test: ${concurrent} concurrent users, ${requests} requests`);
  
  const startTime = Date.now();
  const results = [];
  
  // Create concurrent workers
  const workers = Array.from({ length: concurrent }, async (_, workerId) => {
    const requestsPerWorker = Math.floor(requests / concurrent);
    
    for (let i = 0; i < requestsPerWorker; i++) {
      const requestStart = Date.now();
      
      try {
        const response = await fetch(`${baseUrl}/api/tournaments`, {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });
        
        const duration = Date.now() - requestStart;
        results.push({
          workerId,
          requestIndex: i,
          status: response.status,
          duration,
          success: response.ok
        });
        
      } catch (error) {
        results.push({
          workerId,
          requestIndex: i,
          error: error.message,
          duration: Date.now() - requestStart,
          success: false
        });
      }
    }
  });
  
  // Wait for all workers to complete
  await Promise.all(workers);
  
  const totalTime = Date.now() - startTime;
  const successful = results.filter(r => r.success).length;
  const failed = results.length - successful;
  const averageLatency = results.reduce((sum, r) => sum + r.duration, 0) / results.length;
  
  console.log('\n=== Load Test Results ===');
  console.log(`Total Requests: ${results.length}`);
  console.log(`Successful: ${successful}`);
  console.log(`Failed: ${failed}`);
  console.log(`Success Rate: ${((successful / results.length) * 100).toFixed(1)}%`);
  console.log(`Total Time: ${totalTime}ms`);
  console.log(`Average Latency: ${averageLatency.toFixed(0)}ms`);
  console.log(`Requests/Second: ${(results.length / (totalTime / 1000)).toFixed(2)}`);
  
  return {
    totalRequests: results.length,
    successful,
    failed,
    successRate: (successful / results.length) * 100,
    totalTime,
    averageLatency,
    requestsPerSecond: results.length / (totalTime / 1000),
    results
  };
};

// Run load test
loadTest(5, 50);
```

## Debugging Tools

### API Request Inspector

```javascript theme={null}
class APIInspector {
  constructor(apiKey, baseUrl) {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
    this.requestLog = [];
  }
  
  async inspectRequest(method, endpoint, data = null) {
    const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
    const requestTime = new Date();
    
    console.log(`\n[${requestId}] ${method} ${endpoint}`);
    console.log('Headers:', {
      'Authorization': `Bearer ${this.apiKey.substr(0, 20)}...`,
      'Content-Type': 'application/json'
    });
    
    if (data) {
      console.log('Body:', JSON.stringify(data, null, 2));
    }
    
    const startTime = Date.now();
    
    try {
      const response = await fetch(`${this.baseUrl}${endpoint}`, {
        method,
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json'
        },
        body: data ? JSON.stringify(data) : undefined
      });
      
      const duration = Date.now() - startTime;
      const responseBody = await response.text();
      
      let parsedBody;
      try {
        parsedBody = JSON.parse(responseBody);
      } catch {
        parsedBody = responseBody;
      }
      
      // Log response
      console.log(`\n[${requestId}] Response (${duration}ms):`);
      console.log('Status:', response.status, response.statusText);
      console.log('Headers:', Object.fromEntries(response.headers.entries()));
      console.log('Body:', typeof parsedBody === 'object' 
        ? JSON.stringify(parsedBody, null, 2) 
        : parsedBody
      );
      
      // Store in log
      this.requestLog.push({
        requestId,
        timestamp: requestTime,
        method,
        endpoint,
        requestData: data,
        responseStatus: response.status,
        responseData: parsedBody,
        duration,
        success: response.ok
      });
      
      return {
        status: response.status,
        headers: Object.fromEntries(response.headers.entries()),
        data: parsedBody,
        duration
      };
      
    } catch (error) {
      const duration = Date.now() - startTime;
      
      console.error(`\n[${requestId}] Error (${duration}ms):`, error.message);
      
      this.requestLog.push({
        requestId,
        timestamp: requestTime,
        method,
        endpoint,
        requestData: data,
        error: error.message,
        duration,
        success: false
      });
      
      throw error;
    }
  }
  
  exportRequestLog(filename = 'api-requests.json') {
    const fs = require('fs');
    fs.writeFileSync(filename, JSON.stringify(this.requestLog, null, 2));
    console.log(`Request log exported to ${filename}`);
  }
  
  analyzePerformance() {
    const successful = this.requestLog.filter(r => r.success);
    const failed = this.requestLog.filter(r => !r.success);
    
    if (successful.length === 0) {
      console.log('No successful requests to analyze');
      return;
    }
    
    const avgLatency = successful.reduce((sum, r) => sum + r.duration, 0) / successful.length;
    const minLatency = Math.min(...successful.map(r => r.duration));
    const maxLatency = Math.max(...successful.map(r => r.duration));
    
    console.log('\n=== Performance Analysis ===');
    console.log(`Total Requests: ${this.requestLog.length}`);
    console.log(`Successful: ${successful.length}`);
    console.log(`Failed: ${failed.length}`);
    console.log(`Average Latency: ${avgLatency.toFixed(0)}ms`);
    console.log(`Min Latency: ${minLatency}ms`);
    console.log(`Max Latency: ${maxLatency}ms`);
    
    // Group by endpoint
    const endpointStats = {};
    successful.forEach(req => {
      if (!endpointStats[req.endpoint]) {
        endpointStats[req.endpoint] = [];
      }
      endpointStats[req.endpoint].push(req.duration);
    });
    
    console.log('\nEndpoint Performance:');
    Object.entries(endpointStats).forEach(([endpoint, durations]) => {
      const avg = durations.reduce((sum, d) => sum + d, 0) / durations.length;
      console.log(`  ${endpoint}: ${avg.toFixed(0)}ms avg (${durations.length} requests)`);
    });
  }
}

// Usage
const inspector = new APIInspector(
  'sk_live_test_abcdef123456789',
  'https://ts.playservices.tech/api'
);

// Inspect tournament creation
inspector.inspectRequest('POST', '/api/tournaments', {
  name: 'Debug Tournament',
  gameSlug: 'crash-classic',
  maxPlayers: 10
});

// Inspect tournament list
inspector.inspectRequest('GET', '/api/tournaments?status=scheduled&limit=5');

// Analyze performance after tests
inspector.analyzePerformance();
inspector.exportRequestLog('debug-session.json');
```

### Webhook Testing Tool

```javascript theme={null}
const express = require('express');
const crypto = require('crypto');

class WebhookTester {
  constructor(port = 3001) {
    this.app = express();
    this.port = port;
    this.receivedWebhooks = [];
    this.webhookSecret = 'test-webhook-secret-123';
    
    this.setupRoutes();
  }
  
  setupRoutes() {
    this.app.use(express.json());
    
    // Test webhook endpoint
    this.app.post('/webhook-test', (req, res) => {
      const signature = req.headers['x-tournament-signature'];
      const timestamp = new Date().toISOString();
      const eventData = req.body;
      
      console.log(`\n[${timestamp}] Webhook received:`);
      console.log('Headers:', req.headers);
      console.log('Body:', JSON.stringify(eventData, null, 2));
      
      // Verify signature
      const isValidSignature = this.verifySignature(
        JSON.stringify(eventData),
        signature
      );
      
      console.log('Signature Valid:', isValidSignature);
      
      // Store webhook data
      this.receivedWebhooks.push({
        timestamp,
        eventType: eventData.eventType,
        eventId: eventData.eventId,
        tournamentId: eventData.tournamentId,
        signature,
        signatureValid: isValidSignature,
        data: eventData,
        headers: req.headers
      });
      
      // Simulate processing delay
      setTimeout(() => {
        if (this.shouldSimulateFailure(eventData)) {
          console.log('Simulating webhook failure');
          res.status(500).json({ error: 'Simulated failure' });
        } else {
          res.status(200).json({ 
            received: true,
            eventId: eventData.eventId,
            processedAt: new Date().toISOString()
          });
        }
      }, 100);
    });
    
    // Webhook stats endpoint
    this.app.get('/webhook-stats', (req, res) => {
      const stats = this.getWebhookStats();
      res.json(stats);
    });
    
    // Clear webhook history
    this.app.delete('/webhook-history', (req, res) => {
      this.receivedWebhooks = [];
      res.json({ cleared: true });
    });
    
    // Get webhook history
    this.app.get('/webhook-history', (req, res) => {
      res.json({
        webhooks: this.receivedWebhooks,
        count: this.receivedWebhooks.length
      });
    });
  }
  
  verifySignature(body, signature) {
    if (!signature) return false;
    
    const expectedSignature = crypto
      .createHmac('sha256', this.webhookSecret)
      .update(body)
      .digest('hex');
    
    const receivedSignature = signature.replace('sha256=', '');
    
    return crypto.timingSafeEqual(
      Buffer.from(expectedSignature, 'hex'),
      Buffer.from(receivedSignature, 'hex')
    );
  }
  
  shouldSimulateFailure(eventData) {
    // Simulate 5% failure rate for testing
    return Math.random() < 0.05;
  }
  
  getWebhookStats() {
    const total = this.receivedWebhooks.length;
    const validSignatures = this.receivedWebhooks.filter(w => w.signatureValid).length;
    const eventTypes = {};
    const tournaments = {};
    
    this.receivedWebhooks.forEach(webhook => {
      // Count by event type
      eventTypes[webhook.eventType] = (eventTypes[webhook.eventType] || 0) + 1;
      
      // Count by tournament
      if (webhook.tournamentId) {
        tournaments[webhook.tournamentId] = (tournaments[webhook.tournamentId] || 0) + 1;
      }
    });
    
    return {
      totalWebhooks: total,
      validSignatures,
      signatureSuccessRate: total > 0 ? (validSignatures / total * 100).toFixed(1) + '%' : '0%',
      eventTypeBreakdown: eventTypes,
      tournamentBreakdown: tournaments,
      recentWebhooks: this.receivedWebhooks.slice(-10)
    };
  }
  
  start() {
    return new Promise((resolve) => {
      this.server = this.app.listen(this.port, () => {
        console.log(`\nWebhook tester running on http://localhost:${this.port}`);
        console.log(`Test endpoint: http://localhost:${this.port}/webhook-test`);
        console.log(`Stats endpoint: http://localhost:${this.port}/webhook-stats`);
        resolve();
      });
    });
  }
  
  stop() {
    if (this.server) {
      this.server.close();
    }
  }
}

// Usage
const webhookTester = new WebhookTester(3001);
webhookTester.start();

// Register this URL with Tournament Platform:
// https://your-domain.com:3001/webhook-test
```

## Troubleshooting Guide

### Common Issues & Solutions

#### Authentication Errors

**Issue: 401 Unauthorized responses**

```javascript theme={null}
// Debug authentication
const debugAuth = async (apiKey, endpoint) => {
  const response = await fetch(endpoint, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });
  
  if (response.status === 401) {
    console.error('Authentication failed:');
    console.log('- Check API key format (should start with "sk_" for live, "sk_test_" for sandbox)');
    console.log('- Verify API key is active in dashboard');
    console.log('- Ensure using correct environment (sandbox vs production)');
    console.log('- Check for extra whitespace in API key');
    
    const authHeader = `Bearer ${apiKey}`;
    console.log('Full auth header:', authHeader);
    console.log('API key length:', apiKey.length);
  }
  
  return response;
};
```

**Solutions:**

* Verify API key format and environment
* Check API key permissions in dashboard
* Ensure no whitespace in API key
* Confirm correct base URL for environment

#### Rate Limiting

**Issue: 429 Too Many Requests**

```javascript theme={null}
// Implement exponential backoff
const apiCallWithBackoff = async (apiCall, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await apiCall();
      
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
        console.log(`Rate limited, retrying in ${retryAfter}s (attempt ${attempt}/${maxRetries})`);
        
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }
      
      return response;
      
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Request failed, retrying in ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};
```

#### Webhook Delivery Issues

**Issue: Webhooks not being received**

```javascript theme={null}
// Webhook diagnostics
const diagnoseWebhookIssues = async (webhookId, apiKey) => {
  console.log('Diagnosing webhook issues...');
  
  // Check webhook configuration
  const config = await fetch(`/api/webhooks/${webhookId}`, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  }).then(r => r.json());
  
  console.log('Webhook config:', config);
  
  // Check recent deliveries
  const deliveries = await fetch(`/api/webhooks/${webhookId}/deliveries?limit=10`, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  }).then(r => r.json());
  
  console.log('Recent deliveries:', deliveries);
  
  // Test webhook endpoint
  const testResult = await fetch(`/api/webhooks/${webhookId}/test`, {
    method: 'POST',
    headers: { 
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      eventType: 'test.webhook',
      data: { test: true }
    })
  }).then(r => r.json());
  
  console.log('Test result:', testResult);
  
  // Provide recommendations
  if (config.active === false) {
    console.log('� Webhook is disabled - enable it in the configuration');
  }
  
  if (deliveries.deliveries?.some(d => !d.success)) {
    console.log('� Some deliveries failed - check your endpoint response status');
  }
  
  if (testResult.deliveryStatus !== 'success') {
    console.log('� Test delivery failed - verify your endpoint is accessible');
  }
};
```

#### JWT Token Issues

**Issue: Token validation failures**

```javascript theme={null}
// Debug JWT tokens
const debugJWTToken = (token) => {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) {
      throw new Error('Invalid JWT format');
    }
    
    const header = JSON.parse(atob(parts[0]));
    const payload = JSON.parse(atob(parts[1]));
    
    console.log('JWT Header:', header);
    console.log('JWT Payload:', payload);
    
    // Check expiration
    if (payload.exp) {
      const expiration = new Date(payload.exp * 1000);
      const now = new Date();
      
      console.log('Expires at:', expiration.toISOString());
      console.log('Current time:', now.toISOString());
      console.log('Is expired:', expiration < now);
      
      if (expiration < now) {
        console.error('Token has expired - request new token from casino system');
      }
    }
    
    // Check required claims
    const requiredClaims = ['tournamentId', 'playerId', 'permissions'];
    const missingClaims = requiredClaims.filter(claim => !payload[claim]);
    
    if (missingClaims.length > 0) {
      console.error('Missing required claims:', missingClaims);
    }
    
  } catch (error) {
    console.error('JWT parsing failed:', error.message);
    console.log('Token might be malformed or corrupted');
  }
};
```

### Performance Optimization

#### Request Batching

```javascript theme={null}
// Batch multiple API calls
class APIBatcher {
  constructor(apiKey, baseUrl) {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
    this.batchQueue = [];
    this.batchTimeout = null;
    this.batchSize = 10;
    this.batchDelay = 100; // ms
  }
  
  queueRequest(method, endpoint, data = null) {
    return new Promise((resolve, reject) => {
      this.batchQueue.push({
        method,
        endpoint,
        data,
        resolve,
        reject
      });
      
      if (this.batchQueue.length >= this.batchSize) {
        this.flushBatch();
      } else if (!this.batchTimeout) {
        this.batchTimeout = setTimeout(() => {
          this.flushBatch();
        }, this.batchDelay);
      }
    });
  }
  
  async flushBatch() {
    if (this.batchTimeout) {
      clearTimeout(this.batchTimeout);
      this.batchTimeout = null;
    }
    
    if (this.batchQueue.length === 0) return;
    
    const batch = this.batchQueue.splice(0, this.batchSize);
    
    // Execute all requests concurrently
    const promises = batch.map(async (request) => {
      try {
        const response = await fetch(`${this.baseUrl}${request.endpoint}`, {
          method: request.method,
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: request.data ? JSON.stringify(request.data) : undefined
        });
        
        const result = await response.json();
        request.resolve(result);
        
      } catch (error) {
        request.reject(error);
      }
    });
    
    await Promise.allSettled(promises);
    
    // Process remaining queue
    if (this.batchQueue.length > 0) {
      setTimeout(() => this.flushBatch(), this.batchDelay);
    }
  }
}
```

#### Caching Strategy

```javascript theme={null}
// API response caching
class APICache {
  constructor(ttl = 300000) { // 5 minutes default
    this.cache = new Map();
    this.ttl = ttl;
  }
  
  generateKey(method, endpoint, data) {
    const payload = data ? JSON.stringify(data) : '';
    return `${method}:${endpoint}:${crypto.createHash('md5').update(payload).digest('hex')}`;
  }
  
  get(method, endpoint, data = null) {
    const key = this.generateKey(method, endpoint, data);
    const cached = this.cache.get(key);
    
    if (cached && (Date.now() - cached.timestamp < this.ttl)) {
      console.log('Cache hit:', key);
      return cached.data;
    }
    
    return null;
  }
  
  set(method, endpoint, data, response) {
    const key = this.generateKey(method, endpoint, data);
    this.cache.set(key, {
      data: response,
      timestamp: Date.now()
    });
    
    console.log('Cache set:', key);
  }
  
  clear() {
    this.cache.clear();
    console.log('Cache cleared');
  }
  
  cleanup() {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > this.ttl) {
        this.cache.delete(key);
      }
    }
  }
}

// Usage with API calls
const apiCache = new APICache();

const cachedAPICall = async (method, endpoint, data = null) => {
  // Check cache first
  const cached = apiCache.get(method, endpoint, data);
  if (cached) {
    return cached;
  }
  
  // Make API call
  const response = await fetch(`${baseUrl}${endpoint}`, {
    method,
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: data ? JSON.stringify(data) : undefined
  });
  
  const result = await response.json();
  
  // Cache successful responses
  if (response.ok) {
    apiCache.set(method, endpoint, data, result);
  }
  
  return result;
};
```

## Best Practices

### Error Handling

<CardGroup cols={2}>
  <Card title="Retry Logic" icon="rotate-ccw">
    Implement exponential backoff for transient failures and rate limiting
  </Card>

  <Card title="Graceful Degradation" icon="shield">
    Handle API failures gracefully with fallback behavior
  </Card>

  <Card title="Monitoring" icon="chart-bar">
    Log and monitor API response times and error rates
  </Card>

  <Card title="Circuit Breaker" icon="zap-off">
    Implement circuit breaker pattern for service protection
  </Card>
</CardGroup>

### Security Testing

```javascript theme={null}
// Security test checklist
const securityTests = {
  async testAPIKeyValidation() {
    // Test with invalid API key
    const response = await fetch('/api/tournaments', {
      headers: { 'Authorization': 'Bearer invalid_key' }
    });
    
    assert(response.status === 401, 'Should reject invalid API key');
  },
  
  async testInputSanitization() {
    // Test SQL injection attempts
    const maliciousInput = "'; DROP TABLE tournaments; --";
    
    const response = await fetch('/api/tournaments', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: maliciousInput
      })
    });
    
    // Should either sanitize input or reject request
    assert(response.status !== 200 || !response.error, 'Should handle malicious input');
  },
  
  async testRateLimiting() {
    // Test rate limiting
    const requests = Array.from({ length: 100 }, () => 
      fetch('/api/tournaments', {
        headers: { 'Authorization': `Bearer ${apiKey}` }
      })
    );
    
    const responses = await Promise.all(requests);
    const rateLimited = responses.some(r => r.status === 429);
    
    assert(rateLimited, 'Should enforce rate limits');
  }
};
```

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api-reference/overview">
    Complete API documentation with all endpoints and parameters.
  </Card>

  <Card title="Database Schema" icon="database" href="/database/schema-overview">
    Explore the database structure supporting the tournament platform.
  </Card>
</CardGroup>
