forked from mirror/crumbs-original
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>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
66c91df983
commit
26cae27857
+397
-87
@@ -1,166 +1,476 @@
|
||||
# API Reference
|
||||
<!-- AUTO-GENERATED from docs/openapi.yaml — do not edit manually -->
|
||||
<!-- Run: pnpm docs:api -->
|
||||
|
||||
All API endpoints require authentication (session cookie) except `/api/auth/setup` and `/api/auth/login`.
|
||||
# Crumbs API
|
||||
|
||||
## Authentication
|
||||
REST API for Crumbs by Bretzel — a self-hostable, offline-first notes app.
|
||||
|
||||
### POST /api/auth/setup
|
||||
First-time setup. Creates the single user account.
|
||||
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": "min8characters" }
|
||||
{
|
||||
"password": "password"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
**Response:** `201`
|
||||
|
||||
```json
|
||||
{ "success": true }
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
Sets `session` cookie.
|
||||
|
||||
**Errors:** `400` Setup already completed or invalid password
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/auth/login`
|
||||
|
||||
Log in
|
||||
|
||||
> No authentication required.
|
||||
|
||||
### POST /api/auth/login
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "password": "yourpassword" }
|
||||
{
|
||||
"password": "password"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "success": true }
|
||||
```
|
||||
Sets `session` cookie.
|
||||
**Response:** `200`
|
||||
|
||||
### POST /api/auth/logout
|
||||
Clears session.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "success": true }
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:** `401` Invalid password
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/auth/logout`
|
||||
|
||||
Log out
|
||||
|
||||
**Response:** `200`
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
### GET /api/notes
|
||||
List notes by filter.
|
||||
### `GET /api/notes`
|
||||
|
||||
**Query Parameters:**
|
||||
- `filter` - `all` (default), `archived`, `trashed`
|
||||
List notes
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|------|----|------|----------|-------------|
|
||||
| `filter` | query | string | no | (all, archived, trashed) — default: `all` |
|
||||
|
||||
**Response:** `200`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "My Note",
|
||||
"content": "**Markdown** content",
|
||||
"color": "coral",
|
||||
"title": "title",
|
||||
"content": "content",
|
||||
"color": "default",
|
||||
"pinned": true,
|
||||
"archived": false,
|
||||
"trashed": false,
|
||||
"checklistMode": false,
|
||||
"sortOrder": 0,
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z",
|
||||
"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": ["work", "important"]
|
||||
"tags": [
|
||||
"item"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### POST /api/notes
|
||||
Create a new note.
|
||||
---
|
||||
|
||||
### `POST /api/notes`
|
||||
|
||||
Create a note
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "My Note",
|
||||
"content": "Note content with #tags",
|
||||
"title": "title",
|
||||
"content": "content",
|
||||
"color": "default",
|
||||
"pinned": false,
|
||||
"checklistMode": false
|
||||
"pinned": true,
|
||||
"archived": true,
|
||||
"trashed": true,
|
||||
"checklistMode": true,
|
||||
"sortOrder": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created` - Returns the created note.
|
||||
**Response:** `201`
|
||||
|
||||
### GET /api/notes/:id
|
||||
Get a single note.
|
||||
|
||||
### PATCH /api/notes/:id
|
||||
Update a note.
|
||||
|
||||
**Request:** (partial update - only include changed fields)
|
||||
```json
|
||||
{
|
||||
"title": "Updated Title",
|
||||
"color": "coral",
|
||||
"pinned": true
|
||||
"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"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK` - Returns the updated note.
|
||||
---
|
||||
|
||||
### DELETE /api/notes/:id
|
||||
Permanently delete a note.
|
||||
### `GET /api/notes/{id}`
|
||||
|
||||
## Search
|
||||
Get a note
|
||||
|
||||
### GET /api/search
|
||||
Full-text search across notes.
|
||||
**Parameters:**
|
||||
|
||||
**Query Parameters:**
|
||||
- `q` - Search query
|
||||
| Name | In | Type | Required | Description |
|
||||
|------|----|------|----------|-------------|
|
||||
| `id` | path | string | yes | |
|
||||
|
||||
**Response:** `200 OK` - Array of matching notes (excluding trashed).
|
||||
**Response:** `200`
|
||||
|
||||
## Tags
|
||||
|
||||
### GET /api/tags
|
||||
List all tags.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{ "id": 1, "name": "work" },
|
||||
{ "id": 2, "name": "personal" }
|
||||
]
|
||||
{
|
||||
"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 attachments for a note.
|
||||
### `GET /api/notes/{id}/attachments`
|
||||
|
||||
### POST /api/notes/:id/attachments
|
||||
Upload an image attachment.
|
||||
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 Created` - Returns attachment metadata.
|
||||
**Response:** `201`
|
||||
|
||||
### DELETE /api/notes/:id/attachments?attachmentId=xxx
|
||||
Delete an attachment.
|
||||
```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
|
||||
|
||||
### POST /api/sync
|
||||
Push local changes to server.
|
||||
### `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|update|delete",
|
||||
"timestamp": 1704067200000,
|
||||
"data": { "title": "...", "content": "..." }
|
||||
"operation": "create",
|
||||
"timestamp": 1,
|
||||
"data": {
|
||||
"title": "title",
|
||||
"content": "content",
|
||||
"color": "default",
|
||||
"pinned": true,
|
||||
"archived": true,
|
||||
"trashed": true,
|
||||
"checklistMode": true,
|
||||
"sortOrder": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/sync?since=timestamp
|
||||
Pull changes since a timestamp (milliseconds).
|
||||
**Response:** `200`
|
||||
|
||||
**Response:** `200 OK` - Array of notes updated since the given timestamp.
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Crumbs API
|
||||
description: REST API for Crumbs by Bretzel — a self-hostable, offline-first notes app.
|
||||
version: 0.1.0
|
||||
contact:
|
||||
name: Bretzel
|
||||
url: https://bretzel.app
|
||||
|
||||
servers:
|
||||
- url: http://localhost:3000
|
||||
description: Local development
|
||||
|
||||
security:
|
||||
- sessionCookie: []
|
||||
|
||||
paths:
|
||||
/api/auth/setup:
|
||||
post:
|
||||
summary: First-time password setup
|
||||
description: Creates the single user account. Only works once — returns 400 if already set up.
|
||||
tags: [Auth]
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [password]
|
||||
properties:
|
||||
password:
|
||||
type: string
|
||||
minLength: 8
|
||||
responses:
|
||||
'201':
|
||||
description: Account created, session cookie set
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
'400':
|
||||
description: Setup already completed or invalid password
|
||||
|
||||
/api/auth/login:
|
||||
post:
|
||||
summary: Log in
|
||||
tags: [Auth]
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [password]
|
||||
properties:
|
||||
password:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Logged in, session cookie set
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
'401':
|
||||
description: Invalid password
|
||||
|
||||
/api/auth/logout:
|
||||
post:
|
||||
summary: Log out
|
||||
tags: [Auth]
|
||||
responses:
|
||||
'200':
|
||||
description: Session cleared
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
|
||||
/api/notes:
|
||||
get:
|
||||
summary: List notes
|
||||
tags: [Notes]
|
||||
parameters:
|
||||
- name: filter
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [all, archived, trashed]
|
||||
default: all
|
||||
responses:
|
||||
'200':
|
||||
description: Array of notes
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
post:
|
||||
summary: Create a note
|
||||
tags: [Notes]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NoteInput'
|
||||
responses:
|
||||
'201':
|
||||
description: Created note
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Note'
|
||||
|
||||
/api/notes/{id}:
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
get:
|
||||
summary: Get a note
|
||||
tags: [Notes]
|
||||
responses:
|
||||
'200':
|
||||
description: Note with tags
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Note'
|
||||
'404':
|
||||
description: Note not found
|
||||
patch:
|
||||
summary: Update a note
|
||||
description: Partial update — only include changed fields.
|
||||
tags: [Notes]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NoteInput'
|
||||
responses:
|
||||
'200':
|
||||
description: Updated note
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Note'
|
||||
'404':
|
||||
description: Note not found
|
||||
delete:
|
||||
summary: Permanently delete a note
|
||||
tags: [Notes]
|
||||
responses:
|
||||
'200':
|
||||
description: Deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
'404':
|
||||
description: Note not found
|
||||
|
||||
/api/notes/{id}/attachments:
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
get:
|
||||
summary: List or download attachments
|
||||
description: Without `attachmentId`, lists all attachments. With `attachmentId`, returns the file.
|
||||
tags: [Attachments]
|
||||
parameters:
|
||||
- name: attachmentId
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Attachment list or file content
|
||||
post:
|
||||
summary: Upload an image attachment
|
||||
tags: [Attachments]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
required: [file]
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
description: Image file (max 10MB)
|
||||
responses:
|
||||
'201':
|
||||
description: Attachment metadata
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Attachment'
|
||||
'400':
|
||||
description: Invalid file
|
||||
delete:
|
||||
summary: Delete an attachment
|
||||
tags: [Attachments]
|
||||
parameters:
|
||||
- name: attachmentId
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
|
||||
/api/search:
|
||||
get:
|
||||
summary: Full-text search
|
||||
description: Searches across note titles, content, and tags. Excludes trashed notes.
|
||||
tags: [Search]
|
||||
parameters:
|
||||
- name: q
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Matching notes
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
|
||||
/api/tags:
|
||||
get:
|
||||
summary: List all tags
|
||||
tags: [Tags]
|
||||
responses:
|
||||
'200':
|
||||
description: Array of tags
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
|
||||
/api/sync:
|
||||
get:
|
||||
summary: Pull changes since timestamp
|
||||
tags: [Sync]
|
||||
parameters:
|
||||
- name: since
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: Unix timestamp in milliseconds
|
||||
responses:
|
||||
'200':
|
||||
description: Notes updated since the given timestamp
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Note'
|
||||
post:
|
||||
summary: Push local changes
|
||||
tags: [Sync]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [changes]
|
||||
properties:
|
||||
changes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/SyncChange'
|
||||
responses:
|
||||
'200':
|
||||
description: Changes applied
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Success'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
sessionCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: session
|
||||
|
||||
schemas:
|
||||
Success:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
|
||||
Note:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
title:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
color:
|
||||
type: string
|
||||
enum: [default, coral, peach, sand, mint, sage, fog, storm, dusk, blossom, clay, chalk]
|
||||
pinned:
|
||||
type: boolean
|
||||
archived:
|
||||
type: boolean
|
||||
trashed:
|
||||
type: boolean
|
||||
checklistMode:
|
||||
type: boolean
|
||||
sortOrder:
|
||||
type: integer
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
version:
|
||||
type: integer
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
NoteInput:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
color:
|
||||
type: string
|
||||
enum: [default, coral, peach, sand, mint, sage, fog, storm, dusk, blossom, clay, chalk]
|
||||
pinned:
|
||||
type: boolean
|
||||
archived:
|
||||
type: boolean
|
||||
trashed:
|
||||
type: boolean
|
||||
checklistMode:
|
||||
type: boolean
|
||||
sortOrder:
|
||||
type: integer
|
||||
|
||||
Tag:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
|
||||
Attachment:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
noteId:
|
||||
type: string
|
||||
filename:
|
||||
type: string
|
||||
mimeType:
|
||||
type: string
|
||||
size:
|
||||
type: integer
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
SyncChange:
|
||||
type: object
|
||||
required: [noteId, operation, timestamp]
|
||||
properties:
|
||||
noteId:
|
||||
type: string
|
||||
format: uuid
|
||||
operation:
|
||||
type: string
|
||||
enum: [create, update, delete]
|
||||
timestamp:
|
||||
type: integer
|
||||
description: Unix timestamp in milliseconds
|
||||
data:
|
||||
$ref: '#/components/schemas/NoteInput'
|
||||
Reference in New Issue
Block a user