Files
simplenote-web/api-endpoints.md
Hiro 007c51a98f fix(api): align frontend API client with backend endpoints
- Fix addDocumentTags to use POST /documents/:id/tags (was using PUT)
- Add getDocumentsByTag(tag) -> GET /tags/:tag
- Add getLibraryTree(id) -> GET /libraries/:id/tree
- Add getLibraryDocuments(id) -> GET /libraries/:id/documents
- Add getProjectDocuments(id) -> GET /projects/:id/documents
- Add getFolder(id) -> GET /folders/:id
- Add getFolderDocuments(id) -> GET /folders/:id/documents
- Add getFolderTree(id) -> GET /folders/:id/tree
- Add api-endpoints.md with full API documentation
- Remove duplicate/unused dead code blocks
2026-03-28 17:12:38 +00:00

6.7 KiB

SimpleNote Web - API Endpoints

Base URL: /api/v1 Auth: All endpoints require Authorization: Bearer <token> header unless noted.


Auth

POST /auth/token

Generate a new API token (admin only).

Request body:

{ "label": "my-token-label" }

Response 201:

{ "token": "snk_...", "label": "my-token-label", "createdAt": "2026-03-28T..." }

GET /auth/verify

Verify a token is valid.

Response 200:

{ "valid": true, "token": "snk_..." }

Projects

GET /projects

List all projects.

Response 200:

{ "projects": [...] }

POST /projects

Create a project.

Request body:

{ "name": "Project Name", "description": "optional" }

Response 201:

{ "id": "...", "name": "...", "description": "...", "createdAt": "...", "updatedAt": "..." }

GET /projects/:id

Get a single project.

Response 200:

{ "id": "...", "name": "...", "description": "...", "createdAt": "...", "updatedAt": "..." }

Response 404:

{ "error": "Project not found", "code": "NOT_FOUND" }

PUT /projects/:id

Update a project.

Request body:

{ "name": "New Name", "description": "New desc" }

Response 200:

{ "id": "...", "name": "...", "description": "...", "createdAt": "...", "updatedAt": "..." }

DELETE /projects/:id

Delete a project.

Response 200:

{ "deleted": true, "id": "..." }

GET /projects/:id/tree

Get full project tree (folder hierarchy + documents).

Response 200:

{
  "project": { "id": "...", "name": "..." },
  "documents": [...],
  "folders": [...],
  "totalDocuments": 5
}

GET /projects/:id/documents

List documents directly in a project (not in sub-folders).

Response 200:

{ "documents": [...], "total": 3 }

Folders

GET /folders?projectId=X&parentId=Y

List folders in a project. projectId is required.

Query params:

  • projectId (required): Project ID
  • parentId (optional): Parent folder ID. Omit for root folders.

Response 200:

{ "folders": [...] }

Response 400:

{ "error": "projectId query parameter is required", "code": "VALIDATION_ERROR" }

POST /folders

Create a folder.

Request body:

{ "name": "Folder Name", "projectId": "...", "parentId": "..." }

Response 201:

{ "id": "...", "name": "...", "projectId": "...", "parentId": null, "createdAt": "...", "updatedAt": "..." }

GET /folders/:id

Get a single folder.

Response 200:

{ "id": "...", "name": "...", "projectId": "...", "parentId": null, "createdAt": "...", "updatedAt": "..." }

PUT /folders/:id

Update a folder (rename).

Request body:

{ "name": "New Folder Name" }

Response 200:

{ "id": "...", "name": "New Folder Name", ... }

DELETE /folders/:id

Delete a folder.

Response 200:

{ "deleted": true, "id": "..." }

GET /folders/:id/documents

List documents directly in a folder.

Response 200:

{ "documents": [...], "total": 2 }

GET /folders/:id/tree

Get full folder tree (sub-folders + documents recursively).

Response 200:

{
  "folder": { "id": "...", "name": "..." },
  "documents": [...],
  "subFolders": [...],
  "totalDocuments": 4
}

Documents

GET /documents

List documents with optional filters.

Query params:

  • tag - Filter by tag
  • library - Filter by library ID
  • project - Filter by project ID
  • folder - Filter by folder ID
  • type - Filter by type (e.g., requirement, general)
  • status - Filter by status (e.g., draft, approved)
  • limit - Max results (default 50)
  • offset - Pagination offset (default 0)

Response 200:

{ "documents": [...], "total": 10, "limit": 50, "offset": 0 }

POST /documents

Create a document.

Request body:

{
  "title": "Doc Title",
  "libraryId": "...",
  "projectId": "...",
  "folderId": "...",
  "content": "# Markdown content",
  "tags": ["tag1", "tag2"],
  "type": "requirement",
  "priority": "high",
  "status": "draft"
}

Response 201:

{ "id": "...", "title": "...", "content": "...", "tags": [...], "type": "...", "priority": "...", "status": "...", "createdAt": "...", "updatedAt": "..." }

GET /documents/:id

Get a single document.

Response 200:

{ "id": "...", "title": "...", "content": "...", "tags": [...], "type": "...", "priority": "...", "status": "...", "createdAt": "...", "updatedAt": "..." }

PUT /documents/:id

Update a document.

Request body:

{ "title": "New Title", "content": "...", "tags": [...], "type": "...", "priority": "...", "status": "...", "folderId": "..." }

Response 200: Document object.


DELETE /documents/:id

Delete a document.

Response 200:

{ "deleted": true, "id": "..." }

GET /documents/:id/export

Export document as markdown.

Response 200: Raw text/markdown (Content-Type: text/markdown).


POST /documents/:id/tags

Add tags to a document.

Request body:

{ "tags": ["new-tag", "another"] }

Response 200: Updated document object.


Tags

GET /tags

List all tags with counts.

Response 200:

{ "tags": [{ "name": "backend", "count": 5 }, ...], "total": 12 }

GET /tags/:tag

Get all documents with a specific tag.

Response 200:

{ "tag": "backend", "documents": [...], "count": 5 }

Libraries

GET /libraries

List root libraries.

Response 200:

{ "libraries": [...] }

POST /libraries

Create a library.

Request body:

{ "name": "Library Name", "parentId": "..." }

Response 201:

{ "id": "...", "name": "...", "parentId": null, "createdAt": "...", "updatedAt": "..." }

GET /libraries/:id

Get library contents.

Response 200:

{ "id": "...", "name": "...", "parentId": null, ... }

GET /libraries/:id/tree

Get full library tree.

Response 200:

{
  "library": { ... },
  "documents": [...],
  "subLibraries": [...],
  "totalDocuments": 3
}

GET /libraries/:id/documents

List documents in a library.

Response 200:

{ "documents": [...], "total": 3 }

DELETE /libraries/:id

Delete a library.

Response 200:

{ "deleted": true, "id": "..." }

Error Format

All errors follow this structure:

{ "error": "Human-readable message", "code": "ERROR_CODE" }

Common codes: VALIDATION_ERROR, NOT_FOUND, UNAUTHORIZED, INTERNAL_ERROR