{"openapi":"3.1.0","info":{"title":"InterlinedList API","version":"0.1.0","description":"HTTP API for InterlinedList. Generated deterministically from the route tree under app/api/ and enriched from docs/api-reference.md by scripts/generate-openapi.js (`npm run docs:openapi`). Served at /api/openapi.json and rendered at /api-docs.\n\nMost endpoints accept either a session cookie (`interlinedlist-session`) or a Bearer sync token from POST /api/auth/sync-token. A subset (auth account management, exports, identities, organizations, LinkedIn, message dig, architecture aggregates) requires the session cookie."},"servers":[{"url":"https://interlinedlist.com","description":"Production"},{"url":"http://localhost:3000","description":"Local development"}],"tags":[{"name":"Authentication","description":"Login, registration, sync tokens, password reset, account switching, OAuth provider flows."},{"name":"Messages","description":"Posting, replies, dig reactions, scheduled posts, media uploads, cross-posting."},{"name":"Lists","description":"List CRUD, schema/DSL, data rows, watchers, connections, search."},{"name":"List Folders","description":"Folder hierarchy for organising lists."},{"name":"Documents","description":"Document CRUD, delta sync, templates, search, image uploads."},{"name":"Document Folders","description":"Folder hierarchy for organising documents."},{"name":"Users & Profile","description":"Current user, profile updates, avatars, linked identities, public profiles."},{"name":"Following","description":"Follow/unfollow, follow requests, follower & following lists."},{"name":"Organizations","description":"Org CRUD, members, LinkedIn page integration. Session cookie required."},{"name":"Notifications","description":"Notification tray, mark read, single & bulk operations."},{"name":"Push Notifications","description":"Register and unregister APNS device tokens."},{"name":"Exports","description":"CSV exports of messages, lists, list rows, and follows. Session cookie required."},{"name":"GitHub","description":"Connected-account GitHub issue and repo helpers."},{"name":"LinkedIn","description":"Personal LinkedIn posting targets and OAuth. Session cookie required."},{"name":"Utility","description":"Geolocation, weather, image proxy, analytics, OAuth metadata, status probes."},{"name":"Billing","description":"Stripe checkout and customer portal sessions."},{"name":"Admin","description":"Admin-only user and email-log management."},{"name":"Webhooks & Cron","description":"Internal endpoints: signature-verified webhooks and CRON_SECRET jobs. Not for general client use."},{"name":"Openapi.json"}],"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"paths":{"/api/admin/email-logs":{"get":{"tags":["Admin"],"summary":"Query params:","operationId":"getAdminEmailLogs","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/admin/users":{"get":{"tags":["Admin"],"summary":"Get all users (admin only)","operationId":"getAdminUsers","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{"type":"string"},"bio":{"type":"string"},"emailVerified":{"type":"boolean"},"cleared":{"type":"boolean"},"customerStatus":{"type":"string"},"createdAt":{"type":"string"},"isAdministrator":{"type":"boolean"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"page":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"users":[{"id":"...","email":"...","username":"...","displayName":"...","avatar":"...","bio":"...","emailVerified":true,"cleared":false,"customerStatus":"free","createdAt":"...","isAdministrator":false}],"pagination":{"total":1024,"limit":10,"offset":0,"page":1,"hasMore":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Admin"],"summary":"Create a new user (admin only)","operationId":"postAdminUsers","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"},"password":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"bio":{},"emailVerified":{"type":"boolean"},"isAdministrator":{"type":"boolean"},"customerStatus":{"type":"string"}},"example":{"email":"user@example.com","username":"user1","password":"min8chars","displayName":"User One","avatar":null,"bio":null,"emailVerified":false,"isAdministrator":false,"customerStatus":"free"}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/admin/users/bulk-clearance":{"patch":{"tags":["Admin"],"summary":"Flip cleared status for each selected user (admin + Public owner only)","operationId":"patchAdminUsersBulkClearance","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userIds":{"type":"array","items":{"type":"string"}}},"example":{"userIds":["u1","u2","u3"]}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/admin/users/bulk-delete":{"post":{"tags":["Admin"],"summary":"Delete multiple users (admin + Public owner only)","operationId":"postAdminUsersBulkDelete","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userIds":{"type":"array","items":{"type":"string"}}},"example":{"userIds":["u1","u2"]}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/admin/users/bulk-status":{"patch":{"tags":["Admin"],"summary":"Set emailVerified for multiple users (admin + Public owner only)","operationId":"patchAdminUsersBulkStatus","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userIds":{"type":"array","items":{"type":"string"}},"emailVerified":{"type":"boolean"}},"example":{"userIds":["u1","u2"],"emailVerified":true}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/admin/users/{userId}":{"put":{"tags":["Admin"],"summary":"Update a user (admin + Public owner only)","operationId":"putAdminUsersByUserId","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Admin"],"summary":"Delete a user (admin only)","operationId":"deleteAdminUsersByUserId","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/admin/users/{userId}/password":{"post":{"tags":["Admin"],"summary":"Set a user's password (admin + Public owner only).","operationId":"postAdminUsersByUserIdPassword","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string"}},"example":{"password":"min8chars"}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/analytics/ingest":{"post":{"tags":["Utility"],"summary":"First-party analytics beacon.","operationId":"postAnalyticsIngest","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"path":{"type":"string"},"referrer":{"type":"string"}},"example":{"type":"page_view","path":"/dashboard","referrer":"https://google.com"}}}}},"security":[],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/architecture-aggregates/schema":{"get":{"tags":["Utility"],"summary":"Get ERD data from Prisma schema","operationId":"getArchitectureAggregatesSchema","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/architecture-aggregates/{table}":{"get":{"tags":["Utility"],"summary":"Get paginated data from a database table (read-only, owner access only)","operationId":"getArchitectureAggregatesByTable","parameters":[{"name":"table","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/auth/accounts":{"get":{"tags":["Authentication"],"summary":"List all cached (multi-account) sessions for the current browser cookie.","operationId":"getAuthAccounts","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{}}}},"currentUserId":{"type":"string"}},"example":{"accounts":[{"id":"user1","username":"alice","displayName":"Alice","avatar":null}],"currentUserId":"user1"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/bluesky/authorize":{"get":{"tags":["Authentication"],"summary":"Bluesky OAuth - Initiate authorization flow.","operationId":"getAuthBlueskyAuthorize","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/bluesky/callback":{"get":{"tags":["Authentication"],"summary":"Bluesky OAuth callback.","operationId":"getAuthBlueskyCallback","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/forgot-password":{"post":{"tags":["Authentication"],"summary":"Request a password-reset email.","operationId":"postAuthForgotPassword","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"}},"example":{"email":"you@example.com"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"If an account with that email exists, a password reset link has been sent."}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/github/authorize":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/github/authorize","operationId":"getAuthGithubAuthorize","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/github/callback":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/github/callback","operationId":"getAuthGithubCallback","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/linkedin/authorize":{"get":{"tags":["LinkedIn"],"summary":"GET /api/auth/linkedin/authorize","operationId":"getAuthLinkedinAuthorize","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/linkedin/callback":{"get":{"tags":["LinkedIn"],"summary":"GET /api/auth/linkedin/callback","operationId":"getAuthLinkedinCallback","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/linkedin/org-authorize":{"get":{"tags":["LinkedIn"],"summary":"Start the LinkedIn OAuth flow that connects a shared organization LinkedIn credential.","operationId":"getAuthLinkedinOrgAuthorize","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/linkedin/org-callback":{"get":{"tags":["LinkedIn"],"summary":"LinkedIn redirect target for the org flow.","operationId":"getAuthLinkedinOrgCallback","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/linkedin/status":{"get":{"tags":["LinkedIn"],"summary":"Check whether LinkedIn OAuth is configured on this server.","operationId":"getAuthLinkedinStatus","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"configured":{"type":"boolean"},"redirectUri":{"type":"string"}},"example":{"configured":true,"redirectUri":"https://..."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/login":{"post":{"tags":["Authentication"],"summary":"Authenticate with email and password; sets a session cookie.","operationId":"postAuthLogin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"example":{"email":"you@example.com","password":"yourpassword"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"bio":{},"theme":{},"emailVerified":{"type":"boolean"},"createdAt":{"type":"string"}}}},"example":{"message":"Login successful","user":{"id":"clxyz...","email":"you@example.com","username":"yourhandle","displayName":"Your Name","avatar":null,"bio":null,"theme":null,"emailVerified":true,"createdAt":"2026-01-01T00:00:00.000Z"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/logout":{"post":{"tags":["Authentication"],"summary":"Destroy the current session (or all sessions with all=true).","operationId":"postAuthLogout","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Logged out successfully"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Logged out successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/mastodon/authorize":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/mastodon/authorize","operationId":"getAuthMastodonAuthorize","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/mastodon/callback":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/mastodon/callback","operationId":"getAuthMastodonCallback","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/register":{"post":{"tags":["Authentication"],"summary":"Create a new user account; sets a session cookie and sends a verification email.","operationId":"postAuthRegister","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"},"password":{"type":"string"},"displayName":{"type":"string"}},"example":{"email":"you@example.com","username":"yourhandle","password":"minimum8chars","displayName":"Your Name"}}}}},"security":[],"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"bio":{},"theme":{},"emailVerified":{"type":"boolean"},"createdAt":{"type":"string"}}}},"example":{"message":"User created successfully","user":{"id":"clxyz...","email":"you@example.com","username":"yourhandle","displayName":"Your Name","avatar":null,"bio":null,"theme":null,"emailVerified":false,"createdAt":"2026-06-04T00:00:00.000Z"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/remove-account":{"post":{"tags":["Authentication"],"summary":"Remove a cached account from the multi-account session list.","operationId":"postAuthRemoveAccount","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"}},"example":{"userId":"user2"}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Account removed"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/reset-password":{"post":{"tags":["Authentication"],"summary":"Complete a password reset using the token from the reset email.","operationId":"postAuthResetPassword","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"password":{"type":"string"}},"example":{"token":"<reset-token>","password":"newpassword123"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Password has been reset successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/send-verification-email":{"post":{"tags":["Authentication"],"summary":"Resend the email verification email.","operationId":"postAuthSendVerificationEmail","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Verification email sent successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/switch":{"post":{"tags":["Authentication"],"summary":"Switch the active session to a different cached account.","operationId":"postAuthSwitch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"}},"example":{"userId":"user2"}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Switched successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/sync-token":{"post":{"tags":["Authentication"],"summary":"Authenticate with email and password; returns a sync token (API key) for CLI use.","operationId":"postAuthSyncToken","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"example":{"email":"you@example.com","password":"yourpassword"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"message":{"type":"string"}},"example":{"token":"a3f8...64-char hex...","message":"Sync token created. Store it in your CLI config."}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/twitter/authorize":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/twitter/authorize","operationId":"getAuthTwitterAuthorize","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/twitter/callback":{"get":{"tags":["Authentication"],"summary":"GET /api/auth/twitter/callback","operationId":"getAuthTwitterCallback","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/auth/twitter/status":{"get":{"tags":["Authentication"],"summary":"Check whether Twitter/X OAuth is configured on this server.","operationId":"getAuthTwitterStatus","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"configured":{"type":"boolean"},"redirectUri":{"type":"string"}},"example":{"configured":true,"redirectUri":"https://..."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/verify-email":{"post":{"tags":["Authentication"],"summary":"Verify a user's email address using the token sent at registration.","operationId":"postAuthVerifyEmail","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"example":{"token":"<verification-token>"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Email verified successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/verify-email-change":{"post":{"tags":["Authentication"],"summary":"Confirm a requested email address change using the token sent to the new address.","operationId":"postAuthVerifyEmailChange","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"example":{"token":"<email-change-token>"}}}}},"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Email updated successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/cron/publish-scheduled-messages":{"get":{"tags":["Webhooks & Cron"],"summary":"Cron: publishes scheduled messages whose scheduledAt has passed.","operationId":"getCronPublishScheduledMessages","description":"Internal job protected by CRON_SECRET (Bearer). Not for general client use.","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/cron/sync-github-lists":{"get":{"tags":["Webhooks & Cron"],"summary":"Hourly cron: syncs all GitHub-backed lists from GitHub API to cache.","operationId":"getCronSyncGithubLists","description":"Internal job protected by CRON_SECRET (Bearer). Not for general client use.","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/documents":{"get":{"tags":["Documents"],"summary":"Get root-level documents (folderId is null) for the current user","operationId":"getDocuments","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Documents"],"summary":"Create a root-level document (folderId is null)","operationId":"postDocuments","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string"},"relativePath":{"type":"string"},"isPublic":{"type":"boolean"}},"example":{"title":"My Notes","content":"# Hello\n\nMarkdown content.","relativePath":"my-notes.md","isPublic":false}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/api/documents/folders":{"get":{"tags":["Document Folders"],"summary":"Get root folders for the current user","operationId":"getDocumentsFolders","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"folders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"relativePath":{"type":"string"}}}}}}}},"example":{"folders":[{"id":"f1","name":"Work","parentId":null,"documents":[{"id":"doc1","title":"Meeting Notes","relativePath":"meeting-notes.md"}]},{"id":"f2","name":"Projects","parentId":"f1","documents":[]},{"id":"f3","name":"Archive","parentId":"f1","documents":[{"id":"doc2","title":"Old Spec","relativePath":"old-spec.md"}]}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Document Folders"],"summary":"Create a new folder","operationId":"postDocumentsFolders","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"parentId":{"type":"string"}},"example":{"name":"Projects","parentId":"f1"}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/folders/{id}":{"get":{"tags":["Document Folders"],"summary":"Get a folder by ID with children and documents","operationId":"getDocumentsFoldersById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Document Folders"],"summary":"Update a folder (rename, move)","operationId":"putDocumentsFoldersById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"parentId":{"type":"string"}},"example":{"name":"Renamed Folder","parentId":"f3"}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Document Folders"],"summary":"Soft delete a folder (cascade to children and documents)","operationId":"deleteDocumentsFoldersById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Folder deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/documents/folders/{id}/documents":{"get":{"tags":["Document Folders"],"summary":"List documents in a folder","operationId":"getDocumentsFoldersByIdDocuments","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Document Folders"],"summary":"Create a new document in a folder","operationId":"postDocumentsFoldersByIdDocuments","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string"},"relativePath":{"type":"string"},"isPublic":{"type":"boolean"}},"example":{"title":"Meeting Notes","content":"# Agenda\n\n...","relativePath":"meeting-notes.md","isPublic":false}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/documents/from-template":{"post":{"tags":["Documents"],"summary":"Body: { templateDocumentId: string, targetFolderId?: string | null }","operationId":"postDocumentsFromTemplate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"templateDocumentId":{"type":"string"},"targetFolderId":{"type":"string"}},"example":{"templateDocumentId":"doc_tmpl","targetFolderId":"folder123"}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/search":{"get":{"tags":["Documents"],"summary":"Search documents by title or content","operationId":"getDocumentsSearch","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"content":{"type":"string"},"folderId":{"type":"string"},"isPublic":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"documents":[{"id":"doc1","title":"Meeting Notes","content":"Full document body...","folderId":"f1","isPublic":false,"createdAt":"2026-06-21T12:00:00.000Z","updatedAt":"2026-06-21T12:00:00.000Z"}],"pagination":{"total":3,"limit":20,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/sync":{"get":{"tags":["Documents"],"summary":"Return folders and documents changed since lastSyncAt (delta sync).","operationId":"getDocumentsSync","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Documents"],"summary":"Apply batch of create/update/delete operations from CLI","operationId":"postDocumentsSync","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"operations":{"type":"array","items":{"type":"object","properties":{"op":{"type":"string"},"type":{"type":"string"},"path":{"type":"string"}}}}},"example":{"operations":[{"op":"create","type":"folder","path":"Work/Projects"},{"op":"create","type":"document","path":"Work/Projects/notes.md","data":{"id":"doc_cli_1","folderId":"f1","title":"Notes","content":"# Hello","relativePath":"notes.md","isPublic":false}},{"op":"delete","type":"document","path":"old.md","data":{"id":"doc_old"}}]}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"lastSyncAt":{"type":"string"}},"example":{"lastSyncAt":"2026-06-04T12:05:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/templates":{"get":{"tags":["Documents"],"summary":"Ensures _templates root folder exists; lists template documents.","operationId":"getDocumentsTemplates","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/templates/seed-defaults":{"post":{"tags":["Documents"],"summary":"Idempotently adds default Recipe and Social Media Campaign templates.","operationId":"postDocumentsTemplatesSeedDefaults","responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/documents/{id}":{"get":{"tags":["Documents"],"summary":"Get a document by ID (owner or public)","operationId":"getDocumentsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Documents"],"summary":"Update a document","operationId":"putDocumentsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Documents"],"summary":"Alias for PUT — iOS client uses PATCH for partial document updates,","operationId":"patchDocumentsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string"},"isPublic":{"type":"boolean"},"folderId":{"type":"string"}},"example":{"title":"Updated Title","content":"New markdown content","isPublic":true,"folderId":"folder123"}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Documents"],"summary":"Soft delete a document and cascade delete blob images","operationId":"deleteDocumentsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Document deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/documents/{id}/images/upload":{"post":{"tags":["Documents"],"summary":"Upload an image to embed in a document.","operationId":"postDocumentsByIdImagesUpload","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://vercel-blob.com/documents/..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/exports/follows":{"get":{"tags":["Exports"],"summary":"Export user's follow relationships as CSV","operationId":"getExportsFollows","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/exports/list-data-rows":{"get":{"tags":["Exports"],"summary":"Export user's list data rows as CSV","operationId":"getExportsListDataRows","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/exports/lists":{"get":{"tags":["Exports"],"summary":"Export user's lists as CSV","operationId":"getExportsLists","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/exports/messages":{"get":{"tags":["Exports"],"summary":"Export user's messages as CSV","operationId":"getExportsMessages","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/folders":{"get":{"tags":["List Folders"],"summary":"Get all non-deleted list folders for the authenticated user","operationId":"getFolders","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"folders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{}}}}},"example":{"folders":[{"id":"f1","name":"Work","parentId":null},{"id":"f2","name":"Projects","parentId":"f1"}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["List Folders"],"summary":"Create a new list folder (subscribers only)","operationId":"postFolders","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"parentId":{}},"example":{"name":"My Folder","parentId":null}}}}},"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"folder":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{}}}},"example":{"message":"Folder created successfully","folder":{"id":"f1","name":"My Folder","parentId":null}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/folders/{id}":{"put":{"tags":["List Folders"],"summary":"Rename or move a list folder","operationId":"putFoldersById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"parentId":{"type":"string"}},"example":{"name":"New Name","parentId":"f3"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"folder":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{"type":"string"}}}},"example":{"message":"Folder updated successfully","folder":{"id":"f1","name":"New Name","parentId":"f3"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["List Folders"],"summary":"Soft-delete a list folder; detach its lists first","operationId":"deleteFoldersById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Folder deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/requests":{"get":{"tags":["Following"],"summary":"Get pending follow requests for the current user","operationId":"getFollowRequests","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"requests":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"followId":{"type":"string"},"createdAt":{"type":"string"}}}}},"example":{"requests":[{"id":"u3","username":"bob","displayName":"Bob","avatar":null,"followId":"fol2","createdAt":"2026-06-04T10:00:00.000Z"}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/follow/{userId}":{"post":{"tags":["Following"],"summary":"Follow a user","operationId":"postFollowByUserId","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"follow":{"type":"object","properties":{"id":{"type":"string"},"followerId":{"type":"string"},"followingId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"example":{"follow":{"id":"fol1","followerId":"u1","followingId":"u2","status":"approved","createdAt":"...","updatedAt":"..."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Following"],"summary":"Unfollow a user","operationId":"deleteFollowByUserId","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Unfollowed successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/approve":{"post":{"tags":["Following"],"summary":"Approve a pending follow request","operationId":"postFollowByUserIdApprove","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"follow":{"type":"object","properties":{"id":{"type":"string"},"followerId":{"type":"string"},"followingId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"example":{"follow":{"id":"...","followerId":"u3","followingId":"u1","status":"approved","createdAt":"...","updatedAt":"..."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/counts":{"get":{"tags":["Following"],"summary":"Get follower/following counts for a user","operationId":"getFollowByUserIdCounts","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"followers":{"type":"integer"},"following":{"type":"integer"}},"example":{"followers":42,"following":17}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/followers":{"get":{"tags":["Following"],"summary":"Get list of users following a user","operationId":"getFollowByUserIdFollowers","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"followers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"followId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"followers":[{"id":"u2","username":"alice","displayName":"Alice","avatar":null,"followId":"fol_123","status":"approved","createdAt":"2026-06-04T10:00:00.000Z"}],"pagination":{"total":42,"limit":50,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/following":{"get":{"tags":["Following"],"summary":"Get list of users a user is following","operationId":"getFollowByUserIdFollowing","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"following":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"followId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"following":[{"id":"u4","username":"carol","displayName":"Carol","avatar":null,"followId":"fol_456","status":"approved","createdAt":"2026-06-04T10:00:00.000Z"}],"pagination":{"total":17,"limit":50,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/mutual":{"get":{"tags":["Following"],"summary":"Get mutual connections between current user and specified user","operationId":"getFollowByUserIdMutual","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"mutualFollowers":{"type":"integer"},"mutualFollowing":{"type":"integer"}},"example":{"mutualFollowers":4,"mutualFollowing":6}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/reject":{"post":{"tags":["Following"],"summary":"Reject a pending follow request","operationId":"postFollowByUserIdReject","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Follow request rejected"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/remove":{"delete":{"tags":["Following"],"summary":"Remove a follower (only callable by the user being followed)","operationId":"deleteFollowByUserIdRemove","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Follower removed successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/follow/{userId}/status":{"get":{"tags":["Following"],"summary":"Get follow status between current user and target user","operationId":"getFollowByUserIdStatus","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"isFollowing":{"type":"boolean"},"isPending":{"type":"boolean"}},"example":{"status":"approved","isFollowing":true,"isPending":false}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/github/issues":{"get":{"tags":["GitHub"],"summary":"List issues from a repository.","operationId":"getGithubIssues","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["GitHub"],"summary":"Create a GitHub issue.","operationId":"postGithubIssues","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"repo":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"labels":{"type":"array","items":{}},"assignees":{"type":"array","items":{}}},"example":{"repo":"owner/repo","title":"Bug report","body":"Details...","labels":[],"assignees":[]}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/github/issues/{owner}/{repo}/{number}":{"patch":{"tags":["GitHub"],"summary":"Update an existing GitHub issue's labels and/or assignees via the GitHub API.","operationId":"patchGithubIssuesByOwnerByRepoByNumber","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"labels":{"type":"array","items":{"type":"string"}},"assignees":{"type":"array","items":{"type":"string"}}},"example":{"labels":["bug","p1"],"assignees":["octocat"]}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/github/issues/{owner}/{repo}/{number}/comments":{"post":{"tags":["GitHub"],"summary":"Add a comment to an existing GitHub issue.","operationId":"postGithubIssuesByOwnerByRepoByNumberComments","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string"}},"example":{"body":"Comment text"}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/github/repos":{"get":{"tags":["GitHub"],"summary":"List accessible repositories for the linked GitHub account.","operationId":"getGithubRepos","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/github/repos/{owner}/{repo}/assignees":{"get":{"tags":["GitHub"],"summary":"List candidate assignees for :owner/:repo via the GitHub API.","operationId":"getGithubReposByOwnerByRepoAssignees","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/github/repos/{owner}/{repo}/labels":{"get":{"tags":["GitHub"],"summary":"List defined labels for :owner/:repo via the GitHub API.","operationId":"getGithubReposByOwnerByRepoLabels","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/github/repos/{owner}/{repo}/next-issue-number":{"get":{"tags":["GitHub"],"summary":"Returns the next issue number for the repository (max existing + 1, or 1 if no issues).","operationId":"getGithubReposByOwnerByRepoNextIssueNumber","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"nextNumber":{"type":"integer"}},"example":{"nextNumber":124}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/images/proxy":{"get":{"tags":["Utility"],"summary":"Proxy endpoint for fetching images (primarily Instagram) server-side","operationId":"getImagesProxy","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/linkedin/posting-targets":{"get":{"tags":["LinkedIn"],"summary":"List the user's available LinkedIn targets together with their saved posting preference.","operationId":"getLinkedinPostingTargets","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"label":{"type":"string"},"avatarUrl":{},"enabled":{"type":"boolean"}}}},"orgScopeMissing":{"type":"boolean"}},"example":{"targets":[{"kind":"personal","label":"Alice Example","avatarUrl":null,"enabled":true},{"kind":"orgPage","pageId":"...","linkedInPageId":"12345678","label":"Acme Corp","logoUrl":null,"enabled":false},{"kind":"personalPage","personalPageId":"...","linkedInPageId":"87654321","label":"Alice's Studio","logoUrl":null,"enabled":true}],"orgScopeMissing":false}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"put":{"tags":["LinkedIn"],"summary":"Replace the user's LinkedIn posting-target preferences atomically.","operationId":"putLinkedinPostingTargets","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"}}}}},"example":{"targets":[{"kind":"personal"},{"kind":"orgPage","pageId":"<OrgLinkedInPage uuid>"},{"kind":"personalPage","personalPageId":"<LinkedInPersonalPage uuid>"}]}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"label":{"type":"string"},"avatarUrl":{},"enabled":{"type":"boolean"}}}}},"example":{"targets":[{"kind":"personal","label":"Alice Example","avatarUrl":null,"enabled":true},{"kind":"orgPage","pageId":"...","linkedInPageId":"12345678","label":"Acme Corp","logoUrl":null,"enabled":true},{"kind":"personalPage","personalPageId":"...","linkedInPageId":"87654321","label":"Alice's Studio","logoUrl":null,"enabled":true}]}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/linkedin/sync-pages":{"post":{"tags":["LinkedIn"],"summary":"Re-discovers the LinkedIn company pages the current user administers via","operationId":"postLinkedinSyncPages","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"linkedInPageId":{"type":"string"},"pageName":{"type":"string"},"pageLogoUrl":{"type":"string"},"lastSyncedAt":{"type":"string"}}}}},"example":{"pages":[{"id":"<LinkedInPersonalPage uuid>","linkedInPageId":"87654321","pageName":"Alice's Studio","pageLogoUrl":"https://...","lastSyncedAt":"2026-06-12T00:00:00.000Z"}]}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"linkedInPageId":{"type":"string"},"pageName":{"type":"string"},"pageLogoUrl":{"type":"string"},"lastSyncedAt":{"type":"string"}}}}},"example":{"pages":[{"id":"<LinkedInPersonalPage uuid>","linkedInPageId":"87654321","pageName":"Alice's Studio","pageLogoUrl":"https://...","lastSyncedAt":"2026-06-12T00:00:00.000Z"}]}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/linkedin/targets":{"get":{"tags":["LinkedIn"],"summary":"List every LinkedIn destination the user can post to right now — the personal account (when linked with an active acc...","operationId":"getLinkedinTargets","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"label":{"type":"string"},"avatarUrl":{}}}}},"example":{"targets":[{"kind":"personal","label":"Alice Example","avatarUrl":null},{"kind":"orgPage","pageId":"...","linkedInPageId":"12345678","label":"Acme Corp","logoUrl":null},{"kind":"personalPage","personalPageId":"...","linkedInPageId":"87654321","label":"Alice's Studio","logoUrl":null}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/lists":{"get":{"tags":["Lists"],"summary":"Get all lists for the current user","operationId":"getLists","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{},"isPublic":{"type":"boolean"},"parentId":{},"parent":{},"children":{"type":"array","items":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"lists":[{"id":"list1","title":"My List","description":null,"isPublic":false,"parentId":null,"parent":null,"children":[],"createdAt":"...","updatedAt":"..."}],"pagination":{"total":12,"limit":50,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Lists"],"summary":"Create a new list with schema from DSL","operationId":"postLists","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"parentId":{},"schema":{"type":"string"},"messageId":{},"metadata":{},"source":{"type":"string"},"githubRepo":{}},"example":{"title":"Project Backlog","description":"Optional description","isPublic":false,"parentId":null,"schema":"optional DSL string","messageId":null,"metadata":null,"source":"local","githubRepo":null}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/api/lists/connections":{"get":{"tags":["Lists"],"summary":"Get all connections between the user's lists.","operationId":"getListsConnections","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"connections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fromListId":{"type":"string"},"toListId":{"type":"string"},"label":{}}}}},"example":{"connections":[{"id":"c1","fromListId":"list1","toListId":"list2","label":null}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Lists"],"summary":"Create a directional connection between two lists the user owns.","operationId":"postListsConnections","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fromListId":{"type":"string"},"toListId":{"type":"string"},"label":{"type":"string"}},"example":{"fromListId":"list1","toListId":"list2","label":"depends on"}}}}},"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"fromListId":{"type":"string"},"toListId":{"type":"string"},"label":{"type":"string"},"createdAt":{"type":"string"}},"example":{"id":"c1","fromListId":"list1","toListId":"list2","label":"depends on","createdAt":"..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/lists/connections/{id}":{"delete":{"tags":["Lists"],"summary":"Delete a list connection by id.","operationId":"deleteListsConnectionsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"example":{"success":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/search":{"get":{"tags":["Lists"],"summary":"Search lists by title or description","operationId":"getListsSearch","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"folderId":{"type":"string"},"itemCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"lists":[{"id":"list1","title":"Reading List","description":"Books to read this year","isPublic":false,"folderId":"f1","itemCount":42,"createdAt":"2026-06-21T12:00:00.000Z","updatedAt":"2026-06-21T12:00:00.000Z"}],"pagination":{"total":3,"limit":20,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/lists/{id}":{"get":{"tags":["Lists"],"summary":"Get a single list by ID","operationId":"getListsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Lists"],"summary":"Update a list","operationId":"putListsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"parentId":{},"folderId":{},"messageId":{},"metadata":{"type":"object","properties":{}}},"example":{"title":"New Title","description":"Updated description","isPublic":true,"parentId":null,"folderId":null,"messageId":null,"metadata":{}}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Lists"],"summary":"Delete a list (hard delete with cascading)","operationId":"deleteListsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"List deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/data":{"get":{"tags":["Lists"],"summary":"Get list data rows with pagination, filtering, and sorting","operationId":"getListsByIdData","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Lists"],"summary":"Create a new list data row or bulk create rows","operationId":"postListsByIdData","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string"},"title":{"type":"string"}}}},"example":{"data":{"status":"open","title":"New task"}}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/data/{rowId}":{"get":{"tags":["Lists"],"summary":"Get a single list data row","operationId":"getListsByIdDataByRowId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rowId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Lists"],"summary":"Update a list data row","operationId":"putListsByIdDataByRowId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rowId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string"},"title":{"type":"string"}}}},"example":{"data":{"status":"closed","title":"Updated task"}}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Lists"],"summary":"Delete a list data row (soft delete).","operationId":"deleteListsByIdDataByRowId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rowId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Row deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/refresh":{"post":{"tags":["Lists"],"summary":"Manual refresh for GitHub-backed lists.","operationId":"postListsByIdRefresh","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"count":{"type":"integer"}},"example":{"message":"Refreshed","count":42}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/schema":{"get":{"tags":["Lists"],"summary":"Get list schema (properties) as DSL","operationId":"getListsByIdSchema","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string"}},"example":{"data":"title: My List\n---\nstatus: text required\n..."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Lists"],"summary":"Two body shapes are supported, selected by the request payload:","operationId":"putListsByIdSchema","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"type":"string"},"parentId":{},"isPublic":{"type":"boolean"}},"example":{"schema":"title: My List\n---\nstatus: text required\n...","parentId":null,"isPublic":false}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/watchers":{"get":{"tags":["Lists"],"summary":"Get watchers for a list.","operationId":"getListsByIdWatchers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"watchers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"role":{"type":"string"},"createdAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{}}}}}}},"example":{"watchers":[{"id":"w1","userId":"u2","role":"collaborator","createdAt":"2026-06-21T12:00:00.000Z","user":{"id":"u2","username":"bob","displayName":"Bob","avatar":null}}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Lists"],"summary":"Add watcher(s) to a list.","operationId":"postListsByIdWatchers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string"}},"example":{"userId":"u2","role":"collaborator"}}}}},"responses":{"201":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"watching":{"type":"boolean"}},"example":{"watching":true}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/watchers/me":{"get":{"tags":["Lists"],"summary":"Check if current user is watching the list.","operationId":"getListsByIdWatchersMe","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"watching":{"type":"boolean"}},"example":{"watching":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/watchers/users":{"get":{"tags":["Lists"],"summary":"Search for users to add as watchers.","operationId":"getListsByIdWatchersUsers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"email":{"type":"string"},"avatar":{"type":"string"}}}},"total":{"type":"integer"},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"users":[{"id":"...","username":"...","displayName":"...","email":"...","avatar":"..."}],"total":124,"pagination":{"limit":50,"offset":0,"hasMore":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/lists/{id}/watchers/{userId}":{"put":{"tags":["Lists"],"summary":"Change a user's role.","operationId":"putListsByIdWatchersByUserId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"}},"example":{"role":"collaborator"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"}},"example":{"role":"collaborator"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Lists"],"summary":"Remove a user from list access.","operationId":"deleteListsByIdWatchersByUserId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"boolean"}},"example":{"removed":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/location":{"get":{"tags":["Utility"],"summary":"Resolve latitude/longitude to a city, state, and timezone via the NOAA API.","operationId":"getLocation","security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"city":{"type":"string"},"state":{"type":"string"},"country":{"type":"string"},"coordinates":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}}},"timezone":{"type":"string"}},"example":{"city":"Seattle","state":"WA","country":"United States","coordinates":{"latitude":47.6,"longitude":-122.3},"timezone":"America/Los_Angeles"}}}}}}}},"/api/messages":{"get":{"tags":["Messages"],"summary":"Retrieve the top-level message feed.","operationId":"getMessages","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"content":{"type":"string"},"publiclyVisible":{"type":"boolean"},"imageUrls":{"type":"array","items":{}},"videoUrls":{"type":"array","items":{}},"tags":{"type":"array","items":{}},"crossPostUrls":{"type":"array","items":{}},"scheduledAt":{},"pushedMessageId":{},"pushCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{}}},"dugByMe":{"type":"boolean"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"messages":[{"id":"msg123","content":"Hello world","publiclyVisible":true,"imageUrls":[],"videoUrls":[],"tags":[],"crossPostUrls":[],"scheduledAt":null,"pushedMessageId":null,"pushCount":0,"createdAt":"2026-06-04T10:00:00.000Z","updatedAt":"2026-06-04T10:00:00.000Z","user":{"id":"u1","username":"alice","displayName":"Alice","avatar":null},"dugByMe":false}],"pagination":{"total":120,"limit":50,"offset":0,"hasMore":true}}}}}}}},"post":{"tags":["Messages"],"summary":"Create a message.","operationId":"postMessages","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string"},"publiclyVisible":{"type":"boolean"},"parentId":{},"pushedMessageId":{},"imageUrls":{"type":"array","items":{}},"videoUrls":{"type":"array","items":{}},"tags":{"type":"array","items":{}},"mastodonProviderIds":{"type":"array","items":{}},"crossPostToBluesky":{"type":"boolean"},"crossPostToLinkedIn":{"type":"boolean"},"linkedInTargets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"}}}},"linkedInLinkAsFirstComment":{"type":"boolean"},"crossPostToTwitter":{"type":"boolean"},"scheduledAt":{},"scheduledCrossPostConfig":{}},"example":{"content":"Your message text","publiclyVisible":true,"parentId":null,"pushedMessageId":null,"imageUrls":[],"videoUrls":[],"tags":[],"mastodonProviderIds":[],"crossPostToBluesky":false,"crossPostToLinkedIn":false,"linkedInTargets":[{"kind":"personal"},{"kind":"orgPage","pageId":"<org-linkedin-page-uuid>"},{"kind":"personalPage","personalPageId":"<linkedin-personal-page-uuid>"}],"linkedInLinkAsFirstComment":false,"crossPostToTwitter":false,"scheduledAt":null,"scheduledCrossPostConfig":null}}}}},"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/api/messages/images/upload":{"post":{"tags":["Messages"],"summary":"Upload an image to attach to a message.","operationId":"postMessagesImagesUpload","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://vercel-blob.com/messages/..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/messages/scheduled":{"get":{"tags":["Messages"],"summary":"List the authenticated user's upcoming scheduled messages.","operationId":"getMessagesScheduled","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/messages/search":{"get":{"tags":["Messages"],"summary":"Search top-level messages by content (respecting feed visibility)","operationId":"getMessagesSearch","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"content":{"type":"string"},"publiclyVisible":{"type":"boolean"},"imageUrls":{"type":"array","items":{}},"videoUrls":{"type":"array","items":{}},"tags":{"type":"array","items":{}},"crossPostUrls":{"type":"array","items":{}},"scheduledAt":{},"pushedMessageId":{},"pushCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{}}},"dugByMe":{"type":"boolean"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"messages":[{"id":"msg123","content":"Hello world from the API","publiclyVisible":true,"imageUrls":[],"videoUrls":[],"tags":[],"crossPostUrls":[],"scheduledAt":null,"pushedMessageId":null,"pushCount":0,"createdAt":"2026-06-04T10:00:00.000Z","updatedAt":"2026-06-04T10:00:00.000Z","user":{"id":"u1","username":"alice","displayName":"Alice","avatar":null},"dugByMe":false}],"pagination":{"total":1,"limit":20,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/messages/videos/upload":{"post":{"tags":["Messages"],"summary":"Upload a video to attach to a message.","operationId":"postMessagesVideosUpload","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://vercel-blob.com/messages/..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/messages/{id}":{"get":{"tags":["Messages"],"summary":"Retrieve a single message.","operationId":"getMessagesById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response."},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Messages"],"summary":"Edit a scheduled message that has not yet been published.","operationId":"patchMessagesById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scheduledAt":{"type":"string"},"scheduledCrossPostConfig":{"type":"object","properties":{"mastodonProviderIds":{"type":"array","items":{}},"crossPostToBluesky":{"type":"boolean"},"crossPostToLinkedIn":{"type":"boolean"},"linkedInLinkAsFirstComment":{"type":"boolean"},"linkedInTargets":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"}}}},"crossPostToTwitter":{"type":"boolean"}}}},"example":{"scheduledAt":"2026-07-01T09:00:00.000Z","scheduledCrossPostConfig":{"mastodonProviderIds":[],"crossPostToBluesky":true,"crossPostToLinkedIn":true,"linkedInLinkAsFirstComment":false,"linkedInTargets":[{"kind":"personal"},{"kind":"orgPage","pageId":"<org-linkedin-page-uuid>"},{"kind":"personalPage","personalPageId":"<linkedin-personal-page-uuid>"}],"crossPostToTwitter":false}}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Messages"],"summary":"Delete a message and all its replies.","operationId":"deleteMessagesById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Message deleted successfully"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/messages/{id}/dig":{"post":{"tags":["Messages"],"summary":"Record a \"dig\" reaction on a message.","operationId":"postMessagesByIdDig","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"isNewDig":{"type":"boolean"},"digCount":{"type":"integer"},"digCreatedAt":{"type":"string"}},"example":{"isNewDig":true,"digCount":5,"digCreatedAt":"2026-06-18T00:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Messages"],"summary":"Remove the viewer's dig on a message.","operationId":"deleteMessagesByIdDig","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"digCount":{"type":"integer"}},"example":{"digCount":4}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/messages/{id}/metadata":{"post":{"tags":["Messages"],"summary":"Fetches and updates metadata for a message's links","operationId":"postMessagesByIdMetadata","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"metadata":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"}}}}}}},"example":{"message":"Metadata fetched successfully","metadata":{"links":[{"url":"...","title":"...","description":"...","image":"..."}]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/messages/{id}/replies":{"get":{"tags":["Messages"],"summary":"Returns direct replies to a message.","operationId":"getMessagesByIdReplies","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response."},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/notifications":{"get":{"tags":["Notifications"],"summary":"Get unread notification tray items and the total unread count.","operationId":"getNotifications","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"unreadCount":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"actionUrl":{"type":"string"},"type":{"type":"string"},"metadata":{"type":"object","properties":{}},"createdAt":{"type":"string"},"readAt":{}}}}},"example":{"unreadCount":3,"items":[{"id":"n1","title":"Alice liked your message","body":"...","actionUrl":"/messages/msg123","type":"like","metadata":{},"createdAt":"2026-06-04T10:00:00.000Z","readAt":null}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/notifications/mark-all-read":{"post":{"tags":["Notifications"],"summary":"Mark all unread notifications as read for the authenticated user.","operationId":"postNotificationsMarkAllRead","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"updated":{"type":"integer"}},"example":{"ok":true,"updated":5}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/notifications/{id}":{"delete":{"tags":["Notifications"],"summary":"Delete a notification owned by the authenticated user.","operationId":"deleteNotificationsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/notifications/{id}/read":{"patch":{"tags":["Notifications"],"summary":"Mark a single notification as read (idempotent).","operationId":"patchNotificationsByIdRead","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"example":{"ok":true}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/oauth/client-metadata":{"get":{"tags":["Utility"],"summary":"OAuth client metadata for Bluesky/AT Protocol.","operationId":"getOauthClientMetadata","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/openapi.json":{"get":{"tags":["Openapi.json"],"summary":"Serves the generated OpenAPI 3.1 specification that backs the Swagger UI page","operationId":"getOpenapiJson","responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/organizations":{"get":{"tags":["Organizations"],"summary":"List organizations.","operationId":"getOrganizations","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Organizations"],"summary":"Create a new organization.","operationId":"postOrganizations","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"avatar":{},"isPublic":{"type":"boolean"}},"example":{"name":"Acme Corp","description":"Our org","avatar":null,"isPublic":true}}}}},"security":[{"cookieAuth":[]}],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/organizations/{id}":{"get":{"tags":["Organizations"],"summary":"Get an organization by ID or slug.","operationId":"getOrganizationsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"isPublic":{"type":"boolean"},"memberCount":{"type":"integer"},"userRole":{"type":"string"}}}},"example":{"organization":{"id":"org1","name":"Acme","isPublic":true,"memberCount":12,"userRole":"member"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Organizations"],"summary":"Update organization details.","operationId":"putOrganizationsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"avatar":{},"isPublic":{"type":"boolean"},"settings":{"type":"object","properties":{}}},"example":{"name":"New Name","description":"Updated","avatar":null,"isPublic":true,"settings":{}}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Organizations"],"summary":"Delete an organization.","operationId":"deleteOrganizationsById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/linkedin/assignments":{"put":{"tags":["Organizations"],"summary":"Assign or unassign an organization member to one of the org's LinkedIn Company Pages.","operationId":"putOrganizationsByIdLinkedinAssignments","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"pageId":{"type":"string"}},"example":{"userId":"<member user id>","pageId":"<OrgLinkedInPage uuid> | null"}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"assignment":{"type":"object","properties":{"id":{"type":"string"},"pageId":{"type":"string"},"userId":{"type":"string"},"assignedByUserId":{"type":"string"}}}},"example":{"assignment":{"id":"...","pageId":"...","userId":"...","assignedByUserId":"..."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/linkedin/credential":{"delete":{"tags":["Organizations"],"summary":"Disconnect the organization's LinkedIn credential.","operationId":"deleteOrganizationsByIdLinkedinCredential","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"disconnected":{"type":"boolean"}},"example":{"disconnected":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/linkedin/status":{"get":{"tags":["Organizations"],"summary":"Return the organization's LinkedIn credential (if any), its pages, and each page's member assignments.","operationId":"getOrganizationsByIdLinkedinStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"credential":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"connectedByUserId":{"type":"string"},"providerUserId":{"type":"string"},"providerUsername":{"type":"string"},"expiresAt":{"type":"string"},"scopesGranted":{"type":"string"},"disconnectedAt":{},"lastVerifiedAt":{"type":"string"},"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"linkedInPageId":{"type":"string"},"pageName":{"type":"string"},"pageLogoUrl":{"type":"string"},"lastSyncedAt":{"type":"string"},"assignments":{"type":"array","items":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{"type":"string"}}}}}}}}}}},"role":{"type":"string"}},"example":{"credential":{"id":"...","organizationId":"...","connectedByUserId":"...","providerUserId":"...","providerUsername":"...","expiresAt":"2026-12-01T00:00:00.000Z","scopesGranted":"openid profile email w_member_social rw_organization_admin","disconnectedAt":null,"lastVerifiedAt":"2026-06-01T00:00:00.000Z","pages":[{"id":"<OrgLinkedInPage uuid>","linkedInPageId":"12345678","pageName":"Acme Corp","pageLogoUrl":"https://...","lastSyncedAt":"2026-06-01T00:00:00.000Z","assignments":[{"user":{"id":"...","username":"alice","displayName":"Alice","avatar":"..."}}]}]},"role":"owner"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/linkedin/sync-pages":{"post":{"tags":["Organizations"],"summary":"Re-discover LinkedIn Company Pages the org's stored credential admins.","operationId":"postOrganizationsByIdLinkedinSyncPages","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"linkedInPageId":{"type":"string"},"pageName":{"type":"string"},"pageLogoUrl":{"type":"string"},"lastSyncedAt":{"type":"string"}}}}},"example":{"pages":[{"id":"...","linkedInPageId":"...","pageName":"...","pageLogoUrl":"...","lastSyncedAt":"..."}]}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/members":{"get":{"tags":["Organizations"],"summary":"List members of an organization.","operationId":"getOrganizationsByIdMembers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"emailVerified":{"type":"boolean"},"role":{"type":"string"},"active":{"type":"boolean"},"joinedAt":{"type":"string"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"members":[{"id":"u1","username":"alice","displayName":"Alice","avatar":null,"emailVerified":true,"role":"owner","active":true,"joinedAt":"2026-01-01T00:00:00.000Z"}],"pagination":{"total":12,"limit":50,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Organizations"],"summary":"Add a user to an organization.","operationId":"postOrganizationsByIdMembers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string"}},"example":{"userId":"u2","role":"member"}}}}},"security":[{"cookieAuth":[]}],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/members/{userId}":{"put":{"tags":["Organizations"],"summary":"Update a member's role (and optionally their active flag).","operationId":"putOrganizationsByIdMembersByUserId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"},"active":{"type":"boolean"}},"example":{"role":"admin","active":true}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Organizations"],"summary":"Remove a member from the organization.","operationId":"deleteOrganizationsByIdMembersByUserId","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/organizations/{id}/users":{"get":{"tags":["Organizations"],"summary":"Search users not already members of the organization.","operationId":"getOrganizationsByIdUsers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"email":{"type":"string"},"avatar":{"type":"string"},"createdAt":{"type":"string"}}}},"total":{"type":"integer"},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}},"example":{"users":[{"id":"...","username":"...","displayName":"...","email":"...","avatar":"...","createdAt":"..."}],"total":1024,"pagination":{"limit":1000,"offset":0,"hasMore":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/push/register":{"post":{"tags":["Push Notifications"],"summary":"Body: { token: string, platform: \"ios\" | \"android\" }","operationId":"postPushRegister","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"platform":{"type":"string"}},"example":{"token":"<device-token>","platform":"ios"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"example":{"ok":true}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/push/unregister":{"delete":{"tags":["Push Notifications"],"summary":"Body: { token: string }","operationId":"deletePushUnregister","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"example":{"ok":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/stripe/create-checkout-session":{"post":{"tags":["Billing"],"summary":"POST /api/stripe/create-checkout-session","operationId":"postStripeCreateCheckoutSession","responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/stripe/create-portal-session":{"post":{"tags":["Billing"],"summary":"POST /api/stripe/create-portal-session","operationId":"postStripeCreatePortalSession","responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/test-db":{"get":{"tags":["Utility"],"summary":"Minimal, unauthenticated DB health probe.","operationId":"getTestDb","security":[],"responses":{"200":{"description":"Successful response."}}}},"/api/user":{"get":{"tags":["Users & Profile"],"summary":"Return the full profile of the currently authenticated user.","operationId":"getUser","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"avatar":{},"bio":{},"theme":{},"emailVerified":{"type":"boolean"},"pendingEmail":{},"maxMessageLength":{"type":"integer"},"defaultPubliclyVisible":{"type":"boolean"},"messagesPerPage":{"type":"integer"},"viewingPreference":{"type":"string"},"showPreviews":{"type":"boolean"},"showAdvancedPostSettings":{"type":"boolean"},"latitude":{},"longitude":{},"isPrivateAccount":{"type":"boolean"},"cleared":{"type":"boolean"},"githubDefaultRepo":{},"openaiApiKey":{},"anthropicApiKey":{},"customerStatus":{"type":"string"},"notificationTrayLimit":{"type":"integer"},"createdAt":{"type":"string"},"isAdministrator":{"type":"boolean"}}}},"example":{"user":{"id":"u1","email":"you@example.com","username":"you","displayName":"You","avatar":null,"bio":null,"theme":null,"emailVerified":true,"pendingEmail":null,"maxMessageLength":666,"defaultPubliclyVisible":false,"messagesPerPage":20,"viewingPreference":"all_messages","showPreviews":true,"showAdvancedPostSettings":false,"latitude":null,"longitude":null,"isPrivateAccount":false,"cleared":false,"githubDefaultRepo":null,"openaiApiKey":null,"anthropicApiKey":null,"customerStatus":"free","notificationTrayLimit":20,"createdAt":"2026-01-01T00:00:00.000Z","isAdministrator":false}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/avatar/from-url":{"post":{"tags":["Users & Profile"],"summary":"Fetch an image from a URL and store it as the user's avatar blob.","operationId":"postUserAvatarFromUrl","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://example.com/photo.jpg"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://vercel-blob.com/avatars/..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/avatar/upload":{"post":{"tags":["Users & Profile"],"summary":"Upload a new profile avatar.","operationId":"postUserAvatarUpload","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"}},"example":{"url":"https://vercel-blob.com/avatars/..."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/change-email/request":{"post":{"tags":["Users & Profile"],"summary":"Request an email address change.","operationId":"postUserChangeEmailRequest","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newEmail":{"type":"string"}},"example":{"newEmail":"new@example.com"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Verification email sent successfully. Check your inbox."}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/delete":{"post":{"tags":["Users & Profile"],"summary":"Delete the current user's account.","operationId":"postUserDelete","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string"},"email":{"type":"string"}},"example":{"username":"yourhandle","email":"you@example.com"}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"example":{"message":"Account deleted successfully"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/identities":{"get":{"tags":["Users & Profile"],"summary":"List all linked OAuth identities for the authenticated user.","operationId":"getUserIdentities","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"identities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"providerUsername":{"type":"string"},"profileUrl":{"type":"string"},"avatarUrl":{},"connectedAt":{"type":"string"},"lastVerifiedAt":{}}}}},"example":{"identities":[{"id":"li1","provider":"mastodon:mastodon.social","providerUsername":"you@mastodon.social","profileUrl":"https://mastodon.social/@you","avatarUrl":null,"connectedAt":"2026-01-01T00:00:00.000Z","lastVerifiedAt":null}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"delete":{"tags":["Users & Profile"],"summary":"Disconnect a linked OAuth identity.","operationId":"deleteUserIdentities","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"example":{"success":true}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/identities/verify":{"post":{"tags":["Users & Profile"],"summary":"Verify that the stored access token for a linked identity is still valid.","operationId":"postUserIdentitiesVerify","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string"}},"example":{"provider":"github"}}}}},"security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"example":{"success":true}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/notification-preferences":{"get":{"tags":["Users & Profile"],"summary":"Return the user's notification preferences as a list of events.","operationId":"getUserNotificationPreferences","responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"channels":{"type":"object","properties":{"push":{"type":"boolean"},"inApp":{"type":"boolean"}}}}}}},"example":{"events":[{"key":"dig","label":"Digs on your messages","description":"When someone presses “I Dig!” on one of your messages.","channels":{"push":true,"inApp":true}},{"key":"push","label":"Pushes of your messages","description":"When someone pushes (reposts) one of your messages, with or without commentary.","channels":{"push":true,"inApp":true}},{"key":"follow","label":"New followers & follow requests","description":"When someone follows you or requests to follow you.","channels":{"push":true}}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"patch":{"tags":["Users & Profile"],"summary":"Update the channel toggles for a single notification event.","operationId":"patchUserNotificationPreferences","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"channels":{"type":"object","properties":{"push":{"type":"boolean"},"inApp":{"type":"boolean"}}}},"example":{"key":"dig","channels":{"push":false,"inApp":true}}}}}},"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"channels":{"type":"object","properties":{"push":{"type":"boolean"},"inApp":{"type":"boolean"}}}},"example":{"key":"dig","label":"Digs on your messages","description":"When someone presses “I Dig!” on one of your messages.","channels":{"push":false,"inApp":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/organizations":{"get":{"tags":["Users & Profile"],"summary":"List all organizations the authenticated user belongs to.","operationId":"getUserOrganizations","security":[{"cookieAuth":[]}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Users & Profile"],"summary":"Join a public organization.","operationId":"postUserOrganizations","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string"}},"example":{"organizationId":"org1"}}}}},"security":[{"cookieAuth":[]}],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/update":{"patch":{"tags":["Users & Profile"],"summary":"Update profile and preference settings for the authenticated user.","operationId":"patchUserUpdate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string"},"bio":{"type":"string"},"avatar":{"type":"string"},"theme":{"type":"string"},"maxMessageLength":{"type":"integer"},"defaultPubliclyVisible":{"type":"boolean"},"messagesPerPage":{"type":"integer"},"viewingPreference":{"type":"string"},"showPreviews":{"type":"boolean"},"showAdvancedPostSettings":{"type":"boolean"},"latitude":{"type":"number"},"longitude":{"type":"number"},"isPrivateAccount":{"type":"boolean"},"githubDefaultRepo":{"type":"string"},"notificationTrayLimit":{"type":"integer"},"openaiApiKey":{},"anthropicApiKey":{}},"example":{"displayName":"New Name","bio":"About me","avatar":"https://...","theme":"dark","maxMessageLength":500,"defaultPubliclyVisible":true,"messagesPerPage":25,"viewingPreference":"following_only","showPreviews":true,"showAdvancedPostSettings":false,"latitude":47.6,"longitude":-122.3,"isPrivateAccount":false,"githubDefaultRepo":"owner/repo","notificationTrayLimit":20,"openaiApiKey":null,"anthropicApiKey":null}}}}},"responses":{"200":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/user/{username}/messages":{"get":{"tags":["Users & Profile"],"summary":"Get the public message wall for a user.","operationId":"getUserByUsernameMessages","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"responses":{"200":{"description":"Successful response."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/users/{username}/documents":{"get":{"tags":["Documents"],"summary":"Get public documents for a specific user by username","operationId":"getUsersByUsernameDocuments","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"folderId":{"type":"string"},"relativePath":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"folders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"parentId":{}}}}},"example":{"documents":[{"id":"doc1","title":"Public Notes","folderId":"f1","relativePath":"public-notes.md","createdAt":"2026-06-04T10:00:00.000Z","updatedAt":"2026-06-04T10:00:00.000Z"}],"folders":[{"id":"f1","name":"Public","parentId":null}]}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/users/{username}/lists":{"get":{"tags":["Lists"],"summary":"Get public lists for a specific user by username","operationId":"getUsersByUsernameLists","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"}],"security":[],"responses":{"200":{"description":"Successful response."},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/users/{username}/lists/{id}":{"get":{"tags":["Lists"],"summary":"Get public list metadata and ancestor chain for breadcrumbs.","operationId":"getUsersByUsernameListsById","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"parentId":{},"children":{"type":"array","items":{}}}},"ancestors":{"type":"array","items":{}}},"example":{"list":{"id":"list1","title":"...","parentId":null,"children":[]},"ancestors":[]}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/users/{username}/lists/{id}/data":{"get":{"tags":["Lists"],"summary":"Get list data rows for a public list with pagination, filtering, sorting.","operationId":"getUsersByUsernameListsByIdData","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[],"responses":{"200":{"description":"Successful response."},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/weather":{"get":{"tags":["Utility"],"summary":"US weather data from NOAA's api.weather.gov for a given lat/lon.","operationId":"getWeather","security":[],"responses":{"200":{"description":"Successful response.","content":{"application/json":{"schema":{"type":"object","properties":{"location":{"type":"string"},"temperature":{"type":"integer"},"condition":{"type":"string"},"conditionIcon":{"type":"string"},"high":{"type":"integer"},"low":{"type":"integer"},"humidity":{"type":"integer"},"windSpeed":{"type":"integer"},"timeZone":{"type":"string"},"hourly":{"type":"array","items":{"type":"object","properties":{"startTime":{"type":"string"},"temperature":{"type":"integer"},"probabilityOfPrecipitation":{"type":"integer"},"shortForecast":{"type":"string"}}}},"weekly":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"startTime":{"type":"string"},"isDaytime":{"type":"boolean"},"temperature":{"type":"integer"},"probabilityOfPrecipitation":{"type":"integer"},"shortForecast":{"type":"string"},"icon":{"type":"string"}}}}},"example":{"location":"Seattle","temperature":62,"condition":"Partly Sunny","conditionIcon":"bx-cloud","high":68,"low":54,"humidity":71,"windSpeed":5,"timeZone":"America/Los_Angeles","hourly":[{"startTime":"...","temperature":62,"probabilityOfPrecipitation":0,"shortForecast":"Partly Sunny"}],"weekly":[{"name":"Tonight","startTime":"...","isDaytime":false,"temperature":54,"probabilityOfPrecipitation":0,"shortForecast":"Mostly Cloudy","icon":"..."}]}}}}}}}},"/api/webhooks/resend":{"post":{"tags":["Webhooks & Cron"],"summary":"POST /api/webhooks/resend","operationId":"postWebhooksResend","description":"Signature-verified webhook. Not callable directly by clients.","security":[],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/webhooks/stripe":{"post":{"tags":["Webhooks & Cron"],"summary":"POST /api/webhooks/stripe","operationId":"postWebhooksStripe","description":"Signature-verified webhook. Not callable directly by clients.","security":[],"responses":{"201":{"description":"Successful response."},"400":{"$ref":"#/components/responses/BadRequest"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Sync token from POST /api/auth/sync-token, sent as `Authorization: Bearer <token>`."},"cookieAuth":{"type":"apiKey","in":"cookie","name":"interlinedlist-session","description":"Session cookie set by POST /api/auth/login."}},"parameters":{"limit":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50},"description":"Page size."},"offset":{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0},"description":"Items to skip."}},"responses":{"BadRequest":{"description":"Bad request — invalid or missing parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Not authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Forbidden — email not verified or subscriber feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"],"example":{"error":"Not authenticated"}},"Pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}