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

# Best Practices & Richtlinien

> Sicherheits-, Leistungs- und Integrations-Best Practices für die Lovi API

## Einführung

Dieser Leitfaden behandelt Sicherheits-Best Practices, Leistungsoptimierung und Integrationsrichtlinien, um Ihnen bei der Erstellung robuster Anwendungen mit der Lovi API zu helfen.

***

## 🔒 Sicherheits-Best Practices

### API-Schlüssel-Verwaltung

**✅ TUN:**

* API-Schlüssel in Umgebungsvariablen oder sicherer Konfigurationsverwaltung speichern
* Verschiedene API-Schlüssel für verschiedene Umgebungen verwenden (Entwicklung, Staging, Produktion)
* API-Schlüssel regelmäßig rotieren (empfohlen: alle 90 Tage)
* API-Schlüssel-Nutzung überwachen und Alarme für ungewöhnliche Aktivitäten einrichten
* Das Prinzip der geringsten Berechtigung anwenden (separate Schlüssel für verschiedene Funktionen, falls verfügbar)

**❌ NICHT TUN:**

* API-Schlüssel in Quellcode hartcodieren oder in Versionskontrolle festschreiben
* API-Schlüssel per E-Mail, Chat oder anderen unsicheren Kanälen teilen
* Produktions-API-Schlüssel in Entwicklungs-Umgebungen verwenden
* Vollständige API-Schlüssel in Anwendungslogs protokollieren

### Authentifizierungs-Sicherheit

```javascript theme={null}
// ✅ Gut - In Umgebungsvariablen speichern
const ACCESS_KEY = process.env.LOVI_ACCESS_KEY;

// ❌ Schlecht - Im Quellcode hartcodiert
const ACCESS_KEY = 'your-actual-api-key-here';
```

### Anfrage-Sicherheit

**Immer HTTPS verwenden:**

```javascript theme={null}
// ✅ Gut - Nur HTTPS
const BASE_URL = 'https://cloud.lovi.ai';

// ❌ Schlecht - Unsicheres HTTP
const BASE_URL = 'http://cloud.lovi.ai';
```

**Eingabedaten validieren:**

```javascript theme={null}
function validatePhoneNumber(number) {
  // Alle Nicht-Ziffern-Zeichen entfernen
  const cleaned = number.replace(/\D/g, '');

  // Überprüfen, ob es ein gültiges internationales Format ist
  if (!/^\d{10,15}$/.test(cleaned)) {
    throw new Error('Ungültiges Telefonnummernformat');
  }

  return cleaned;
}
```

***

## ⚡ Leistungsoptimierung

### Verbindungsverwaltung

**HTTP-Verbindungen wiederverwenden:**

```javascript theme={null}
// ✅ Gut - Verbindungspool wiederverwenden
const https = require('https');
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 10
});

const fetch = require('node-fetch');

async function makeRequest(url, data) {
  return fetch(url, {
    method: 'POST',
    agent: agent,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
}
```

### Batch-Verarbeitung

**Benachrichtigungen in Batches verarbeiten:**

```javascript theme={null}
async function sendNotificationsBatch(notifications, batchSize = 10) {
  const results = [];

  for (let i = 0; i < notifications.length; i += batchSize) {
    const batch = notifications.slice(i, i + batchSize);
    const batchPromises = batch.map(notification =>
      sendNotification(notification)
    );

    const batchResults = await Promise.allSettled(batchPromises);
    results.push(...batchResults);

    // Ratenbegrenzung: zwischen Batches warten
    if (i + batchSize < notifications.length) {
      await sleep(100); // 100ms Verzögerung
    }
  }

  return results;
}
```

### Caching-Strategien

**Template-Informationen cachen:**

