Summary
Four Documents routes the client does not build, plus two authoring affordances the web has and macOS lacks.
Routes
| Route |
Auth |
What it unlocks |
GET /api/documents/tree |
sync-token |
The whole sidebar in one call — today macOS assembles it from several |
GET /api/users/{username}/documents |
public |
Public documents by user — the profile page has no documents tab |
POST /api/documents/folders/{id}/documents |
sync-token, subscriber |
Create a document directly in a folder |
GET /api/documents/invite/{token} |
public |
Invite landing (the accept half is session-only — see the caveat) |
Live shapes (2026-09-07, Bearer)
GET /api/documents/tree:
{"folders":[{"id":"2b776197-…","name":"One-Folder","parentId":null,
"documents":[{"id":"effbcb05-…","title":"a-single-doc",
"relativePath":"a-single-doc.md","isPublic":false}]},
{"id":"b6a8f347-…","name":"_templates","parentId":null,
"documents":[{"id":"c283ee0b-…","title":"Bespoke_Template!!!","…":"…"},
{"id":"c20f9ba6-…","title":"Recipe","…":"…"}]},
{"id":"3775f95a-…","name":"emptiness","parentId":null,"documents":[]}],
"rootDocuments":[{"id":"60668d66-…","title":"a-root-doc","…":"…"}]}
Note it returns the _templates folder inline — the same folder the template picker uses.
GET /api/users/adron/documents:
{"documents":[{"id":"026028c0-…","title":"Railroad Apps to Build for Fun",
"folderId":null,"relativePath":"railroad-passenger-seating.md",
"createdAt":"…","updatedAt":"…"}],
"folders":[]}
⚠️ Backend constraint on the invite pair
POST /api/documents/invite/{token} and POST /api/documents/shared/{token} are both x-auth-type: session in the live spec — a Bearer-only client cannot claim. Deliver the landing view and hand the accept step to the browser; the backend ask is filed separately. Accepting is documented as always free, so no entitlement gate on the landing view.
Two authoring gaps
Move a document between folders. /help/documents: "Open the document, use the Move to folder option (or the document settings menu), and choose a destination; select No folder (root) to remove it from all folders." macOS has folder create / rename / delete (FolderTreeViewModel.swift:114/136/169) but no move-document action.
Template seed defaults. /help/documents: "Templates are stored in a special folder named _templates, created automatically the first time you open the template picker. A Seed defaults action fills it with a starter set (Recipe, Meeting Notes, Release Notes, and more)." macOS ships DocumentTemplatePickerView + ServerTemplatesViewModel — verify whether the seed-defaults action is present before building it; if it is, this bullet closes as already-done.
Deliberately deferred
POST / DELETE /api/documents/{id}/presence — the live-cursor heartbeat. It is a collaborative-editing feature with a continuous polling cost, and multi-user simultaneous editing is not currently a goal. Not in scope for this issue. (This was G13; it is no longer backend-blocked, just low-value.)
Division of labor
Kit
Domain
App
Tests
Acceptance criteria
- The sidebar is built from one call.
- A document can be moved between folders and to root from the Mac.
- Full E2E gate green.
Notes
work-consolidation.md tracks this as G24. Size M.
Summary
Four Documents routes the client does not build, plus two authoring affordances the web has and macOS lacks.
Routes
GET /api/documents/treeGET /api/users/{username}/documentsPOST /api/documents/folders/{id}/documentsGET /api/documents/invite/{token}Live shapes (2026-09-07, Bearer)
GET /api/documents/tree:{"folders":[{"id":"2b776197-…","name":"One-Folder","parentId":null, "documents":[{"id":"effbcb05-…","title":"a-single-doc", "relativePath":"a-single-doc.md","isPublic":false}]}, {"id":"b6a8f347-…","name":"_templates","parentId":null, "documents":[{"id":"c283ee0b-…","title":"Bespoke_Template!!!","…":"…"}, {"id":"c20f9ba6-…","title":"Recipe","…":"…"}]}, {"id":"3775f95a-…","name":"emptiness","parentId":null,"documents":[]}], "rootDocuments":[{"id":"60668d66-…","title":"a-root-doc","…":"…"}]}Note it returns the
_templatesfolder inline — the same folder the template picker uses.GET /api/users/adron/documents:{"documents":[{"id":"026028c0-…","title":"Railroad Apps to Build for Fun", "folderId":null,"relativePath":"railroad-passenger-seating.md", "createdAt":"…","updatedAt":"…"}], "folders":[]}POST /api/documents/invite/{token}andPOST /api/documents/shared/{token}are bothx-auth-type: sessionin the live spec — a Bearer-only client cannot claim. Deliver the landing view and hand the accept step to the browser; the backend ask is filed separately. Accepting is documented as always free, so no entitlement gate on the landing view.Two authoring gaps
Move a document between folders.
/help/documents: "Open the document, use the Move to folder option (or the document settings menu), and choose a destination; select No folder (root) to remove it from all folders." macOS has folder create / rename / delete (FolderTreeViewModel.swift:114/136/169) but no move-document action.Template seed defaults.
/help/documents: "Templates are stored in a special folder named_templates, created automatically the first time you open the template picker. A Seed defaults action fills it with a starter set (Recipe, Meeting Notes, Release Notes, and more)." macOS shipsDocumentTemplatePickerView+ServerTemplatesViewModel— verify whether the seed-defaults action is present before building it; if it is, this bullet closes as already-done.Deliberately deferred
POST/DELETE /api/documents/{id}/presence— the live-cursor heartbeat. It is a collaborative-editing feature with a continuous polling cost, and multi-user simultaneous editing is not currently a goal. Not in scope for this issue. (This wasG13; it is no longer backend-blocked, just low-value.)Division of labor
Kit
Documents.tree(),Documents.publicDocuments(username:),Documents.createInFolder(folderID:…),Documents.invite(token:)+ DTOsdocuments; root documents are a sibling array — do not flatten)Domain
DocumentsServiceas the sidebar's single source, keeping the existing SWR cache semantics — the tree replaces several calls, so the cache key and TTL need revisiting, not just the fetch.App
DocumentsSidebarViewpaints from the single tree call.Tests
_templatesfolder is not offered as a normal destinationAcceptance criteria
Notes
work-consolidation.mdtracks this as G24. Size M.