Split monolithic chat service into modular structure with Matrix client support, extract web server into per-resource route modules, introduce bootstrap/main-loop separation, and add comprehensive vitest coverage across services, repositories, and utilities. Adds project docs and CLAUDE.md agent instructions.
15 KiB
API Reference
Complete reference for the RedditBot web dashboard API.
Table of Contents
- Overview
- Authentication
- Base URL
- Bot Status & Control
- Activity & Messages
- Chat & Conversations
- Media
- Analytics
- Configuration
- Logs & Debugging
- Error Responses
- SSE Events
Overview
The RedditBot web dashboard exposes a REST API for monitoring and controlling the bot. All endpoints are served by the Express server.
Content-Type: application/json (except SSE)
Response Format: JSON
Authentication: None (local network only)
Authentication
No authentication is required. The dashboard is intended for local network access only.
Security Note: If exposing the dashboard externally, add authentication (e.g., basic auth, reverse proxy with auth).
Base URL
http://localhost:3000/api
The port is configured via config.web.port (default: 3000).
Bot Status & Control
Get Bot Statistics
Retrieve current bot statistics including running state, counts, and response rate.
GET /api/stats
Response:
{
"running": true,
"processed": 1250,
"sent": 980,
"responded": 312,
"responseRate": 0.318,
"hourlyCount": 15,
"timeUntilSlot": 45
}
Fields:
| Field | Type | Description |
|---|---|---|
running |
boolean | Whether the bot is currently running |
processed |
number | Total posts processed |
sent |
number | Total messages sent |
responded |
number | Total messages that received responses |
responseRate |
number | Response rate (0.0 to 1.0) |
hourlyCount |
number | Messages sent this hour |
timeUntilSlot |
number | Seconds until next message slot |
Start Bot
Start the bot's main processing loop.
POST /api/start
Response:
{
"success": true,
"message": "Bot started"
}
Errors:
{
"error": "Bot is already running"
}
Stop Bot
Stop the bot's main processing loop gracefully.
POST /api/stop
Response:
{
"success": true,
"message": "Bot stopping..."
}
Activity & Messages
Get Activity Log
Retrieve recent activity entries from the bot's log.
GET /api/activity
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 50 | Number of entries to return |
Response:
[
{
"level": "info",
"message": "Processed post abc123 from r/gonewild",
"timestamp": "2024-01-15T10:30:00.000Z"
},
{
"level": "warn",
"message": "AI model refused to analyze post def456",
"timestamp": "2024-01-15T10:28:00.000Z"
},
{
"level": "error",
"message": "Failed to send DM to user789: timeout",
"timestamp": "2024-01-15T10:25:00.000Z"
}
]
Get Posts by Author
Look up processed posts for a specific Reddit user.
GET /api/posts/by-author/:username
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
username |
string | Reddit username |
Response:
[
{
"id": "abc123",
"subreddit": "gonewild",
"author": "user123",
"title": "Summer vibes",
"image_url": "https://...",
"image_analysis": "{\"gender\":\"F\",\"description\":\"...\"}",
"generated_message": "Hey, you look amazing...",
"processed_at": 1716234567,
"message_sent": 1,
"error": null
}
]
Get Sent Messages
Retrieve recent sent messages.
GET /api/messages
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 50 | Number of messages to return |
Response:
[
{
"id": 1,
"post_id": "abc123",
"recipient": "user123",
"subject": "Stunning",
"message": "Hey, you look amazing...",
"sent_at": "2024-01-15T10:30:00.000Z",
"strategy_id": "compliment",
"got_response": 1,
"response_checked_at": "2024-01-15T11:00:00.000Z"
}
]
Get Successful Messages
Retrieve successful message/response pairs used for few-shot learning.
GET /api/successful
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 50 | Number of entries to return |
Response:
[
{
"id": 1,
"sent_message_id": 1,
"original_message": "Hey, you look amazing...",
"image_analysis": "{\"gender\":\"F\",\"description\":\"...\"}",
"post_title": "Summer vibes",
"response_snippet": "Thank you so much! 😊",
"subreddit": "gonewild",
"created_at": "2024-01-15T10:30:00.000Z"
}
]
Chat & Conversations
Get Active Chats
Retrieve cached active conversations.
GET /api/chats
Response:
[
{
"chatId": "chat_abc123",
"participant": "user456",
"lastMessage": "Thanks for the compliment!",
"timestamp": "2024-01-15T10:30:00.000Z",
"hasNewMessages": false
}
]
Fetch All Chats
Force-fetch all chats from Reddit (refreshes cache).
POST /api/chats/fetch-all
Response:
{
"success": true,
"count": 15
}
Get Conversations
Retrieve all cached conversations.
GET /api/conversations
Response:
[
{
"chatId": "chat_abc123",
"participants": ["user456", "bot"],
"messageCount": 24,
"lastUpdated": "2024-01-15T10:30:00.000Z",
"hasNewMessages": false,
"pendingReply": false,
"isUpsell": false
}
]
Get Conversation Detail
Retrieve full details of a specific conversation.
GET /api/conversations/:id
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Response:
{
"chatId": "chat_abc123",
"participants": ["user456", "bot"],
"messages": [
{
"author": "user456",
"text": "Hey there!",
"timestamp": "2024-01-15T10:00:00.000Z"
},
{
"author": "bot",
"text": "Hi! Thanks for the compliment!",
"timestamp": "2024-01-15T10:01:00.000Z"
},
{
"author": "user456",
"text": "Thanks for the compliment!",
"timestamp": "2024-01-15T10:02:00.000Z"
}
],
"lastUpdated": "2024-01-15T10:30:00.000Z",
"hasNewMessages": false,
"pendingReply": false,
"isUpsell": false
}
Suggest Reply
Generate an AI reply suggestion for a conversation.
POST /api/conversations/:id/suggest-reply
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Response:
{
"success": true,
"reply": "Thanks for reaching out! 😊 How's your day going?"
}
Send Reply
Send a manual reply in a conversation.
POST /api/conversations/:id/send-reply
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Request Body:
{
"text": "Thanks for reaching out! 😊"
}
Response:
{
"success": true,
"delivered": true
}
Approve Pending Reply
Approve an auto-reply that is pending manual approval.
POST /api/conversations/:id/approve-reply
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Response:
{
"success": true,
"message": "Reply sent"
}
Reject Pending Reply
Reject an auto-reply that is pending manual approval.
POST /api/conversations/:id/reject-reply
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Response:
{
"success": true,
"message": "Reply rejected"
}
Dismiss Upsell Flag
Clear the upsell/spam flag on a conversation.
POST /api/conversations/:id/dismiss-upsell
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id |
string | Chat ID |
Response:
{
"success": true,
"message": "Upsell flag dismissed"
}
Media
Get Media Gallery
Retrieve downloaded media files.
GET /api/media
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 100 | Number of files to return |
Response:
[
{
"hash": "abc123def456",
"filename": "abc123def456.jpg",
"size": 245678,
"conversationId": "chat_abc123",
"downloadedAt": "2024-01-15T10:30:00.000Z"
}
]
Get Media Sync Status
Retrieve current media sync status.
GET /api/media/sync
Response:
{
"running": false,
"mode": null,
"progress": 0,
"total": 0,
"completed": 0,
"lastSync": "2024-01-15T09:00:00.000Z"
}
Trigger Incremental Sync
Start an incremental media sync (top 10 conversations).
POST /api/media/sync
Response:
{
"success": true,
"message": "Incremental sync started"
}
Trigger Full Sync
Start a full media sync (all conversations).
POST /api/media/sync/full
Response:
{
"success": true,
"message": "Full sync started"
}
Analytics
Response Rate by Subreddit
Get response rates broken down by subreddit.
GET /api/analytics/by-subreddit
Response:
[
{
"subreddit": "gonewild",
"sent": 500,
"responded": 175,
"rate": 0.35
},
{
"subreddit": "ratemyboobs",
"sent": 300,
"responded": 90,
"rate": 0.30
},
{
"subreddit": "HomemadeNsfw",
"sent": 180,
"responded": 72,
"rate": 0.40
}
]
Response Rate by Strategy
Get response rates broken down by A/B test variant.
GET /api/analytics/by-strategy
Response:
[
{
"strategy_id": "compliment",
"sent": 400,
"responded": 140,
"rate": 0.35
},
{
"strategy_id": "question",
"sent": 350,
"responded": 147,
"rate": 0.42
},
{
"strategy_id": "observation",
"sent": 230,
"responded": 69,
"rate": 0.30
}
]
Daily Response Trend
Get daily response rates over time.
GET /api/analytics/trend
Response:
[
{
"date": "2024-01-01",
"sent": 18,
"responded": 6,
"rate": 0.33
},
{
"date": "2024-01-02",
"sent": 22,
"responded": 8,
"rate": 0.36
},
{
"date": "2024-01-03",
"sent": 15,
"responded": 4,
"rate": 0.27
}
]
Configuration
Get Runtime Configuration
Get current runtime configuration.
GET /api/config
Response:
{
"reddit": {
"subreddits": ["gonewild", "ratemyboobs"],
"pollInterval": 15,
"targetGender": "F",
"sellerKeywords": ["seller", "onlyfans"]
},
"openrouter": {
"model": "meta-llama/llama-3.2-90b-vision-preview",
"fallbackModels": ["google/gemini-2.0-flash-001"]
},
"rateLimit": {
"minDelayMs": 30000,
"maxMessagesPerHour": 20,
"jitterMs": 15000
},
"browser": {
"headless": true,
"userDataDir": "./data/browser"
},
"database": {
"path": "./data/reddit-bot.db"
},
"mediaSync": {
"enabled": true,
"intervalMinutes": 30
},
"autoReply": {
"enabled": true,
"autoSend": false,
"checkInterval": 10
},
"strategyVariants": [
{
"name": "compliment",
"enabled": true
}
],
"web": {
"port": 3000
},
"dryRun": false,
"fewShotExamples": 3,
"minStrategySamples": 10,
"explorationRate": 0.15
}
Update Runtime Configuration
Update runtime configuration values without restarting.
PUT /api/config
Request Body (partial updates supported):
{
"rateLimit": {
"minDelayMs": 45000,
"maxMessagesPerHour": 15
},
"dryRun": true,
"reddit": {
"pollInterval": 20
}
}
Response:
{
"success": true,
"config": { ... }
}
Errors:
{
"error": "Invalid config: rateLimit.minDelayMs must be a positive integer"
}
Logs & Debugging
SSE Log Stream
Connect to the realtime log stream via Server-Sent Events.
GET /api/logs/stream
Headers:
| Header | Value |
|---|---|
| Accept | text/event-stream |
Response (streaming):
event: log
data: {"level":"info","message":"Bot started","timestamp":"2024-01-15T10:30:00.000Z"}
event: log
data: {"level":"info","message":"Processed post abc123","timestamp":"2024-01-15T10:30:05.000Z"}
event: log
data: {"level":"warn","message":"AI refusal detected","timestamp":"2024-01-15T10:30:10.000Z"}
Client usage (JavaScript):
const eventSource = new EventSource('/api/logs/stream');
eventSource.onmessage = (event) => {
const log = JSON.parse(event.data);
console.log(log.level, log.message);
};
// Close connection
eventSource.close();
Get Recent Logs
Retrieve recent log entries via HTTP (non-streaming).
GET /api/logs
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 100 | Number of entries to return |
level |
string | all | Filter by level: info, warn, error |
Response: Same format as /api/activity.
Get Rate Limiter Timers
Get current rate limiter status.
GET /api/timers
Response:
{
"timeUntilSlot": 45,
"hourlyCount": 15,
"maxMessagesPerHour": 20,
"isThrottled": false
}
Debug: Inspect DOM
Inspect the current chat DOM structure (for debugging shadow DOM issues).
POST /api/debug/inspect-dom
Response:
{
"success": true,
"domStructure": { ... }
}
Debug: Manual Response Check
Trigger a manual response check (bypasses scheduled interval).
POST /api/debug/check-responses
Response:
{
"success": true,
"responsesFound": 3,
"updated": 2
}
Error Responses
All error responses follow this format:
{
"error": "Error message describing what went wrong"
}
Common Error Codes
| HTTP Status | Description | Example |
|---|---|---|
| 400 | Bad Request | Invalid query parameter |
| 404 | Not Found | Resource not found |
| 500 | Internal Server Error | Unexpected error |
SSE Events
The SSE log stream (/api/logs/stream) emits the following events:
log Event
Emitted for every log entry.
Data Format:
{
"level": "info",
"message": "Processed post abc123 from r/gonewild",
"timestamp": "2024-01-15T10:30:00.000Z"
}
Log Levels:
| Level | Description |
|---|---|
info |
Normal operation |
warn |
Warning (recoverable issue) |
error |
Error (action failed) |
debug |
Debug information |