```javascript theme={null}
class TemplateCache {
  constructor(ttl = 3600000) { // 1 Stunde TTL
    this.cache = new Map();
    this.ttl = ttl;
  }

  async getTemplate(templateName) {
    const cached = this.cache.get(templateName);

    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }

    const template = await fetchTemplateFromAPI(templateName);
    this.cache.set(templateName, {
      data: template,
      timestamp: Date.now()
    });

    return template;
  }
}
```

***

## 📊 Ratenbegrenzung & Drosselung

### Ratenlimits verstehen

| Operation           | Limit        | Fenster  |
| ------------------- | ------------ | -------- |
| Authentifizierung   | 10 Anfragen  | 1 Minute |
| Benachrichtigungen  | 100 Anfragen | 1 Minute |
| Template-Abruf      | 50 Anfragen  | 1 Minute |
| Template-Erstellung | 5 Anfragen   | 1 Stunde |

### Ratenlimit-Behandlung

```javascript theme={null}
class RateLimitHandler {
  constructor() {
    this.requestQueue = [];
    this.processing = false;
  }

  async makeRequest(url, data) {
    return new Promise((resolve, reject) => {
      this.requestQueue.push({ url, data, resolve, reject });
      this.processQueue();
    });
  }

  async processQueue() {
    if (this.processing || this.requestQueue.length === 0) return;

    this.processing = true;

    while (this.requestQueue.length > 0) {
      const request = this.requestQueue.shift();

      try {
        const response = await this.executeRequest(request);
        request.resolve(response);
      } catch (error) {
        if (error.status === 429) {
          // Ratenbegrenzt - Anfrage zurückstellen und warten
          this.requestQueue.unshift(request);
          await sleep(error.retryAfter * 1000);
          continue;
        }
        request.reject(error);
      }

      // Kleine Verzögerung zwischen Anfragen
      await sleep(100);
    }

    this.processing = false;
  }
}
```

***

## 🏗️ Architekturmuster

### Repository-Muster

```javascript theme={null}
class NotificationRepository {
  constructor(apiClient) {
    this.apiClient = apiClient;
  }

  async sendWhatsAppNotification(notification) {
    const payload = this.formatWhatsAppPayload(notification);
    return await this.apiClient.post('/notify', payload);
  }

  async sendVoiceNotification(notification) {
    const payload = this.formatVoicePayload(notification);
    return await this.apiClient.post('/notify/voice', payload);
  }

  formatWhatsAppPayload(notification) {
    return {
      contact: {
        number: this.validatePhoneNumber(notification.phoneNumber),
        name: notification.contactName
      },
      language_template: notification.language,
      name_template: notification.templateName,
      recipient_id: notification.phoneNumber,
      notification_type: notification.type,
      campaign_name: notification.campaign
    };
  }
}
```

### Factory-Muster für Benachrichtigungen

```javascript theme={null}
class NotificationFactory {
  static create(type, data) {
    switch (type) {
      case 'whatsapp':
        return new WhatsAppNotification(data);
      case 'voice':
        return new VoiceNotification(data);
      default:
        throw new Error(`Unbekannter Benachrichtigungstyp: ${type}`);
    }
  }
}

class WhatsAppNotification {
  constructor(data) {
    this.contact = { number: data.phoneNumber, name: data.name };
    this.template = data.templateName;
    this.type = 'whatsapp';
  }

  toPayload() {
    return {
      contact: this.contact,
      name_template: this.template,
      // ... andere Eigenschaften
    };
  }
}
```

***

## 🧪 Teststrategien

### Unit-Tests

```javascript theme={null}
// API-Antworten für Tests mocken
const mockAPIClient = {
  post: jest.fn()
};

describe('NotificationService', () => {
  test('should WhatsApp-Benachrichtigung erfolgreich senden', async () => {
    mockAPIClient.post.mockResolvedValue({
      success: true,
      notification_id: 'test-123'
    });

    const service = new NotificationService(mockAPIClient);
    const result = await service.sendWhatsApp({
      phoneNumber: '34666033135',
      templateName: 'welcome',
      contactName: 'John Doe'
    });

    expect(result.success).toBe(true);
    expect(mockAPIClient.post).toHaveBeenCalledWith('/notify', expect.any(Object));
  });
});
```

