callumalpass_tasknotes/docs/HTTP_API.md
Callum Alpass ac57dd738a feat: add OpenAPI specification and Pomodoro API endpoints
## OpenAPI Specification
- Add decorator-based OpenAPI system with @OpenAPIController and @OpenAPI decorators
- Generate machine-readable OpenAPI 3.0 spec at /api/docs
- Serve interactive Swagger UI documentation at /api/docs/ui
- Complete schema definitions for all API types and responses
- Enable TypeScript experimental decorators support

## Pomodoro API Endpoints
- POST /api/pomodoro/start - Start new pomodoro session with optional task
- POST /api/pomodoro/stop - Stop current session
- POST /api/pomodoro/pause - Pause running session
- POST /api/pomodoro/resume - Resume paused session
- GET /api/pomodoro/status - Get current session status and statistics
- GET /api/pomodoro/sessions - Get session history with filtering
- GET /api/pomodoro/stats - Get daily/date-specific statistics

## Documentation Updates
- Add comprehensive HTTP API documentation with pomodoro examples
- Include JavaScript PomodoroController integration example
- Update feature documentation with view types and settings
- Improve navigation structure across documentation files

## Dependencies
- Add reflect-metadata for decorator metadata support
- Remove unused express dependency
- Update TypeScript configuration for decorator support

All endpoints include proper error handling, OpenAPI documentation, and support for recurring task integration.
2025-08-13 22:12:14 +10:00

575 lines
11 KiB
Markdown

