1028 lines
18 KiB
Markdown
1028 lines
18 KiB
Markdown
# API Documentation
|
|||
|
|
|
||
|
|
Project E exposes a REST API through Next.js API routes. All endpoints live under `/api/` and communicate via JSON.
|
||
|
|
|
||
|
|
## Table of Contents
|
||
|
|
|
||
|
|
- [Authentication](#authentication)
|
||
|
|
- [Request Format](#request-format)
|
||
|
|
- [Response Format](#response-format)
|
||
|
|
- [Error Handling](#error-handling)
|
||
|
|
- [Pagination](#pagination)
|
||
|
|
- [Filtering and Sorting](#filtering-and-sorting)
|
||
|
|
- [Endpoints](#endpoints)
|
||
|
|
- [Health](#health)
|
||
|
|
- [Auth](#auth)
|
||
|
|
- [Tasks](#tasks)
|
||
|
|
- [Habits](#habits)
|
||
|
|
- [Projects](#projects)
|
||
|
|
- [Notes](#notes)
|
||
|
|
- [Reports](#reports)
|
||
|
|
- [Milestones](#milestones)
|
||
|
|
- [Domains](#domains)
|
||
|
|
- [Tags](#tags)
|
||
|
|
- [Agents](#agents)
|
||
|
|
- [Webhooks](#webhooks)
|
||
|
|
- [Analytics](#analytics)
|
||
|
|
- [Realtime](#realtime)
|
||
|
|
- [MCP](#mcp)
|
||
|
|
|
||
|
|
## Authentication
|
||
|
|
|
||
|
|
All API endpoints (except `/api/health` and `/api/auth/login`) require authentication.
|
||
|
|
|
||
|
|
### Session-Based Auth
|
||
|
|
|
||
|
|
The web app uses cookie-based sessions. After login, the server sets an `httpOnly` cookie named `pb_auth` containing a PocketBase JWT token.
|
||
|
|
|
||
|
|
**Login:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
POST /api/auth/login
|
||
|
|
Content-Type: application/json
|
||
|
|
|
||
|
|
{
|
||
|
|
"email": "user@example.com",
|
||
|
|
"password": "your-password"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"user": {
|
||
|
|
"id": "user_id",
|
||
|
|
"email": "user@example.com",
|
||
|
|
"name": "User Name"
|
||
|
|
},
|
||
|
|
"token": "eyJhbGciOi..."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
The `Set-Cookie` header includes the `pb_auth` cookie. Include this cookie in subsequent requests.
|
||
|
|
|
||
|
|
### Token Refresh
|
||
|
|
|
||
|
|
Tokens expire after 7 days. Refresh before expiry:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
POST /api/auth/refresh
|
||
|
|
Cookie: pb_auth=eyJhbGciOi...
|
||
|
|
```
|
||
|
|
|
||
|
|
### Current User
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/auth/me
|
||
|
|
Cookie: pb_auth=eyJhbGciOi...
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"id": "user_id",
|
||
|
|
"email": "user@example.com",
|
||
|
|
"name": "User Name"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logout
|
||
|
|
|
||
|
|
```bash
|
||
|
|
POST /api/auth/logout
|
||
|
|
Cookie: pb_auth=eyJhbGciOi...
|
||
|
|
```
|
||
|
|
|
||
|
|
Clears the `pb_auth` cookie.
|
||
|
|
|
||
|
|
## Request Format
|
||
|
|
|
||
|
|
All write endpoints (`POST`, `PATCH`, `PUT`) expect JSON bodies with `Content-Type: application/json`.
|
||
|
|
|
||
|
|
Request bodies are validated with Zod schemas from `@project-e/shared`. Invalid input returns a `400 VALIDATION_ERROR`.
|
||
|
|
|
||
|
|
## Response Format
|
||
|
|
|
||
|
|
Successful responses return JSON with appropriate HTTP status codes:
|
||
|
|
|
||
|
|
| Status | Meaning |
|
||
|
|
|--------|---------|
|
||
|
|
| `200` | Success |
|
||
|
|
| `201` | Created |
|
||
|
|
| `204` | No Content (delete) |
|
||
|
|
| `400` | Bad Request (validation error) |
|
||
|
|
| `401` | Unauthorized |
|
||
|
|
| `404` | Not Found |
|
||
|
|
| `500` | Internal Server Error |
|
||
|
|
|
||
|
|
List endpoints return paginated results:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"items": [...],
|
||
|
|
"totalItems": 42,
|
||
|
|
"totalPages": 3,
|
||
|
|
"page": 1,
|
||
|
|
"perPage": 20
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Error Handling
|
||
|
|
|
||
|
|
Errors follow a consistent structure:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"error": {
|
||
|
|
"code": "VALIDATION_ERROR",
|
||
|
|
"message": "Invalid input",
|
||
|
|
"details": [
|
||
|
|
{
|
||
|
|
"code": "invalid_string",
|
||
|
|
"message": "Title is required",
|
||
|
|
"path": ["title"]
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Error codes:
|
||
|
|
|
||
|
|
| Code | Status | Description |
|
||
|
|
|------|--------|-------------|
|
||
|
|
| `UNAUTHORIZED` | 401 | Missing or invalid auth token |
|
||
|
|
| `VALIDATION_ERROR` | 400 | Request body failed Zod validation |
|
||
|
|
| `NOT_FOUND` | 404 | Resource does not exist |
|
||
|
|
| `FORBIDDEN` | 403 | Insufficient permissions |
|
||
|
|
| `INTERNAL_ERROR` | 500 | Unexpected server error |
|
||
|
|
|
||
|
|
## Pagination
|
||
|
|
|
||
|
|
List endpoints accept query parameters for pagination:
|
||
|
|
|
||
|
|
| Parameter | Type | Default | Description |
|
||
|
|
|-----------|------|---------|-------------|
|
||
|
|
| `page` | number | 1 | Page number (1-indexed) |
|
||
|
|
| `perPage` | number | 50 | Items per page (max 200) |
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/tasks?page=2&perPage=20
|
||
|
|
```
|
||
|
|
|
||
|
|
## Filtering and Sorting
|
||
|
|
|
||
|
|
### Filtering
|
||
|
|
|
||
|
|
Use the `filter` query parameter with PocketBase filter syntax:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/tasks?filter=status = "todo" && priority = "high"
|
||
|
|
```
|
||
|
|
|
||
|
|
Filter operators:
|
||
|
|
|
||
|
|
| Operator | Description |
|
||
|
|
|----------|-------------|
|
||
|
|
| `=` | Equal |
|
||
|
|
| `!=` | Not equal |
|
||
|
|
| `>`, `>=`, `<`, `<=` | Comparison |
|
||
|
|
| `~` | Contains (case-insensitive) |
|
||
|
|
| `!~` | Not contains |
|
||
|
|
| `^` | Starts with |
|
||
|
|
| `@` | Full-text search |
|
||
|
|
| `&&` | AND |
|
||
|
|
| `\|\|` | OR |
|
||
|
|
|
||
|
|
### Sorting
|
||
|
|
|
||
|
|
Use the `sort` query parameter. Prefix with `-` for descending order:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/tasks?sort=-created
|
||
|
|
GET /api/tasks?sort=priority,-due_date
|
||
|
|
```
|
||
|
|
|
||
|
|
## Endpoints
|
||
|
|
|
||
|
|
### Health
|
||
|
|
|
||
|
|
#### `GET /api/health`
|
||
|
|
|
||
|
|
Returns server health status. No authentication required.
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "ok",
|
||
|
|
"timestamp": "2024-01-15T10:30:00.000Z",
|
||
|
|
"version": "0.1.0"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Auth
|
||
|
|
|
||
|
|
#### `POST /api/auth/login`
|
||
|
|
|
||
|
|
Authenticate a user and create a session.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"email": "user@example.com",
|
||
|
|
"password": "your-password"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response (200):**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"user": {
|
||
|
|
"id": "user_id",
|
||
|
|
"email": "user@example.com",
|
||
|
|
"name": "User Name"
|
||
|
|
},
|
||
|
|
"token": "eyJhbGciOi..."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### `POST /api/auth/logout`
|
||
|
|
|
||
|
|
End the current session. Requires authentication.
|
||
|
|
|
||
|
|
#### `GET /api/auth/me`
|
||
|
|
|
||
|
|
Get the current authenticated user. Requires authentication.
|
||
|
|
|
||
|
|
#### `POST /api/auth/refresh`
|
||
|
|
|
||
|
|
Refresh the auth token. Requires authentication.
|
||
|
|
|
||
|
|
### Tasks
|
||
|
|
|
||
|
|
#### `GET /api/tasks`
|
||
|
|
|
||
|
|
List tasks with filtering, sorting, and pagination.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `page` | number | Page number |
|
||
|
|
| `perPage` | number | Items per page |
|
||
|
|
| `filter` | string | PocketBase filter expression |
|
||
|
|
| `sort` | string | Sort field(s) |
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/tasks?filter=status = "todo"&sort=-priority
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"items": [
|
||
|
|
{
|
||
|
|
"id": "task_id",
|
||
|
|
"title": "Complete documentation",
|
||
|
|
"description": "Write API docs",
|
||
|
|
"status": "todo",
|
||
|
|
"priority": "high",
|
||
|
|
"due_date": "2024-01-20T00:00:00.000Z",
|
||
|
|
"project_id": "project_id",
|
||
|
|
"tags": ["docs", "api"],
|
||
|
|
"domain": "work",
|
||
|
|
"subtasks": [],
|
||
|
|
"attachments": [],
|
||
|
|
"created": "2024-01-15T10:00:00.000Z",
|
||
|
|
"updated": "2024-01-15T10:00:00.000Z"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"totalItems": 1,
|
||
|
|
"totalPages": 1,
|
||
|
|
"page": 1,
|
||
|
|
"perPage": 50
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### `POST /api/tasks`
|
||
|
|
|
||
|
|
Create a new task.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "Complete documentation",
|
||
|
|
"description": "Write API docs",
|
||
|
|
"status": "todo",
|
||
|
|
"priority": "high",
|
||
|
|
"due_date": "2024-01-20T00:00:00.000Z",
|
||
|
|
"project_id": "project_id",
|
||
|
|
"tags": ["docs", "api"],
|
||
|
|
"domain": "work"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `title`, `domain`
|
||
|
|
|
||
|
|
**Response (201):** Returns the created task.
|
||
|
|
|
||
|
|
#### `GET /api/tasks/[id]`
|
||
|
|
|
||
|
|
Get a single task by ID.
|
||
|
|
|
||
|
|
**Response:** Returns the task object.
|
||
|
|
|
||
|
|
#### `PATCH /api/tasks/[id]`
|
||
|
|
|
||
|
|
Update a task. Send only the fields you want to change.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "in_progress",
|
||
|
|
"priority": "urgent"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Response:** Returns the updated task.
|
||
|
|
|
||
|
|
#### `DELETE /api/tasks/[id]`
|
||
|
|
|
||
|
|
Delete a task. Returns `204 No Content`.
|
||
|
|
|
||
|
|
#### `POST /api/tasks/bulk`
|
||
|
|
|
||
|
|
Bulk operations on tasks.
|
||
|
|
|
||
|
|
**Request (bulk update):**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"action": "update",
|
||
|
|
"task_ids": ["id1", "id2", "id3"],
|
||
|
|
"data": {
|
||
|
|
"status": "done"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Request (bulk delete):**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"action": "delete",
|
||
|
|
"task_ids": ["id1", "id2", "id3"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Habits
|
||
|
|
|
||
|
|
#### `GET /api/habits`
|
||
|
|
|
||
|
|
List habits with filtering and pagination.
|
||
|
|
|
||
|
|
**Query Parameters:** Same as tasks.
|
||
|
|
|
||
|
|
**Response:** Paginated list of habit objects.
|
||
|
|
|
||
|
|
#### `POST /api/habits`
|
||
|
|
|
||
|
|
Create a new habit.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "Morning meditation",
|
||
|
|
"description": "10 minutes of mindfulness",
|
||
|
|
"frequency": "daily",
|
||
|
|
"domain": "health",
|
||
|
|
"difficulty": "medium",
|
||
|
|
"target_count": 1,
|
||
|
|
"tags": ["wellness"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `title`, `domain`
|
||
|
|
|
||
|
|
**Response (201):** Returns the created habit.
|
||
|
|
|
||
|
|
#### `GET /api/habits/[id]`
|
||
|
|
|
||
|
|
Get a single habit by ID.
|
||
|
|
|
||
|
|
#### `PATCH /api/habits/[id]`
|
||
|
|
|
||
|
|
Update a habit.
|
||
|
|
|
||
|
|
#### `DELETE /api/habits/[id]`
|
||
|
|
|
||
|
|
Delete a habit.
|
||
|
|
|
||
|
|
#### `GET /api/habit-logs`
|
||
|
|
|
||
|
|
List habit completion logs.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `habit_id` | string | Filter by habit |
|
||
|
|
| `date` | string | Filter by date |
|
||
|
|
|
||
|
|
#### `POST /api/habit-logs`
|
||
|
|
|
||
|
|
Log a habit completion.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"habit_id": "habit_id",
|
||
|
|
"date": "2024-01-15",
|
||
|
|
"mood": "good",
|
||
|
|
"quantity": 1,
|
||
|
|
"notes": "Felt great"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Projects
|
||
|
|
|
||
|
|
#### `GET /api/projects`
|
||
|
|
|
||
|
|
List projects.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `status` | string | Filter by status (`active`, `paused`, `archived`) |
|
||
|
|
| `domain` | string | Filter by domain |
|
||
|
|
|
||
|
|
#### `POST /api/projects`
|
||
|
|
|
||
|
|
Create a new project.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "Website Redesign",
|
||
|
|
"description": "Complete overhaul of the company website",
|
||
|
|
"domain": "work",
|
||
|
|
"status": "active",
|
||
|
|
"color": "#3b82f6",
|
||
|
|
"tags": ["design", "frontend"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `name`, `domain`
|
||
|
|
|
||
|
|
#### `GET /api/projects/[id]`
|
||
|
|
|
||
|
|
Get a single project.
|
||
|
|
|
||
|
|
#### `PATCH /api/projects/[id]`
|
||
|
|
|
||
|
|
Update a project.
|
||
|
|
|
||
|
|
#### `DELETE /api/projects/[id]`
|
||
|
|
|
||
|
|
Delete a project.
|
||
|
|
|
||
|
|
### Notes
|
||
|
|
|
||
|
|
#### `GET /api/notes`
|
||
|
|
|
||
|
|
List notes.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `domain` | string | Filter by domain |
|
||
|
|
| `is_pinned` | boolean | Filter by pinned status |
|
||
|
|
| `is_archived` | boolean | Filter by archived status |
|
||
|
|
|
||
|
|
#### `POST /api/notes`
|
||
|
|
|
||
|
|
Create a new note.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "Meeting Notes",
|
||
|
|
"content": "# Meeting with design team\n\nDiscussed new layout...",
|
||
|
|
"domain": "work",
|
||
|
|
"tags": ["meetings"],
|
||
|
|
"is_pinned": false
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `title`, `domain`
|
||
|
|
|
||
|
|
#### `GET /api/notes/[id]`
|
||
|
|
|
||
|
|
Get a single note.
|
||
|
|
|
||
|
|
#### `PATCH /api/notes/[id]`
|
||
|
|
|
||
|
|
Update a note.
|
||
|
|
|
||
|
|
#### `DELETE /api/notes/[id]`
|
||
|
|
|
||
|
|
Delete a note.
|
||
|
|
|
||
|
|
### Reports
|
||
|
|
|
||
|
|
#### `GET /api/reports`
|
||
|
|
|
||
|
|
List reports.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `type` | string | Filter by type (`weekly`, `monthly`, `project`, `habit`, `custom`) |
|
||
|
|
| `domain` | string | Filter by domain |
|
||
|
|
|
||
|
|
#### `POST /api/reports`
|
||
|
|
|
||
|
|
Create a new report.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "Weekly Summary",
|
||
|
|
"report_type": "weekly",
|
||
|
|
"domain": "work",
|
||
|
|
"date_range_start": "2024-01-08T00:00:00.000Z",
|
||
|
|
"date_range_end": "2024-01-14T23:59:59.999Z",
|
||
|
|
"content": "# Week of Jan 8-14\n\nCompleted 15 tasks..."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `title`, `report_type`, `domain`
|
||
|
|
|
||
|
|
#### `GET /api/reports/[id]`
|
||
|
|
|
||
|
|
Get a single report.
|
||
|
|
|
||
|
|
#### `PATCH /api/reports/[id]`
|
||
|
|
|
||
|
|
Update a report.
|
||
|
|
|
||
|
|
#### `DELETE /api/reports/[id]`
|
||
|
|
|
||
|
|
Delete a report.
|
||
|
|
|
||
|
|
### Milestones
|
||
|
|
|
||
|
|
#### `GET /api/milestones`
|
||
|
|
|
||
|
|
List milestones.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `project_id` | string | Filter by project |
|
||
|
|
| `status` | string | Filter by status (`planned`, `in_progress`, `complete`) |
|
||
|
|
|
||
|
|
#### `POST /api/milestones`
|
||
|
|
|
||
|
|
Create a new milestone.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "Design Phase",
|
||
|
|
"description": "Complete all design mockups",
|
||
|
|
"project_id": "project_id",
|
||
|
|
"status": "in_progress",
|
||
|
|
"due_date": "2024-02-01T00:00:00.000Z",
|
||
|
|
"sort_order": 1
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `title`, `project_id`
|
||
|
|
|
||
|
|
#### `GET /api/milestones/[id]`
|
||
|
|
|
||
|
|
Get a single milestone.
|
||
|
|
|
||
|
|
#### `PATCH /api/milestones/[id]`
|
||
|
|
|
||
|
|
Update a milestone.
|
||
|
|
|
||
|
|
#### `DELETE /api/milestones/[id]`
|
||
|
|
|
||
|
|
Delete a milestone.
|
||
|
|
|
||
|
|
### Domains
|
||
|
|
|
||
|
|
#### `GET /api/domains`
|
||
|
|
|
||
|
|
List all domains.
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"items": [
|
||
|
|
{
|
||
|
|
"id": "domain_id",
|
||
|
|
"name": "Work",
|
||
|
|
"color": "#3b82f6",
|
||
|
|
"icon": "briefcase",
|
||
|
|
"sort_order": 1
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"totalItems": 3,
|
||
|
|
"page": 1,
|
||
|
|
"perPage": 50
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### `POST /api/domains`
|
||
|
|
|
||
|
|
Create a new domain.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "Work",
|
||
|
|
"color": "#3b82f6",
|
||
|
|
"icon": "briefcase",
|
||
|
|
"sort_order": 1
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `name`
|
||
|
|
|
||
|
|
#### `GET /api/domains/[id]`
|
||
|
|
|
||
|
|
Get a single domain.
|
||
|
|
|
||
|
|
#### `PATCH /api/domains/[id]`
|
||
|
|
|
||
|
|
Update a domain.
|
||
|
|
|
||
|
|
#### `DELETE /api/domains/[id]`
|
||
|
|
|
||
|
|
Delete a domain.
|
||
|
|
|
||
|
|
### Tags
|
||
|
|
|
||
|
|
#### `GET /api/tags`
|
||
|
|
|
||
|
|
List all tags.
|
||
|
|
|
||
|
|
#### `POST /api/tags`
|
||
|
|
|
||
|
|
Create a new tag.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "urgent",
|
||
|
|
"color": "#ef4444"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `name`
|
||
|
|
|
||
|
|
#### `GET /api/tags/[id]`
|
||
|
|
|
||
|
|
Get a single tag.
|
||
|
|
|
||
|
|
#### `PATCH /api/tags/[id]`
|
||
|
|
|
||
|
|
Update a tag.
|
||
|
|
|
||
|
|
#### `DELETE /api/tags/[id]`
|
||
|
|
|
||
|
|
Delete a tag.
|
||
|
|
|
||
|
|
### Agents
|
||
|
|
|
||
|
|
#### `GET /api/agents`
|
||
|
|
|
||
|
|
List agents.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `status` | string | Filter by status (`active`, `disabled`) |
|
||
|
|
|
||
|
|
#### `POST /api/agents`
|
||
|
|
|
||
|
|
Create a new agent.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "Code Assistant",
|
||
|
|
"description": "Helps with code reviews and suggestions",
|
||
|
|
"permission_tier": "read_only",
|
||
|
|
"webhook_url": "https://example.com/webhook",
|
||
|
|
"status": "active"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `name`
|
||
|
|
|
||
|
|
The server generates an `api_key` automatically.
|
||
|
|
|
||
|
|
#### `GET /api/agents/[id]`
|
||
|
|
|
||
|
|
Get a single agent.
|
||
|
|
|
||
|
|
#### `PATCH /api/agents/[id]`
|
||
|
|
|
||
|
|
Update an agent.
|
||
|
|
|
||
|
|
#### `DELETE /api/agents/[id]`
|
||
|
|
|
||
|
|
Delete an agent.
|
||
|
|
|
||
|
|
#### `GET /api/agent-activity`
|
||
|
|
|
||
|
|
List recent agent activity.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `agent_id` | string | Filter by agent |
|
||
|
|
| `limit` | number | Max results |
|
||
|
|
|
||
|
|
#### `POST /api/agent-webhook`
|
||
|
|
|
||
|
|
Webhook endpoint for agent callbacks. Agents POST results here.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"task_id": "agent_task_id",
|
||
|
|
"status": "completed",
|
||
|
|
"result": {
|
||
|
|
"summary": "Task completed successfully"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Webhooks
|
||
|
|
|
||
|
|
#### `GET /api/webhooks`
|
||
|
|
|
||
|
|
List webhooks.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `active` | boolean | Filter by active status |
|
||
|
|
|
||
|
|
#### `POST /api/webhooks`
|
||
|
|
|
||
|
|
Create a new webhook.
|
||
|
|
|
||
|
|
**Request:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "Task Notifications",
|
||
|
|
"url": "https://example.com/webhook",
|
||
|
|
"events": ["task.created", "task.updated", "task.completed"],
|
||
|
|
"secret": "your-webhook-secret",
|
||
|
|
"active": true
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Required fields:** `name`, `url`, `events`
|
||
|
|
|
||
|
|
#### `GET /api/webhooks/[id]`
|
||
|
|
|
||
|
|
Get a single webhook.
|
||
|
|
|
||
|
|
#### `PATCH /api/webhooks/[id]`
|
||
|
|
|
||
|
|
Update a webhook.
|
||
|
|
|
||
|
|
#### `DELETE /api/webhooks/[id]`
|
||
|
|
|
||
|
|
Delete a webhook.
|
||
|
|
|
||
|
|
#### `GET /api/webhook-deliveries`
|
||
|
|
|
||
|
|
List webhook delivery attempts.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `webhook_id` | string | Filter by webhook |
|
||
|
|
| `success` | boolean | Filter by success status |
|
||
|
|
|
||
|
|
### Analytics
|
||
|
|
|
||
|
|
#### `GET /api/analytics`
|
||
|
|
|
||
|
|
Get analytics data.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `period_days` | number | Number of days to analyze (default: 30) |
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"taskCompletionRate": 75,
|
||
|
|
"habitConsistency": 82,
|
||
|
|
"totalTimeMinutes": 1240,
|
||
|
|
"activeStreaks": 5,
|
||
|
|
"bestStreak": 21,
|
||
|
|
"period": 30
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### `GET /api/time-summary`
|
||
|
|
|
||
|
|
Get aggregated time tracking summary.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `start_date` | string | Start date (ISO 8601) |
|
||
|
|
| `end_date` | string | End date (ISO 8601) |
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"totalMinutes": 1240,
|
||
|
|
"byDomain": {
|
||
|
|
"work": 800,
|
||
|
|
"personal": 440
|
||
|
|
},
|
||
|
|
"byProject": {
|
||
|
|
"project_id_1": 600,
|
||
|
|
"project_id_2": 640
|
||
|
|
},
|
||
|
|
"byTag": {
|
||
|
|
"frontend": 300,
|
||
|
|
"backend": 500
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Realtime
|
||
|
|
|
||
|
|
#### `GET /api/realtime`
|
||
|
|
|
||
|
|
Server-sent events endpoint for realtime data updates. Requires authentication.
|
||
|
|
|
||
|
|
**Query Parameters:**
|
||
|
|
|
||
|
|
| Parameter | Type | Description |
|
||
|
|
|-----------|------|-------------|
|
||
|
|
| `collections` | string | Comma-separated list of collections to subscribe to |
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
GET /api/realtime?collections=tasks,habits
|
||
|
|
```
|
||
|
|
|
||
|
|
If no collections specified, subscribes to: `tasks`, `habits`, `projects`, `notes`, `reports`, `milestones`, `notifications`.
|
||
|
|
|
||
|
|
**Event format:**
|
||
|
|
|
||
|
|
```
|
||
|
|
data: {"type":"connected","collections":["tasks","habits"]}
|
||
|
|
|
||
|
|
data: {"type":"create","collection":"tasks","record":{"id":"...","title":"..."}}
|
||
|
|
|
||
|
|
data: {"type":"update","collection":"tasks","record":{"id":"...","status":"done"}}
|
||
|
|
|
||
|
|
data: {"type":"delete","collection":"tasks","record":{"id":"..."}}
|
||
|
|
|
||
|
|
:ping
|
||
|
|
```
|
||
|
|
|
||
|
|
The server sends a `:ping` comment every 30 seconds to keep the connection alive.
|
||
|
|
|
||
|
|
### MCP
|
||
|
|
|
||
|
|
#### `GET /api/mcp`
|
||
|
|
|
||
|
|
MCP server endpoint using Streamable HTTP transport. Requires API key authentication.
|
||
|
|
|
||
|
|
**Authentication:**
|
||
|
|
|
||
|
|
```bash
|
||
|
|
Authorization: Bearer your_agent_api_key
|
||
|
|
```
|
||
|
|
|
||
|
|
The server validates the API key against the `agents` collection.
|
||
|
|
|
||
|
|
**Session management:**
|
||
|
|
|
||
|
|
1. Client sends `GET /api/mcp` to establish a session
|
||
|
|
2. Server responds with `mcp-session-id` header
|
||
|
|
3. Client includes `mcp-session-id` in subsequent `POST` and `DELETE` requests
|
||
|
|
4. Client sends `DELETE /api/mcp` to end the session
|
||
|
|
|
||
|
|
See [MCP Documentation](MCP.md) for the full list of 61 available tools.
|
||
|
|
|
||
|
|
## Rate Limiting
|
||
|
|
|
||
|
|
The API does not enforce rate limiting at the application level. Configure rate limiting at the reverse proxy or infrastructure layer.
|
||
|
|
|
||
|
|
Recommended limits:
|
||
|
|
- Auth endpoints: 10 requests per minute per IP
|
||
|
|
- Write endpoints: 100 requests per minute per user
|
||
|
|
- Read endpoints: 500 requests per minute per user
|
||
|
|
|
||
|
|
## SDK Usage
|
||
|
|
|
||
|
|
### JavaScript/TypeScript
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const API_URL = 'http://localhost:3000/api';
|
||
|
|
|
||
|
|
// Login
|
||
|
|
const loginResponse = await fetch(`${API_URL}/auth/login`, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ email: 'user@example.com', password: 'password' }),
|
||
|
|
});
|
||
|
|
const { token } = await loginResponse.json();
|
||
|
|
|
||
|
|
// List tasks
|
||
|
|
const tasksResponse = await fetch(`${API_URL}/tasks?filter=status = "todo"`, {
|
||
|
|
headers: { Cookie: `pb_auth=${token}` },
|
||
|
|
});
|
||
|
|
const { items: tasks } = await tasksResponse.json();
|
||
|
|
|
||
|
|
// Create a task
|
||
|
|
const createResponse = await fetch(`${API_URL}/tasks`, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
Cookie: `pb_auth=${token}`,
|
||
|
|
},
|
||
|
|
body: JSON.stringify({
|
||
|
|
title: 'New task',
|
||
|
|
domain: 'work',
|
||
|
|
priority: 'high',
|
||
|
|
}),
|
||
|
|
});
|
||
|
|
const task = await createResponse.json();
|
||
|
|
```
|
||
|
|
|
||
|
|
### cURL
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Login
|
||
|
|
curl -X POST http://localhost:3000/api/auth/login \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d '{"email":"user@example.com","password":"password"}' \
|
||
|
|
-c cookies.txt
|
||
|
|
|
||
|
|
# List tasks
|
||
|
|
curl http://localhost:3000/api/tasks \
|
||
|
|
-b cookies.txt
|
||
|
|
|
||
|
|
# Create a task
|
||
|
|
curl -X POST http://localhost:3000/api/tasks \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-b cookies.txt \
|
||
|
|
-d '{"title":"New task","domain":"work","priority":"high"}'
|
||
|
|
```
|