This document provides complete documentation for the Personal OS REST API. The API is built with FastAPI and runs on port 8000 by default.
Base URL: http://localhost:8000
Interactive Documentation: After starting the backend, visit http://localhost:8000/docs for Swagger UI.
# Navigate to backend folder
cd web/backend
# Install dependencies (first time only)
pip install -r requirements.txt
# Create .env file with API key
echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" > .env
# Start the server
uvicorn main:app --reload --port 8000# Check if server is running
curl http://localhost:8000/api/health
# List all reports
curl http://localhost:8000/api/reports
# Submit a YouTube video for analysis
curl -X POST http://localhost:8000/api/analysis/youtube \
-H "Content-Type: application/json" \
-d '{"url": "https://youtube.com/watch?v=abc123", "model": "sonnet"}'The API uses API key authentication for the Anthropic Claude API calls. The key is stored server-side in the .env file.
No client-side authentication is required for the local API. All requests from localhost are allowed.
For production deployments, consider adding:
- API key header authentication
- OAuth2 / JWT tokens
- Rate limiting
All API responses follow a consistent JSON format:
{
"data": { ... },
"status": "success"
}{
"reports": [ ... ],
"total": 150,
"page": 1,
"page_size": 20
}{
"detail": "Error message describing what went wrong",
"status_code": 400
}The API uses standard HTTP status codes:
| Status Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Invalid parameters |
| 404 | Not Found - Resource doesn't exist |
| 422 | Validation Error - Invalid request body |
| 500 | Server Error - Something went wrong |
| Error | Cause | Solution |
|---|---|---|
ANTHROPIC_API_KEY not configured |
Missing API key | Create .env file with key |
Report not found |
Invalid report ID | Check ID exists via list endpoint |
yt-dlp not found |
Missing dependency | Run pip install yt-dlp |
Content fetch failed |
URL unreachable | Check URL is accessible |
Retrieve a paginated list of all reports.
GET /api/reportsQuery Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 | Page number |
page_size |
integer | 20 | Items per page (max 100) |
type |
string | null | Filter by content type |
search |
string | null | Full-text search query |
Example Request:
curl "http://localhost:8000/api/reports?page=1&type=youtube&search=habits"Example Response:
{
"reports": [
{
"id": 42,
"filename": "2024-01-15_building-habits.md",
"filepath": "reports/youtube/2024-01-15_building-habits.md",
"title": "Building Better Habits",
"source_url": "https://youtube.com/watch?v=abc123",
"content_type": "youtube",
"created_at": "2024-01-15T10:30:00Z",
"summary": "A comprehensive guide to building lasting habits...",
"word_count": 2500
}
],
"total": 1,
"page": 1,
"page_size": 20
}Retrieve a specific report by ID.
GET /api/reports/{report_id}Path Parameters:
| Parameter | Type | Description |
|---|---|---|
report_id |
integer | The report ID |
Example Request:
curl http://localhost:8000/api/reports/42Example Response:
{
"id": 42,
"filename": "2024-01-15_building-habits.md",
"filepath": "reports/youtube/2024-01-15_building-habits.md",
"title": "Building Better Habits",
"source_url": "https://youtube.com/watch?v=abc123",
"content_type": "youtube",
"created_at": "2024-01-15T10:30:00Z",
"summary": "A comprehensive guide...",
"word_count": 2500,
"content": "# Building Better Habits\n\n**Source**: https://youtube.com/watch?v=abc123\n..."
}Full-text search across all reports.
GET /api/reports/searchQuery Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | Yes | Search query |
type |
string | No | Filter by content type |
limit |
integer | No | Max results (default 20) |
Example Request:
curl "http://localhost:8000/api/reports/search?q=machine+learning&type=paper"Delete a report by ID.
DELETE /api/reports/{report_id}Example Request:
curl -X DELETE http://localhost:8000/api/reports/42Submit a YouTube video for analysis.
POST /api/analysis/youtubeRequest Body:
{
"url": "https://youtube.com/watch?v=abc123",
"model": "sonnet"
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | YouTube video URL |
model |
string | No | Model to use: haiku, sonnet, opus (default: sonnet) |
Example Request:
curl -X POST http://localhost:8000/api/analysis/youtube \
-H "Content-Type: application/json" \
-d '{"url": "https://youtube.com/watch?v=abc123"}'Example Response:
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"message": "Analysis job created"
}Submit a web article for analysis.
POST /api/analysis/articleRequest Body:
{
"url": "https://example.com/blog-post",
"model": "sonnet"
}Submit an arXiv paper for analysis.
POST /api/analysis/arxivRequest Body:
{
"url": "https://arxiv.org/abs/2401.12345",
"model": "sonnet"
}Submit a podcast episode for analysis.
POST /api/analysis/podcastRequest Body:
{
"url": "https://example.com/podcast.mp3",
"model": "sonnet",
"transcribe": true
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | Podcast audio URL or file path |
model |
string | No | AI model to use |
transcribe |
boolean | No | Whether to transcribe audio (default: true) |
Submit a PDF document for analysis.
POST /api/analysis/pdfRequest Body (multipart/form-data):
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | PDF file upload |
model |
string | No | AI model to use |
Example Request:
curl -X POST http://localhost:8000/api/analysis/pdf \
-F "file=@document.pdf" \
-F "model=sonnet"Check the status of an analysis job.
GET /api/analysis/jobs/{job_id}Path Parameters:
| Parameter | Type | Description |
|---|---|---|
job_id |
string | UUID of the analysis job |
Example Response (Pending):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "running",
"progress_message": "Analyzing content..."
}Example Response (Completed):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"result_filepath": "reports/youtube/2024-01-15_video-title.md"
}Example Response (Failed):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "failed",
"error_message": "Could not fetch video transcript"
}Retrieve today's activity log.
GET /api/logs/todayExample Response:
{
"date": "2024-01-15",
"content": "# Activity Log - 2024-01-15\n\n## Videos Watched\n- [Building Habits](../reports/youtube/...) - 10:30\n..."
}Retrieve activity log for a specific date.
GET /api/logs/{date}Path Parameters:
| Parameter | Type | Description |
|---|---|---|
date |
string | Date in YYYY-MM-DD format |
Example Request:
curl http://localhost:8000/api/logs/2024-01-10Process multiple URLs at once.
POST /api/batchRequest Body:
{
"urls": [
"https://youtube.com/watch?v=abc123",
"https://example.com/article",
"https://arxiv.org/abs/2401.12345"
],
"model": "sonnet"
}Example Response:
{
"batch_id": "batch-550e8400",
"jobs": [
{"job_id": "job-1", "url": "https://youtube.com/watch?v=abc123", "status": "pending"},
{"job_id": "job-2", "url": "https://example.com/article", "status": "pending"},
{"job_id": "job-3", "url": "https://arxiv.org/abs/2401.12345", "status": "pending"}
]
}Check status of all jobs in a batch.
GET /api/batch/{batch_id}Get all available tags.
GET /api/tagsExample Response:
{
"tags": [
{"id": 1, "name": "productivity", "color": "#3B82F6"},
{"id": 2, "name": "ai", "color": "#10B981"},
{"id": 3, "name": "learning", "color": "#F59E0B"}
]
}Create a new tag.
POST /api/tagsRequest Body:
{
"name": "technology",
"color": "#8B5CF6"
}Associate a tag with a report.
POST /api/tags/{tag_id}/reports/{report_id}Remove a tag from a report.
DELETE /api/tags/{tag_id}/reports/{report_id}Get all reports with a specific tag.
GET /api/tags/{tag_id}/reportsGet all collections.
GET /api/collectionsExample Response:
{
"collections": [
{"id": 1, "name": "AI Research", "description": "Papers and videos about AI", "report_count": 15},
{"id": 2, "name": "Productivity", "description": "Self-improvement content", "report_count": 8}
]
}Create a new collection.
POST /api/collectionsRequest Body:
{
"name": "Machine Learning",
"description": "ML papers and tutorials"
}POST /api/collections/{collection_id}/reports/{report_id}DELETE /api/collections/{collection_id}/reports/{report_id}Get all reports in a collection.
GET /api/collections/{collection_id}/reportsGet all RSS feed subscriptions.
GET /api/rssExample Response:
{
"feeds": [
{
"id": 1,
"url": "https://blog.example.com/feed.xml",
"title": "Example Blog",
"content_type": "article",
"last_checked": "2024-01-15T10:00:00Z"
}
]
}Add a new RSS feed subscription.
POST /api/rssRequest Body:
{
"url": "https://blog.example.com/feed.xml",
"content_type": "article"
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | RSS feed URL |
content_type |
string | No | Type for new items: youtube, article, etc. |
DELETE /api/rss/{feed_id}Check all feeds for new content.
POST /api/rss/checkExample Response:
{
"new_items": 5,
"items": [
{"title": "New Blog Post", "url": "https://...", "feed": "Example Blog"}
]
}Export all reports in Obsidian-compatible format.
POST /api/export/obsidianRequest Body:
{
"include_tags": true,
"include_backlinks": true
}Example Response:
{
"export_path": "exports/obsidian/2024-01-15",
"file_count": 42,
"total_size": "2.5 MB"
}Export reports as Notion-compatible JSON.
POST /api/export/notionRequest Body:
{
"report_ids": [1, 2, 3]
}Generate Anki flashcards from reports.
POST /api/export/flashcardsRequest Body:
{
"report_ids": [1, 2, 3],
"format": "anki"
}Example Response:
{
"export_path": "exports/anki/flashcards-2024-01-15.txt",
"card_count": 87
}Transcribe an audio file using Whisper.
POST /api/transcriptionRequest Body (multipart/form-data):
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | Audio file (MP3, M4A, WAV) |
language |
string | No | Language code (default: auto-detect) |
Example Response:
{
"text": "Full transcription text...",
"language": "en",
"duration": 3600
}Transcribe audio from a URL.
POST /api/transcription/urlRequest Body:
{
"url": "https://example.com/podcast.mp3"
}Retrieve the knowledge graph with concepts and relationships.
GET /api/knowledge-graphQuery Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 100 | Maximum number of concepts to return |
Example Response:
{
"nodes": [
{"id": 1, "name": "Machine Learning", "type": "topic", "description": "AI approach using data patterns", "mention_count": 15},
{"id": 2, "name": "Neural Networks", "type": "concept", "description": "Computing systems inspired by brain", "mention_count": 12}
],
"links": [
{"source": 1, "target": 2, "type": "contains", "strength": 0.8}
]
}Get detailed information about a specific concept.
GET /api/knowledge-graph/concept/{concept_id}Example Response:
{
"id": 1,
"name": "Machine Learning",
"concept_type": "topic",
"description": "AI approach using data patterns",
"mention_count": 15,
"reports": [
{"id": 42, "title": "Introduction to ML", "content_type": "youtube"},
{"id": 43, "title": "Deep Learning Basics", "content_type": "paper"}
]
}Extract concepts from a specific report.
POST /api/knowledge-graph/extract/{report_id}Example Response:
{
"concepts_extracted": 8,
"concepts_stored": 6,
"relationships_stored": 12
}Extract concepts from multiple reports.
POST /api/knowledge-graph/extract-allQuery Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Maximum reports to process |
Ask a question across your knowledge base.
POST /api/qaRequest Body:
{
"question": "What are the best practices for habit formation?",
"model": "sonnet",
"max_reports": 5
}| Field | Type | Required | Description |
|---|---|---|---|
question |
string | Yes | The question to ask |
model |
string | No | AI model: haiku, sonnet, opus |
max_reports |
integer | No | Maximum reports to search (default: 5) |
Example Response:
{
"answer": "Based on your knowledge base, the best practices for habit formation include...",
"sources": [
{"id": 42, "title": "Building Better Habits", "content_type": "youtube", "source_url": "https://..."},
{"id": 43, "title": "Atomic Habits Summary", "content_type": "article", "source_url": "https://..."}
],
"tokens_used": 2500,
"cost": 0.0075,
"model": "claude-sonnet-4-20250514",
"followup_suggestions": [
"How long does it take to form a habit?",
"What are common habit formation mistakes?"
]
}Get suggested questions based on your content.
GET /api/qa/suggestionsExample Response:
{
"suggestions": [
"What are the key differences between supervised and unsupervised learning?",
"How do transformers work in NLP?",
"What productivity techniques are mentioned in your videos?"
]
}Compare two reports with AI-generated analysis.
POST /api/comparisonRequest Body:
{
"report_id_a": 42,
"report_id_b": 43,
"model": "sonnet"
}Example Response:
{
"comparison": "## Similarities\n\n- Both discuss habit formation...\n\n## Differences\n\n- Report A focuses on...",
"report_a": {"id": 42, "title": "Building Habits", "content_type": "youtube", "source_url": "https://..."},
"report_b": {"id": 43, "title": "Atomic Habits", "content_type": "article", "source_url": "https://..."},
"tokens_used": 3000,
"cost": 0.009,
"model": "claude-sonnet-4-20250514"
}Get suggested reports to compare with a given report.
GET /api/comparison/suggestions/{report_id}Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 5 | Maximum suggestions to return |
Example Response:
{
"suggestions": [
{"id": 43, "title": "Related Topic", "content_type": "article"},
{"id": 44, "title": "Similar Video", "content_type": "youtube"}
]
}Get available TTS voices.
GET /api/tts/voicesExample Response:
{
"voices": [
{"id": "alloy", "description": "Neutral and balanced"},
{"id": "echo", "description": "Warm and conversational"},
{"id": "fable", "description": "British accent"},
{"id": "onyx", "description": "Deep and authoritative"},
{"id": "nova", "description": "Friendly and upbeat"},
{"id": "shimmer", "description": "Soft and gentle"}
],
"default": "nova"
}Generate audio for a report.
POST /api/tts/{report_id}Request Body:
{
"voice": "nova",
"force_regenerate": false
}| Field | Type | Required | Description |
|---|---|---|---|
voice |
string | No | Voice ID (default: nova) |
force_regenerate |
boolean | No | Force regeneration even if cached |
Example Response:
{
"audio_path": "audio/42_nova.mp3",
"voice": "nova",
"duration_estimate": 420,
"cached": false
}Get existing audio versions for a report.
GET /api/tts/{report_id}Example Response:
{
"report_id": 42,
"audio_versions": [
{"voice": "nova", "description": "Friendly and upbeat", "path": "audio/42_nova.mp3"},
{"voice": "onyx", "description": "Deep and authoritative", "path": "audio/42_onyx.mp3"}
]
}Stream audio file for playback.
GET /api/tts/{report_id}/stream/{voice}Returns audio file with Content-Type: audio/mpeg.
Get reports due for review.
GET /api/reviews/dueQuery Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 10 | Maximum items to return |
Example Response:
{
"items": [
{
"id": 1,
"report_id": 42,
"title": "Building Habits",
"content_type": "youtube",
"source_url": "https://...",
"repetitions": 3,
"ease_factor": 2.5,
"interval": 7,
"next_review": "2024-01-15",
"summary": "A guide to building lasting habits..."
}
],
"count": 5
}Add a report to the spaced repetition queue.
POST /api/reviews/addRequest Body:
{
"report_id": 42
}Example Response:
{
"message": "Report added to review queue"
}Submit a review rating for a report.
POST /api/reviews/{report_id}/reviewRequest Body:
{
"quality": 4
}| Field | Type | Required | Description |
|---|---|---|---|
quality |
integer | Yes | Rating 0-5 (0=blackout, 5=perfect recall) |
Quality Scale:
- 0: Complete blackout, no memory
- 1: Incorrect, but recognized when shown
- 2: Incorrect, but seemed familiar
- 3: Correct with difficulty
- 4: Correct with some hesitation
- 5: Perfect recall
Example Response:
{
"report_id": 42,
"next_review": "2024-01-22",
"interval": 7,
"ease_factor": 2.6,
"repetitions": 4
}Get spaced repetition statistics.
GET /api/reviews/statsExample Response:
{
"total_reviews": 150,
"due_today": 5,
"reviewed_today": 3,
"average_ease": 2.45,
"streak": 7
}Analyze the credibility of a report's source.
GET /api/credibility/{report_id}Example Response:
{
"overall_score": 78,
"domain_score": 85,
"ai_score": 72,
"source_quality": {"score": 80, "notes": "Established author with relevant expertise"},
"evidence_quality": {"score": 75, "notes": "Claims supported by citations"},
"bias_level": {"score": 70, "notes": "Some promotional language detected"},
"fact_checkability": {"score": 85, "notes": "Most claims are verifiable"},
"red_flags": [
"Some claims lack citations",
"Promotional language in conclusion"
],
"strengths": [
"Author credentials verified",
"Multiple expert sources cited",
"Data from reputable studies"
],
"recommendation": "Generally reliable source. Verify promotional claims independently."
}Get all learning goals with progress.
GET /api/goalsExample Response:
{
"goals": [
{
"id": 1,
"title": "Learn Machine Learning",
"description": "Complete ML fundamentals",
"keywords": ["machine learning", "AI", "neural networks"],
"target_count": 20,
"current_count": 12,
"status": "active",
"progress_percent": 60,
"created_at": "2024-01-01T00:00:00Z"
}
]
}Create a new learning goal.
POST /api/goalsRequest Body:
{
"title": "Master Python",
"description": "Learn advanced Python concepts",
"keywords": ["python", "programming", "async"],
"target_count": 15
}| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Goal title |
description |
string | No | Goal description |
keywords |
array | No | Keywords for auto-linking reports |
target_count |
integer | No | Target number of reports (default: 10) |
Get a specific goal with linked reports.
GET /api/goals/{goal_id}Update goal status.
PUT /api/goals/{goal_id}Request Body:
{
"status": "completed"
}| Status | Description |
|---|---|
active |
Currently working on |
paused |
Temporarily paused |
completed |
Goal achieved |
Delete a learning goal.
DELETE /api/goals/{goal_id}Link a report to a learning goal.
POST /api/goals/{goal_id}/reports/{report_id}List supported translation languages.
GET /api/translate/languagesExample Response:
{
"languages": [
{"code": "es", "name": "Spanish"},
{"code": "fr", "name": "French"},
{"code": "de", "name": "German"},
{"code": "it", "name": "Italian"},
{"code": "pt", "name": "Portuguese"},
{"code": "ja", "name": "Japanese"},
{"code": "ko", "name": "Korean"},
{"code": "zh", "name": "Chinese (Simplified)"},
{"code": "ru", "name": "Russian"},
{"code": "ar", "name": "Arabic"}
]
}Translate a report to another language.
POST /api/translate/{report_id}Request Body:
{
"target_language": "es",
"sections": []
}| Field | Type | Required | Description |
|---|---|---|---|
target_language |
string | Yes | Language code (e.g., es, fr, de) |
sections |
array | No | Specific sections to translate (empty = all) |
Example Response:
{
"report_id": 42,
"original_title": "Building Better Habits",
"translated_title": "Construyendo Mejores Hábitos",
"translated_content": "# Construyendo Mejores Hábitos\n\n**Fuente**: https://...\n...",
"target_language": "es",
"language_name": "Spanish"
}Get personalized content recommendations.
GET /api/recommendationsQuery Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 10 | Maximum recommendations |
Example Response:
{
"recommendations": [
{
"id": 42,
"title": "Advanced Python Techniques",
"content_type": "youtube",
"source_url": "https://...",
"reason": "Explore more youtube content",
"score": 0.85
},
{
"id": 43,
"title": "ML Fundamentals Review",
"content_type": "paper",
"source_url": "https://...",
"reason": "Revisit older content",
"score": 0.72
}
],
"message": null
}Find reports similar to a given report.
GET /api/recommendations/similar/{report_id}Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 5 | Maximum results |
Example Response:
{
"similar": [
{"id": 43, "title": "Related Topic", "content_type": "article", "source_url": null, "reason": "Similar content", "score": 0.78}
]
}Get trending topics from recent content.
GET /api/recommendations/trendingExample Response:
{
"trending": [
{"topic": "machine", "count": 12},
{"topic": "learning", "count": 10},
{"topic": "python", "count": 8},
{"topic": "productivity", "count": 6}
]
}Check if the API is running.
GET /api/healthExample Response:
{
"status": "healthy",
"version": "1.0.0"
}Re-sync the database with the filesystem. This endpoint is called by:
- CLI commands - After saving reports (via curl)
- Sidebar Sync button - User-triggered manual sync
- Periodic scanner - Automatically every 30 seconds (internal)
Use this when reports created via CLI aren't appearing in the web UI.
POST /api/syncExample Request:
# Called automatically by CLI commands after saving reports
curl -s -X POST "http://localhost:8000/api/sync" > /dev/null 2>&1 || true
# Or explicitly to trigger a sync
curl -X POST http://localhost:8000/api/syncExample Response:
{
"synced": true,
"reports_added": 3,
"reports_removed": 0
}Background: On Windows, the FileWatcher (using watchdog library) may not detect files created by certain tools like Claude Code's Write tool. This endpoint provides a reliable way to ensure the database stays in sync with the filesystem.
List available AI models and their costs.
GET /api/modelsExample Response:
{
"models": [
{
"key": "haiku",
"id": "claude-3-5-haiku-latest",
"name": "Claude 3.5 Haiku",
"input_cost": 0.80,
"output_cost": 4.00
},
{
"key": "sonnet",
"id": "claude-sonnet-4-20250514",
"name": "Claude Sonnet 4",
"input_cost": 3.00,
"output_cost": 15.00
},
{
"key": "opus",
"id": "claude-opus-4-20250514",
"name": "Claude Opus 4",
"input_cost": 15.00,
"output_cost": 75.00
}
],
"default": "sonnet"
}The API supports WebSocket connections for real-time job status updates.
const ws = new WebSocket('ws://localhost:8000/ws/jobs/{job_id}');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Status:', data.status);
console.log('Progress:', data.progress_message);
};| Event | Description |
|---|---|
status_update |
Job status changed |
progress |
Progress message updated |
completed |
Job finished successfully |
failed |
Job failed with error |
import requests
BASE_URL = "http://localhost:8000"
# Submit YouTube video
response = requests.post(f"{BASE_URL}/api/analysis/youtube", json={
"url": "https://youtube.com/watch?v=abc123",
"model": "sonnet"
})
job_id = response.json()["job_id"]
# Poll for completion
import time
while True:
status = requests.get(f"{BASE_URL}/api/analysis/jobs/{job_id}").json()
if status["status"] in ["completed", "failed"]:
break
time.sleep(2)
print(f"Report saved to: {status.get('result_filepath')}")const BASE_URL = 'http://localhost:8000';
// Submit article for analysis
async function analyzeArticle(url) {
const response = await fetch(`${BASE_URL}/api/analysis/article`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, model: 'sonnet' })
});
return response.json();
}
// Get all reports
async function getReports(page = 1, type = null) {
const params = new URLSearchParams({ page: String(page) });
if (type) params.set('type', type);
const response = await fetch(`${BASE_URL}/api/reports?${params}`);
return response.json();
}# Analyze a YouTube video
curl -X POST http://localhost:8000/api/analysis/youtube \
-H "Content-Type: application/json" \
-d '{"url": "https://youtube.com/watch?v=abc123"}'
# Search reports
curl "http://localhost:8000/api/reports/search?q=machine+learning"
# Subscribe to RSS feed
curl -X POST http://localhost:8000/api/rss \
-H "Content-Type: application/json" \
-d '{"url": "https://blog.example.com/feed.xml", "content_type": "article"}'
# Export to Obsidian
curl -X POST http://localhost:8000/api/export/obsidian \
-H "Content-Type: application/json" \
-d '{"include_tags": true}'The API does not enforce rate limits by default. However, the Anthropic API has its own rate limits:
| Tier | Requests/min | Tokens/min |
|---|---|---|
| Free | 50 | 40,000 |
| Build | 1,000 | 80,000 |
| Scale | 4,000 | 400,000 |
Consider implementing local caching to reduce API calls.
Improvements:
- Enhanced sync reliability with four redundant mechanisms:
- FileWatcher (real-time)
- Periodic Scanner (every 30 seconds)
- CLI Notification (after saving reports)
- Manual Sync Button (user-triggered)
- Added "Sync Reports" button in sidebar for manual database sync
- All CLI commands now notify backend after saving reports
- Improved POST /api/sync documentation
New Features:
- Knowledge Graph API - Concept extraction and visualization
- Q&A System API - Natural language questions across knowledge base
- Comparison API - Side-by-side report analysis
- Text-to-Speech API - Audio generation with OpenAI TTS
- Spaced Repetition API - SM-2 algorithm for review scheduling
- Credibility Analysis API - Source trustworthiness scoring
- Learning Goals API - Progress tracking and goal management
- Translation API - Multi-language report translation
- Recommendations API - Personalized content suggestions
- Initial API release
- Core endpoints for reports, analysis, logs
- Batch processing support
- Tags and collections
- RSS feed management
- Export to Obsidian/Notion
- Anki flashcard generation
- Audio transcription with Whisper
API Reference - Last updated: 2025-12-27
Built with Claude Code powered by Claude Opus 4.5