# TaskNotes HTTP API
The TaskNotes HTTP API allows external applications to interact with your TaskNotes data. This enables powerful integrations with browsers, automation tools, mobile apps, and custom scripts.
## Quick Start
1. **Enable API**: Go to TaskNotes Settings → HTTP API tab (desktop only)
2. **Configure**: Set port (default 8080) and optional auth token
3. **Restart**: Restart Obsidian to start the server
4. **Test**: `curl http://localhost:8080/api/health`
5. **Explore**: Visit `http://localhost:8080/api/docs/ui` for interactive documentation
## Interactive Documentation
TaskNotes provides comprehensive API documentation through Swagger UI:
- **OpenAPI Specification**: `GET /api/docs` - Machine-readable API spec in OpenAPI 3.0 format
- **Interactive Docs**: `GET /api/docs/ui` - Swagger UI for exploring and testing endpoints
The interactive documentation includes:
- Complete endpoint documentation with examples
- Request/response schemas
- Try-it-out functionality for testing endpoints
- Authentication setup for protected endpoints
## Authentication
### Optional Bearer Token
```bash
# Set token in settings, then use in requests:
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/tasks
```
### No Authentication
If no token is configured, all requests are allowed from localhost.
## Base URL
```
http://localhost:{PORT}/api
```
Default port is 8080 (configurable in settings).
## Response Format
All endpoints return JSON in this format:
```json
{
"success": true,
"data": { /* response data */ },
"message": "optional success message"
}
```
Error responses:
```json
{
"success": false,
"error": "Error description"
}
```
## Endpoints
### Health Check
```
GET /api/health
```
**Response:**
```json
{
"success": true,
"data": {
"status": "ok",
"timestamp": "2025-08-12T10:30:00.000Z"
}
}
```
### Tasks
#### List Tasks
```
GET /api/tasks
```
**Query Parameters:**
- `status` - Filter by status (e.g., "open", "completed")
- `priority` - Filter by priority (e.g., "High", "Normal")
- `project` - Filter by project name (partial match)
- `tag` - Filter by tag (partial match)
- `overdue` - "true" for overdue tasks only
- `completed` - "true" or "false"
- `archived` - "true" or "false"
- `due_before` - ISO date (e.g., "2025-08-15")
- `due_after` - ISO date
- `sort` - Field to sort by (e.g., "due:asc", "priority:desc")
- `limit` - Max number of results
- `offset` - Skip this many results
**Examples:**
```bash
# All active tasks
curl "http://localhost:8080/api/tasks?completed=false&archived=false"
# High priority overdue tasks
curl "http://localhost:8080/api/tasks?priority=High&overdue=true"
# Tasks due this week, sorted by due date
curl "http://localhost:8080/api/tasks?due_before=2025-08-19&sort=due:asc"
```
**Response:**
```json
{
"success": true,
"data": {
"tasks": [
{
"path": "TaskNotes/Tasks/sample-task.md",
"title": "Review quarterly budget",
"status": "open",
"priority": "High",
"due": "2025-08-15",
"scheduled": "2025-08-14",
"tags": ["work", "finance"],
"projects": ["[[Q3 Planning]]"],
"contexts": ["@office"],
"dateCreated": "2025-08-10T09:00:00.000Z",
"dateModified": "2025-08-10T09:00:00.000Z"
}
],
"total": 150,
"filtered": 1
}
}
```
#### Create Task
```
POST /api/tasks
```
**Request Body:**
```json
{
"title": "New task title",
"priority": "High",
"status": "open",
"due": "2025-08-15",
"scheduled": "2025-08-14",
"tags": ["email", "urgent"],
"projects": ["[[Work Project]]"],
"contexts": ["@computer"],
"details": "Additional task description",
"timeEstimate": 60
}
```
**Required Fields:**
- `title` - Task title (max 200 characters)
**Optional Fields:**
- `priority` - Task priority
- `status` - Task status
- `due` - Due date (ISO format)
- `scheduled` - Scheduled date (ISO format)
- `tags` - Array of tag strings
- `projects` - Array of project links
- `contexts` - Array of context strings
- `details` - Task description/details
- `timeEstimate` - Estimated time in minutes
#### Get Single Task
```
GET /api/tasks/{id}
```
Where `{id}` is the task file path (URL-encoded).
#### Update Task
```
PUT /api/tasks/{id}
```
**Request Body:** Same format as create task, with partial updates supported.
#### Delete Task
```
DELETE /api/tasks/{id}
```
### Time Tracking
#### Start Time Tracking
```
POST /api/tasks/{id}/time/start
```
#### Stop Time Tracking
```
POST /api/tasks/{id}/time/stop
```
### Task Actions
#### Toggle Status
```
POST /api/tasks/{id}/toggle-status
```
Toggles between open/completed status.
#### Toggle Archive
```
POST /api/tasks/{id}/archive
```
Archives or unarchives the task.
#### Complete Recurring Instance
```
POST /api/tasks/{id}/complete-instance
```
**Request Body:**
```json
{
"date": "2025-08-12"
}
```
### Advanced Queries
#### Query Tasks
```
POST /api/tasks/query
```
**Request Body:** Advanced FilterQuery object (see TaskNotes FilterQuery documentation).
#### Get Filter Options
```
GET /api/filter-options
```
Returns available tags, projects, statuses, and priorities for building filter UIs.
### Statistics
#### Get Task Statistics
```
GET /api/stats
```
**Response:**
```json
{
"success": true,
"data": {
"total": 245,
"completed": 189,
"active": 45,
"overdue": 8,
"archived": 11,
"withTimeTracking": 67
}
}
```
### Pomodoro
Control pomodoro sessions programmatically through the API.
#### Start Pomodoro Session
```
POST /api/pomodoro/start
```
**Request Body (Optional):**
```json
{
"taskId": "path/to/task.md"
}
```
**Response:**
```json
{
"success": true,
"data": {
"session": {
"id": "pomo_123",
"type": "work",
"duration": 1500,
"startTime": "2025-08-13T10:00:00.000Z"
},
"task": {
"id": "path/to/task.md",
"title": "Work on API integration"
},
"message": "Pomodoro session started"
}
}
```
#### Stop Pomodoro Session
```
POST /api/pomodoro/stop
```
#### Pause Pomodoro Session
```
POST /api/pomodoro/pause
```
#### Resume Pomodoro Session
```
POST /api/pomodoro/resume
```
#### Get Pomodoro Status
```
GET /api/pomodoro/status
```
**Response:**
```json
{
"success": true,
"data": {
"isRunning": true,
"timeRemaining": 900,
"currentSession": {
"id": "pomo_123",
"type": "work",
"duration": 1500,
"startTime": "2025-08-13T10:00:00.000Z"
},
"totalPomodoros": 42,
"currentStreak": 3,
"totalMinutesToday": 180
}
}
```
#### Get Pomodoro Session History
```
GET /api/pomodoro/sessions
```
**Query Parameters:**
- `limit` - Maximum number of sessions to return
- `date` - Filter sessions by date (YYYY-MM-DD)
**Examples:**
```bash
# Get last 10 sessions
curl "http://localhost:8080/api/pomodoro/sessions?limit=10"
# Get sessions for specific date
curl "http://localhost:8080/api/pomodoro/sessions?date=2025-08-13"
```
#### Get Pomodoro Statistics
```
GET /api/pomodoro/stats
```
**Query Parameters:**
- `date` - Get stats for specific date (YYYY-MM-DD), defaults to today
**Response:**
```json
{
"success": true,
"data": {
"totalSessions": 15,
"completedSessions": 12,
"interruptedSessions": 3,
"totalFocusTime": 300,
"workSessions": 10,
"breakSessions": 5,
"longestStreak": 8,
"averageSessionLength": 24.5
}
}
```
## Integration Examples
### Browser Bookmarklet
```javascript
javascript:(function(){
const title = document.title;
const url = window.location.href;
fetch('http://localhost:8080/api/tasks', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
title: `Review: ${title}`,
tags: ['web'],
details: `Source: ${url}`
})
}).then(r => r.json()).then(d => {
alert(d.success ? 'Task created!' : 'Error: ' + d.error);
});
})();
```
### Python Script
```python
import requests
def create_task(title, **kwargs):
response = requests.post('http://localhost:8080/api/tasks',
json={'title': title, **kwargs})
return response.json()
# Create task from command line
task = create_task("Call dentist", priority="High", due="2025-08-15")
print(f"Created task: {task['data']['title']}")
```
### Automation (Zapier/IFTTT)
```bash
# Webhook URL for automation services
curl -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"{{trigger.subject}}", "tags":["email"], "details":"{{trigger.body}}"}'
```
### Pomodoro Timer Integration
```javascript
// Simple Pomodoro timer controller
class PomodoroController {
constructor(apiUrl = 'http://localhost:8080') {
this.apiUrl = apiUrl;
}
async startSession(taskId = null) {
const body = taskId ? { taskId } : {};
const response = await fetch(`${this.apiUrl}/api/pomodoro/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
return response.json();
}
async getStatus() {
const response = await fetch(`${this.apiUrl}/api/pomodoro/status`);
return response.json();
}
async pause() {
const response = await fetch(`${this.apiUrl}/api/pomodoro/pause`, {
method: 'POST'
});
return response.json();
}
async resume() {
const response = await fetch(`${this.apiUrl}/api/pomodoro/resume`, {
method: 'POST'
});
return response.json();
}
async stop() {
const response = await fetch(`${this.apiUrl}/api/pomodoro/stop`, {
method: 'POST'
});
return response.json();
}
}
// Usage
const pomodoro = new PomodoroController();
// Start a session for a specific task
await pomodoro.startSession('Projects/MyProject.md');
// Check current status
const status = await pomodoro.getStatus();
console.log(`Time remaining: ${Math.floor(status.data.timeRemaining / 60)} minutes`);
```
## Error Handling
### Common Errors
- `400 Bad Request` - Invalid request data
- `401 Unauthorized` - Invalid or missing auth token
- `404 Not Found` - Task not found
- `500 Internal Server Error` - Server error
### Rate Limiting
No rate limiting currently implemented. Use responsibly.
### CORS
CORS is enabled for all origins (`*`). API is intended for localhost use only.
## Security Notes
- **Localhost Only**: API server only accepts connections from localhost
- **Desktop Only**: API is not available on mobile platforms
- **Optional Auth**: Bearer token authentication is optional but recommended
- **No HTTPS**: Traffic is unencrypted (localhost only)
## Troubleshooting
### API Not Starting
1. Check that API is enabled in settings
2. Ensure port is not in use by another application
3. Try different port (1024-65535)
4. Check Obsidian console for errors
### Connection Refused
1. Verify API is enabled and Obsidian is running
2. Check correct port number
3. Ensure using `http://` not `https://`
4. Try `127.0.0.1` instead of `localhost`
### Authentication Errors
1. Verify token matches exactly (case-sensitive)
2. Include `Bearer ` prefix in Authorization header
3. Check for trailing spaces in token