### Integrationstests

```javascript theme={null}
// Testumgebung mit realen API-Aufrufen verwenden
describe('Integrationstests', () => {
  const testApiKey = process.env.TEST_API_KEY;
  const apiClient = new LoviAPIClient(testApiKey);

  test('should Authentifizierungsablauf behandeln', async () => {
    const authResult = await apiClient.authenticate(
      process.env.TEST_EMAIL,
      process.env.TEST_PASSWORD
    );

    expect(authResult.access_token).toBeDefined();
    expect(authResult.token_type).toBe('bearer');
  });
});
```

***

## 🔍 Monitoring & Logging

### Strukturiertes Logging

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

logger.configure({
  format: logger.format.combine(
    logger.format.timestamp(),
    logger.format.errors({ stack: true }),
    logger.format.json()
  ),
  transports: [
    new logger.transports.File({ filename: 'api-calls.log' })
  ]
});

async function loggedAPICall(endpoint, data) {
  const requestId = generateRequestId();

  logger.info('API-Anfrage gestartet', {
    request_id: requestId,
    endpoint: endpoint,
    method: 'POST',
    timestamp: new Date().toISOString()
  });

  try {
    const response = await makeAPICall(endpoint, data);

    logger.info('API-Anfrage abgeschlossen', {
      request_id: requestId,
      endpoint: endpoint,
      status_code: response.status,
      success: true,
      duration: Date.now() - startTime
    });

    return response;
  } catch (error) {
    logger.error('API-Anfrage fehlgeschlagen', {
      request_id: requestId,
      endpoint: endpoint,
      error: error.message,
      status_code: error.statusCode,
      duration: Date.now() - startTime
    });

    throw error;
  }
}
```

### Gesundheitsprüfungen

```javascript theme={null}
class APIHealthMonitor {
  constructor(apiClient) {
    this.apiClient = apiClient;
    this.healthStatus = { healthy: true, lastCheck: null };
  }

  async checkHealth() {
    try {
      const start = Date.now();
      await this.apiClient.get('/templates?limit=1');
      const duration = Date.now() - start;

      this.healthStatus = {
        healthy: true,
        lastCheck: new Date().toISOString(),
        responseTime: duration,
        status: 'operational'
      };
    } catch (error) {
      this.healthStatus = {
        healthy: false,
        lastCheck: new Date().toISOString(),
        error: error.message,
        status: 'degraded'
      };
    }

    return this.healthStatus;
  }
}
```

***

## 📱 Mobile & Frontend-Integration

### React Hook Beispiel

```javascript theme={null}
import { useState, useEffect } from 'react';

function useLoviNotification() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const sendNotification = async (notificationData) => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('/api/send-notification', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(notificationData)
      });

      if (!response.ok) {
        throw new Error('Benachrichtigung konnte nicht gesendet werden');
      }

      const result = await response.json();
      return result;
    } catch (err) {
      setError(err.message);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  return { sendNotification, loading, error };
}
```

***

## 🔧 Konfigurationsverwaltung

### Umgebungskonfiguration

```javascript theme={null}
// config/lovi.js
module.exports = {
  development: {
    baseURL: 'https://cloud.lovi.ai',
    accessKey: process.env.LOVI_DEV_ACCESS_KEY,
    rateLimits: {
      requests: 10,
      window: 60000 // 1 Minute
    },
    retries: 3,
    timeout: 30000
  },
  production: {
    baseURL: 'https://cloud.lovi.ai',
    accessKey: process.env.LOVI_PROD_ACCESS_KEY,
    rateLimits: {
      requests: 100,
      window: 60000
    },
    retries: 5,
    timeout: 60000
  }
};
```

### Client-Konfiguration

```javascript theme={null}
class LoviAPIClient {
  constructor(config) {
    this.baseURL = config.baseURL;
    this.accessKey = config.accessKey;
    this.timeout = config.timeout;
    this.rateLimiter = new RateLimiter(config.rateLimits);
    this.retryCount = config.retries;
  }

