Files
crumbs/docs/API.md
T
Frederic CabassutandClaude Opus 4.6 b55b6de571 docs: deduplicate README, add OpenAPI spec with auto-generated API docs
- Slim README to essentials, link to docs/ for details
- Add docs/openapi.yaml as single source of truth for the API
- Add scripts/generate-api-docs.ts to produce docs/API.md from the spec
- Add pnpm docs:api / make docs-api target

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:24:29 +01:00

477 lines
6.8 KiB
Markdown

<!-- AUTO-GENERATED from docs/openapi.yaml — do not edit manually -->
<!-- Run: pnpm docs:api -->
# Crumbs API
REST API for Crumbs by Bretzel — a self-hostable, offline-first notes app.
Base URL: `http://localhost:3000`
All endpoints require a `session` cookie (set by login) except where noted.
## Auth
### `POST /api/auth/setup`
First-time password setup
Creates the single user account. Only works once — returns 400 if already set up.
> No authentication required.
**Request:**
```json
{
"password": "password"
}
```
**Response:** `201`
```json
{
"success": true
}
```
**Errors:** `400` Setup already completed or invalid password
---
### `POST /api/auth/login`
Log in
> No authentication required.
**Request:**
```json
{
"password": "password"
}
```
**Response:** `200`
```json
{
"success": true
}
```
**Errors:** `401` Invalid password
---
### `POST /api/auth/logout`
Log out
**Response:** `200`
```json
{
"success": true
}
```
---
## Notes
### `GET /api/notes`
List notes
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `filter` | query | string | no | (all, archived, trashed) — default: `all` |
**Response:** `200`
```json
[
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
]
```
---
### `POST /api/notes`
Create a note
**Request:**
```json
{
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1
}
```
**Response:** `201`
```json
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
```
---
### `GET /api/notes/{id}`
Get a note
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
**Response:** `200`
```json
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
```
**Errors:** `404` Note not found
---
### `PATCH /api/notes/{id}`
Update a note
Partial update — only include changed fields.
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
**Request:**
```json
{
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1
}
```
**Response:** `200`
```json
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
```
**Errors:** `404` Note not found
---
### `DELETE /api/notes/{id}`
Permanently delete a note
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
**Response:** `200`
```json
{
"success": true
}
```
**Errors:** `404` Note not found
---
## Attachments
### `GET /api/notes/{id}/attachments`
List or download attachments
Without `attachmentId`, lists all attachments. With `attachmentId`, returns the file.
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
| `attachmentId` | query | string | no | |
**Response:** `200`
---
### `POST /api/notes/{id}/attachments`
Upload an image attachment
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
**Request:** `multipart/form-data` with `file` field.
**Response:** `201`
```json
{
"id": "id",
"noteId": "noteId",
"filename": "filename",
"mimeType": "mimeType",
"size": 1,
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Errors:** `400` Invalid file
---
### `DELETE /api/notes/{id}/attachments`
Delete an attachment
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | string | yes | |
| `attachmentId` | query | string | yes | |
**Response:** `200`
```json
{
"success": true
}
```
---
## Search
### `GET /api/search`
Full-text search
Searches across note titles, content, and tags. Excludes trashed notes.
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `q` | query | string | yes | |
**Response:** `200`
```json
[
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
]
```
---
## Tags
### `GET /api/tags`
List all tags
**Response:** `200`
```json
[
{
"id": 1,
"name": "name"
}
]
```
---
## Sync
### `GET /api/sync`
Pull changes since timestamp
**Parameters:**
| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `since` | query | integer | yes | Unix timestamp in milliseconds |
**Response:** `200`
```json
[
{
"id": "uuid",
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T00:00:00.000Z",
"version": 1,
"tags": [
"item"
]
}
]
```
---
### `POST /api/sync`
Push local changes
**Request:**
```json
{
"changes": [
{
"noteId": "uuid",
"operation": "create",
"timestamp": 1,
"data": {
"title": "title",
"content": "content",
"color": "default",
"pinned": true,
"archived": true,
"trashed": true,
"checklistMode": true,
"sortOrder": 1
}
}
]
}
```
**Response:** `200`
```json
{
"success": true
}
```
---