API Dokumentation
Alles, was Sie brauchen, um CupidBot in Ihre Dating-Plattform zu integrieren
⚡
Base URL
https://api.cupidbot.de🔑
Authentication
X-API-Key: mk_xxxxx⏱️
Response Time
~30-70 SekundenQuick Start
# Quick Start Guide
## 1. Account erstellen
Registrieren Sie sich auf [cupidbot.de/signup](/signup) und wählen Sie Ihren Tarif.
## 2. Email verifizieren
Bestätigen Sie Ihre Email-Adresse über den Link in der Bestätigungs-Email.
## 3. API Key erstellen
Nach der Verifizierung können Sie im Dashboard Ihren ersten API Key erstellen.
## 4. Erste Anfrage senden
```bash
curl -X POST https://api.cupidbot.de/api/v1/chat \
-H "X-API-Key: mk_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"session_id": "user_12345",
"message": "Hey! Wie gehts?"
}'
```
## 5. Response erhalten
```json
{
"session_id": "user_12345",
"response": "hey mir gehts super danke 😊 und dir?",
"character": {
"name": "Lisa",
"age": 25,
"location": "Berlin",
"physical_description": "Ich bin 168cm groß, schlank mit langen braunen Haaren und grünen Augen.",
"personality_summary": "freundlich, offen, humorvoll",
"interests": ["Reisen", "Fotografie", "Yoga", "Kochen"]
},
"photo_url": null,
"timing": {
"read_delay": 0.0,
"thinking_delay": 0.0,
"typing_delay": 0.0,
"total_delay": 0.0,
"show_typing": 0.0
},
"show_typing": false,
"processing_time": 180.5,
"timestamp": "2025-11-24T15:30:00Z",
"conversation_mode": "flirty"
}
```
**Wichtig:** Die Response-Zeit beträgt durchschnittlich 30-70 Sekunden pro Nachricht (GPU-Inferenz mit 14B-Modell + LoRA).
API Reference
# API Reference
## Base URL
```
https://api.cupidbot.de
```
## Authentication
Alle API-Requests benötigen einen API Key im Header:
```
X-API-Key: mk_xxxxx
```
API Keys können Sie im [Dashboard](/dashboard/keys) erstellen und verwalten.
---
## Hauptendpoint: POST /api/v1/chat
Senden Sie eine Nachricht und erhalten Sie eine menschlich wirkende Antwort.
### Request Body
```json
{
"session_id": "user_session_12345",
"message": "Hey! Wie geht's dir?",
"conversation_mode": "flirty",
"bot_context": {
"name": "Lisa",
"age": 25,
"location": "Berlin",
"relationship_goal": "serious",
"photos": [
"https://example.com/photo1.jpg",
"https://example.com/photo2.jpg"
]
},
"user_context": {
"city": "München",
"country": "Deutschland",
"current_date": "2025-11-24",
"current_time": "18:30",
"weather": "sonnig, 22°C",
"timezone": "Europe/Berlin"
},
"read_delay_multiplier": 0.0,
"thinking_delay_multiplier": 0.0,
"typing_delay_multiplier": 0.0
}
```
### Request Parameter
| Parameter | Typ | Pflicht | Beschreibung |
|-----------|-----|---------|--------------|
| `session_id` | string | **Ja** | Eindeutige Session-ID für Konversationskontinuität |
| `message` | string | **Ja** | Nachricht des Users (1-1000 Zeichen) |
| `conversation_mode` | string | Nein | Gesprächsstil: `flirty`, `intimate`, `casual`, `seductive` (Standard: `flirty`) |
| `bot_context` | object | Nein | Bot-Charakter-Informationen (siehe BotContext unten) |
| `user_context` | object | Nein | User-Kontext-Informationen (siehe UserContext unten) |
| `read_delay_multiplier` | float | Nein | Multiplikator für Leseverzögerung (0.0 = sofort, 1.0 = normal, 2.0 = langsam, Standard: 0.0) |
| `thinking_delay_multiplier` | float | Nein | Multiplikator für Denkverzögerung (Standard: 0.0) |
| `typing_delay_multiplier` | float | Nein | Multiplikator für Tippverzögerung (Standard: 0.0) |
| `debug` | boolean | Nein | Debug-Modus aktivieren (Standard: false) |
### BotContext Object
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `name` | string | Name des Bots |
| `age` | integer | Alter des Bots (18-35) |
| `location` | string | Standort/Stadt des Bots |
| `relationship_goal` | string | Beziehungsziel: `casual`, `serious`, `friendship`, `unsure` |
| `photos` | array | Liste von Foto-URLs (Bot sendet sie während der Konversation) |
### UserContext Object
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `city` | string | Stadt des Users |
| `country` | string | Land des Users |
| `current_date` | string | Aktuelles Datum (z.B. '2025-11-24' oder 'Freitag, 24. November') |
| `current_time` | string | Aktuelle Uhrzeit (z.B. '18:30') |
| `weather` | string | Aktuelles Wetter (z.B. 'sonnig, 22°C') |
| `timezone` | string | Zeitzone des Users (z.B. 'Europe/Berlin') |
### Response
```json
{
"session_id": "user_session_12345",
"response": "hey mir gehts super danke 😊 und dir?",
"character": {
"name": "Lisa",
"age": 25,
"location": "Berlin",
"physical_description": "Ich bin 168cm groß, schlank mit langen braunen Haaren und grünen Augen.",
"personality_summary": "freundlich, offen, humorvoll",
"interests": ["Reisen", "Fotografie", "Yoga", "Kochen"]
},
"photo_url": null,
"timing": {
"read_delay": 0.0,
"thinking_delay": 0.0,
"typing_delay": 0.0,
"total_delay": 0.0,
"show_typing": 0.0
},
"show_typing": false,
"processing_time": 180.5,
"timestamp": "2025-11-24T18:30:45.123456",
"conversation_mode": "flirty",
"debug": null
}
```
### Response Felder
| Feld | Typ | Beschreibung |
|------|-----|--------------|
| `session_id` | string | Session-Identifier |
| `response` | string | Bot-Antwort (Deutsch, Kleinbuchstaben, lockerer Stil) |
| `character` | object | Charakter-Informationen |
| `photo_url` | string/null | URL zu Foto (falls Bot eines sendet) |
| `timing` | object | Simulierte menschliche Verzögerungen |
| `show_typing` | boolean | Ob Typing-Indikator angezeigt werden soll |
| `processing_time` | float | Server-Verarbeitungszeit in Sekunden |
| `timestamp` | string | Response-Zeitstempel (ISO 8601) |
| `conversation_mode` | string | Aktueller Konversationsmodus |
| `debug` | object/null | Debug-Informationen (nur wenn debug=true) |
### Response-Zeit
- **Durchschnitt:** 30-70 Sekunden pro Request
- **Modell:** Qwen2.5-14B-Instruct mit LoRA Fine-Tuning
- **Device:** GPU-Inferenz (NVIDIA RTX 4000 SFF Ada, 20GB VRAM)
- **Timeout:** 600 Sekunden (10 Minuten)
**Wichtig:** Implementieren Sie Client-seitiges Timeout-Handling!
---
## Zusätzliche Endpoints
### POST /api/v1/chat/preload
Laden Sie bestehende Konversationshistorie vor (z.B. bei Migration von anderen Plattformen).
**Use Cases:**
- Migration von Konversationen von einer anderen Plattform
- Wiederherstellung der Konversationshistorie nach Systemmigration
- Vorab-Befüllung von Konversationen für Tests
**Request:**
```json
{
"session_id": "user_12345",
"bot_context": {
"name": "Lisa",
"age": 25,
"location": "München",
"relationship_goal": "serious"
},
"messages": [
{
"role": "user",
"content": "Hey! Wie gehts?",
"timestamp": "2025-11-24T10:00:00Z"
},
{
"role": "assistant",
"content": "Hey! Mir gehts super! Und dir?",
"timestamp": "2025-11-24T10:00:05Z"
}
],
"source": "client_import",
"extract_facts": true,
"batch_size": 20
}
```
**Request Parameter:**
| Parameter | Typ | Pflicht | Beschreibung |
|-----------|-----|---------|--------------|
| `session_id` | string | Ja | Eindeutige Session-ID |
| `messages` | array | Ja | Liste der zu ladenden Nachrichten (min. 1) |
| `messages[].role` | string | Ja | Nachrichtenrolle: `user` oder `assistant` |
| `messages[].content` | string | Ja | Nachrichteninhalt |
| `messages[].timestamp` | string | Nein | ISO-Format Zeitstempel (optional) |
| `bot_context` | object | Nein | Bot-Kontext-Informationen |
| `character_id` | string | Nein | Charakter-ID (optional, kann stattdessen bot_context verwenden) |
| `source` | string | Nein | Quelle der Nachrichten (Standard: `client_import`) |
| `extract_facts` | boolean | Nein | Automatische Faktenextraktion (Standard: `true`) |
| `batch_size` | integer | Nein | Batch-Größe für Faktenextraktion (Standard: `20`) |
**Response:**
```json
{
"success": true,
"session_id": "user_12345",
"total_messages": 2,
"saved_count": 2,
"failed_count": 0,
"cached_in_redis": 2,
"extracted_facts": {
"user_facts": {
"name": "Max",
"age": "28",
"city": "München",
"profession": "Software-Entwickler"
},
"bot_facts": {
"favorite_food": "Pizza",
"hobbies": "Yoga und Reisen"
}
},
"facts_count": 6,
"error": null
}
```
**Was passiert während des Preload:**
1. **PostgreSQL-Speicherung**: Alle Nachrichten werden mit `is_preloaded=True` Flag gespeichert
2. **Redis-Cache**: Letzte 100 Nachrichten werden für schnellen Zugriff gecacht (24h TTL)
3. **Vector Memory**: Nachrichten werden zu ChromaDB für semantische Suche hinzugefügt
4. **Session-Erstellung**: Session wird erstellt, falls sie nicht existiert
5. **Charakter-Setup**: Charakter wird aus bot_context erstellt/geladen
6. **Faktenextraktion** (wenn `extract_facts=true`):
- Verarbeitet Nachrichten in Batches (Standard: 20 Nachrichten pro Batch)
- Extrahiert **User-Fakten** (was der User über sich gesagt hat)
- Extrahiert **Bot-Fakten** (was der Bot über sich gesagt hat)
- Speichert beide Typen in der Datenbank im Format: `{"user_facts": {...}, "bot_facts": {...}}`
- Verwendet BASE-Modell (Qwen2.5-14B-Instruct) für Extraktion
**Extrahierte Faktentypen:**
**User-Fakten:**
- `name`, `age`, `city`, `profession`, `hobbies`, `relationship_status`, `education`, `pets`, `siblings`, `favorite_food`, `favorite_music`, etc.
**Bot-Fakten:**
- `favorite_food`, `hobbies`, `interests`, `personality_traits`, `preferences`, etc.
**Performance:**
- **Verarbeitungszeit**: ~2-5 Sekunden pro Batch (20 Nachrichten)
- **Modell**: Qwen2.5-14B-Instruct (BASE-Modell, nicht LoRA)
- **Genauigkeit**: ~90%+ für explizite Fakten
### POST /api/v1/chat/{session_id}/extract-facts-batch
Extrahieren Sie Fakten aus der gesamten Konversationshistorie mittels Batch-Verarbeitung.
**Use Cases:**
- Vorgeladene Konversationen, die ohne Faktenextraktion importiert wurden
- Neuextraktion von Fakten nach Modell-Updates
- Behebung fehlender Fakten in alten Konversationen
**URL Parameter:**
| Parameter | Typ | Pflicht | Beschreibung |
|-----------|-----|---------|--------------|
| `session_id` | string | Ja | Zu verarbeitende Session-ID |
**Query Parameter:**
| Parameter | Typ | Pflicht | Beschreibung |
|-----------|-----|---------|--------------|
| `batch_size` | integer | Nein | Nachrichten pro Batch (Standard: `20`) |
**Response:**
```json
{
"success": true,
"session_id": "user_12345",
"total_messages": 150,
"user_messages": 75,
"processed_count": 75,
"extracted_facts": {
"user_facts": {
"name": "Max",
"age": "28",
"city": "München",
"profession": "Software-Entwickler",
"hobbies": "Sport und Reisen"
},
"bot_facts": {
"favorite_food": "Pizza und Pasta",
"hobbies": "Yoga und Fotografie"
}
},
"facts_count": 7
}
```
### GET /api/v1/session/{session_id}
Abrufen von Session-Informationen einschließlich Charakter-Details und Nachrichtenanzahl.
**Response:**
```json
{
"session_id": "user_12345",
"character": {
"name": "Lisa",
"age": 25,
"location": "Berlin",
"physical_description": "Ich bin 168cm groß, schlank mit langen braunen Haaren und grünen Augen.",
"personality_summary": "freundlich, offen, humorvoll",
"interests": ["Reisen", "Fotografie", "Yoga", "Kochen"]
},
"message_count": 42,
"created_at": "2025-11-24T10:00:00Z",
"last_activity": "2025-11-24T18:30:00Z"
}
```
**Hinweis:** Dieser Endpoint benötigt KEINE Authentifizierung (für Rückwärtskompatibilität).
Code-Beispiele
# Integration Examples
## Node.js / TypeScript
```javascript
const axios = require('axios');
async function sendChatMessage(sessionId, message, botContext = null) {
try {
const response = await axios.post(
'https://api.cupidbot.de/api/v1/chat',
{
session_id: sessionId,
message: message,
conversation_mode: 'flirty',
bot_context: botContext || {
name: 'Lisa',
age: 25,
location: 'Berlin',
relationship_goal: 'serious'
},
user_context: {
city: 'München',
current_date: new Date().toISOString().split('T')[0],
current_time: new Date().toTimeString().split(' ')[0].substring(0, 5),
weather: 'sonnig, 22°C'
},
read_delay_multiplier: 0.0,
thinking_delay_multiplier: 0.0,
typing_delay_multiplier: 0.0
},
{
headers: {
'X-API-Key': process.env.CUPIDBOT_API_KEY,
'Content-Type': 'application/json'
},
timeout: 600000 // 10 minutes timeout (30-70s average response time)
}
);
return {
message: response.data.response,
character: response.data.character,
timing: response.data.timing,
processing_time: response.data.processing_time
};
} catch (error) {
if (error.response?.status === 429) {
console.error('Rate limit exceeded');
} else if (error.response?.status === 401) {
console.error('Invalid API key');
} else if (error.code === 'ECONNABORTED') {
console.error('Request timeout (>10 minutes)');
} else {
console.error('Error:', error.message);
}
throw error;
}
}
// Verwendung
sendChatMessage('user_12345', 'Hey! Wie gehts?')
.then(result => {
console.log('Bot:', result.message);
console.log('Processing time:', result.processing_time, 'seconds');
})
.catch(err => console.error(err));
```
## Python
```python
import requests
import os
from typing import Optional, Dict
from datetime import datetime
def send_chat_message(
session_id: str,
message: str,
bot_context: Optional[Dict] = None
) -> Dict:
"""Send a message to CupidBot API"""
url = 'https://api.cupidbot.de/api/v1/chat'
payload = {
'session_id': session_id,
'message': message,
'conversation_mode': 'flirty',
'user_context': {
'city': 'München',
'current_date': datetime.now().strftime('%Y-%m-%d'),
'current_time': datetime.now().strftime('%H:%M'),
'weather': 'sonnig, 22°C'
},
'read_delay_multiplier': 0.0,
'thinking_delay_multiplier': 0.0,
'typing_delay_multiplier': 0.0
}
if bot_context:
payload['bot_context'] = bot_context
else:
payload['bot_context'] = {
'name': 'Lisa',
'age': 25,
'location': 'Berlin',
'relationship_goal': 'serious'
}
headers = {
'X-API-Key': os.getenv('CUPIDBOT_API_KEY'),
'Content-Type': 'application/json'
}
try:
response = requests.post(
url,
json=payload,
headers=headers,
timeout=600 # 10 minutes (30-70s average response time)
)
response.raise_for_status()
data = response.json()
return {
'message': data['response'],
'character': data['character'],
'timing': data['timing'],
'processing_time': data['processing_time']
}
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
print('Rate limit exceeded')
elif e.response.status_code == 401:
print('Invalid API key')
raise
except requests.exceptions.Timeout:
print('Request timeout (>10 minutes)')
raise
# Verwendung
result = send_chat_message('user_12345', 'Hey! Wie gehts?')
print(f"Bot: {result['message']}")
print(f"Processing time: {result['processing_time']} seconds")
```
## PHP
```php
<?php
function sendChatMessage($sessionId, $message, $botContext = null) {
$url = 'https://api.cupidbot.de/api/v1/chat';
$payload = [
'session_id' => $sessionId,
'message' => $message,
'conversation_mode' => 'flirty',
'user_context' => [
'city' => 'München',
'current_date' => date('Y-m-d'),
'current_time' => date('H:i'),
'weather' => 'sonnig, 22°C'
],
'read_delay_multiplier' => 0.0,
'thinking_delay_multiplier' => 0.0,
'typing_delay_multiplier' => 0.0
];
if ($botContext) {
$payload['bot_context'] = $botContext;
} else {
$payload['bot_context'] = [
'name' => 'Lisa',
'age' => 25,
'location' => 'Berlin',
'relationship_goal' => 'serious'
];
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . getenv('CUPIDBOT_API_KEY'),
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 600); // 10 minutes (30-70s average)
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new Exception('cURL error: ' . curl_error($ch));
}
curl_close($ch);
if ($httpCode === 429) {
throw new Exception('Rate limit exceeded');
} elseif ($httpCode === 401) {
throw new Exception('Invalid API key');
} elseif ($httpCode !== 200) {
throw new Exception('HTTP error: ' . $httpCode);
}
$data = json_decode($response, true);
return [
'message' => $data['response'],
'character' => $data['character'],
'timing' => $data['timing'],
'processing_time' => $data['processing_time']
];
}
// Verwendung
try {
$result = sendChatMessage('user_12345', 'Hey! Wie gehts?');
echo "Bot: " . $result['message'] . "\n";
echo "Processing time: " . $result['processing_time'] . " seconds\n";
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
?>
```
Best Practices
# Best Practices
## 1. Session Management
**Session-IDs:**
- Verwenden Sie eindeutige Session-IDs pro User-Konversation
- Format: `user_{user_id}` oder `session_{uuid}`
- Speichern Sie Session-IDs persistent für Konversationskontinuität
**Beispiel:**
```javascript
const sessionId = `user_${userId}_${Date.now()}`;
```
## 2. Timeout Handling
**Wichtig:** API-Responses dauern 30-70 Sekunden!
```javascript
// Node.js mit axios
const response = await axios.post(url, data, {
timeout: 120000 // 2 Minuten
});
// Python mit requests
response = requests.post(url, json=data, timeout=120)
// PHP mit cURL
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
```
## 3. Error Handling
```javascript
try {
const response = await sendChatMessage(sessionId, message);
// Success
} catch (error) {
if (error.response?.status === 429) {
// Rate limit exceeded
console.log('Zu viele Anfragen. Bitte warten.');
} else if (error.response?.status === 401) {
// Invalid API key
console.error('Ungültiger API Key');
} else if (error.code === 'ECONNABORTED') {
// Timeout
console.error('Request timeout (>120s)');
} else {
// Other errors
console.error('Fehler:', error.message);
}
}
```
## 4. Security
**API Key Sicherheit:**
- ❌ **NIEMALS** API Keys im Frontend-Code speichern
- ✅ Verwenden Sie Backend-Proxy für API-Calls
- ✅ Nutzen Sie Environment Variables
- ✅ Rotieren Sie Keys regelmäßig im Dashboard
**Beispiel Backend-Proxy (Node.js):**
```javascript
// Backend API Route
app.post('/api/chat', async (req, res) => {
// Authentifizieren Sie Ihren User
const userId = req.session.userId;
// Rufen Sie CupidBot API auf
const response = await axios.post(
'https://api.cupidbot.de/api/v1/chat',
{
session_id: `user_${userId}`,
message: req.body.message
},
{
headers: {
'X-API-Key': process.env.CUPIDBOT_API_KEY
}
}
);
res.json(response.data);
});
```
## 5. Rate Limiting
**Tarif-Limits beachten:**
- **Free Trial:** 100 Nachrichten / 7 Tage
- **Basic:** 500 Nachrichten / Tag
- **Pro:** 2.000 Nachrichten / Tag
- **Business:** 10.000 Nachrichten / Tag
- **Enterprise:** Unlimited
**Client-seitiges Rate Limiting:**
```javascript
let lastRequestTime = 0;
const MIN_REQUEST_INTERVAL = 1000; // 1 Sekunde
async function sendMessage(message) {
const now = Date.now();
const timeSinceLastRequest = now - lastRequestTime;
if (timeSinceLastRequest < MIN_REQUEST_INTERVAL) {
await new Promise(resolve =>
setTimeout(resolve, MIN_REQUEST_INTERVAL - timeSinceLastRequest)
);
}
lastRequestTime = Date.now();
return await apiCall(message);
}
```
## 6. Performance Optimierung
**Caching:**
- Cachen Sie Character-Informationen
- Speichern Sie Konversationshistorie lokal
- Nutzen Sie Redis für Session-Daten
**Connection Pooling:**
```javascript
// Node.js mit axios
const axiosInstance = axios.create({
baseURL: 'https://api.cupidbot.de',
timeout: 120000,
headers: {
'X-API-Key': process.env.CUPIDBOT_API_KEY
},
// Connection pooling
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true })
});
```
## 7. Monitoring
**Wichtige Metriken:**
- API Response Times (sollte 30-70s sein)
- Error Rates (sollte <1% sein)
- Rate Limit Hits
- Nachrichtenvolumen pro Tag
**Dashboard nutzen:**
- Überwachen Sie Ihre Usage im [Dashboard](/dashboard/usage)
- Setzen Sie Alerts für 80% Limit-Auslastung
- Analysieren Sie Error-Logs
## 8. Testing
**Vor Production:**
- Testen Sie mit verschiedenen Nachrichtentypen
- Prüfen Sie Timeout-Handling
- Testen Sie Error-Szenarien (ungültiger Key, Rate Limit)
- Validieren Sie Session-Kontinuität
**Playground nutzen:**
- Testen Sie API-Calls direkt im [Dashboard](/dashboard/keys)
- Experimentieren Sie mit verschiedenen `bot_context` Parametern
- Prüfen Sie Response-Qualität
Brauchen Sie Hilfe?
Unser Support-Team hilft Ihnen gerne bei der Integration