  async request(endpoint, options = {}) {
    await this.rateLimiter.acquire();

    const url = `${this.baseURL}${endpoint}?access_key=${this.accessKey}`;
    const config = {
      timeout: this.timeout,
      ...options
    };

    return this.retryRequest(url, config);
  }
}
```

***

## 📚 Dokumentation & Team-Richtlinien

### Code-Dokumentation

```javascript theme={null}
/**
 * WhatsApp-Benachrichtigung mit Template senden
 *
 * @param {Object} notification - Benachrichtigungsdaten
 * @param {string} notification.phoneNumber - Telefonnummer des Empfängers (internationales Format, ohne +)
 * @param {string} notification.templateName - Name der genehmigten Vorlage
 * @param {string} notification.language - Sprachcode (z. B. 'de_DE', 'en_US')
 * @param {Object} notification.variables - Template-Variablen
 * @param {string} [notification.scheduledTime] - ISO 8601 Datum/Uhrzeit für Planung
 * @param {string} [notification.timezone] - IANA Zeitzonen-Code
 *
 * @returns {Promise<Object>} API-Antwort mit notification_id
 *
 * @throws {ValidationError} Wenn erforderliche Parameter fehlen
 * @throws {APIError} Wenn API-Aufruf fehlschlägt
 *
 * @example
 * const result = await sendWhatsAppNotification({
 *   phoneNumber: '34666033135',
 *   templateName: 'welcome_user',
 *   language: 'de_DE',
 *   variables: { name: 'Hans', course: 'JavaScript' }
 * });
 */
async function sendWhatsAppNotification(notification) {
  // Implementierung...
}
```

### Team-Standards

**API-Integrations-Checkliste:**

* ✅ Korrekte Fehlerbehandlung implementieren
* ✅ Anfrage-/Antwort-Logging hinzufügen
* ✅ Unit-Tests einschließen
* ✅ Eingabeparameter validieren
* ✅ Ratenbegrenzung behandeln
* ✅ Umgebungsspezifische Konfigurationen verwenden
* ✅ Alle Funktionen und Klassen dokumentieren
* ✅ Gesundheitsprüfungen implementieren
* ✅ Monitoring und Alarme hinzufügen

***

## 🚨 Häufige Fallstricke & Lösungen

### Fallstrick: Hartcodierte Werte

```javascript theme={null}
// ❌ Schlecht
const templateName = 'welcome_template_final_v2';

// ✅ Gut
const templateName = config.templates.welcome;
```

### Fallstrick: Schlechte Fehlerbehandlung

```javascript theme={null}
// ❌ Schlecht
try {
  await sendNotification(data);
} catch (error) {
  console.log('Error:', error);
}

// ✅ Gut
try {
  await sendNotification(data);
} catch (error) {
  logger.error('Benachrichtigung fehlgeschlagen', {
    error: error.message,
    data: sanitizeForLog(data),
    stack: error.stack
  });

  throw new NotificationError(
    'Benachrichtigung konnte nicht gesendet werden',
    error.statusCode,
    error.requestId
  );
}
```

### Fallstrick: Ratenlimits ignorieren

```javascript theme={null}
// ❌ Schlecht - Alles auf einmal senden
notifications.forEach(notification => {
  sendNotification(notification);
});

// ✅ Gut - Ratenlimits respektieren
await sendNotificationsBatch(notifications, 10);
```

Denken Sie daran: Die Befolgung dieser Best Practices hilft Ihnen, zuverlässigere, sicherere und wartbarere Integrationen mit der Lovi API zu erstellen.
