This document describes the LogSeq HTTP API architecture based on source code analysis and practical testing.
The LogSeq HTTP API runs on localhost:12315 (default) and acts as a proxy to LogSeq's internal plugin API methods. It bridges external applications to LogSeq's core functionality through JSON-RPC calls.
- Base URL:
http://localhost:12315 - API Endpoint:
POST /api - Authentication: Bearer token required in Authorization header
- Content-Type:
application/json
{
"method": "logseq.Namespace.methodName",
"args": [arg1, arg2, ...]
}Standard JSON-RPC response with result or error.
- HTTP request hits
/apiendpoint (server.cljs:142) - Authentication validated via Bearer token (
server.cljs:74-81) - Method name resolved and mapped (
server.cljs:62-72) - Call forwarded to renderer process via IPC (
server.cljs:97-104) - Plugin API method executed in LogSeq context
- Result returned through the chain
- API methods follow pattern:
logseq.Namespace.methodName - Converted to snake_case internally (e.g.,
createPage→create_page) - Special namespaces:
ui,git,assetsget_suffix
-
createPage(pageName, properties, options)- Creates new page with optional properties
- Options:
{createFirstBlock: true}creates initial empty block - Example:
["My Page", {}, {"createFirstBlock": true}]
-
appendBlockInPage(pageName, content)- Adds content block to existing page
- Example:
["My Page", "This is content"]
-
insertBlock(targetBlockUUID, content, options)- Inserts a new block relative to an existing block
- Options:
{sibling: false, properties: {...}} sibling: falseinserts as child (default)sibling: trueinserts as sibling after target- Example:
["parent-block-uuid-123", "Child content", {"sibling": false, "properties": {}}]
-
getAllPages()- Returns array of all page objects with metadata
- Each page includes: name, properties, journal status, etc.
-
getPage(pageName)- Returns page object with basic metadata
- Does not include block content
-
getPageBlocksTree(pageName)- Returns hierarchical block structure for page
- Each block includes: content, properties, children, etc.
deletePage(pageName)- Delete page entirelyupdatePage(pageName, properties)- Update page propertiesupdateBlock(blockUUID, content)- Update specific block contentremoveBlock(blockUUID)- Delete specific block
getCurrentGraph()- Get current graph infogetGraphs()- List available graphs (potentially)
getPageProperties(pageName)- Get page properties (may not exist in all versions)setPageProperties(pageName, properties)- Set page properties
- Tokens stored in LogSeq config:
:server/tokens - Can be array of token objects:
[{:value "token123", ...}, ...] - Or simple strings:
["token123", "token456"] - Bearer token stripped of "Bearer " prefix before validation
Generated in LogSeq Settings → Features → HTTP APIs server
- 401 Unauthorized: Invalid or missing Bearer token
- 400 Bad Request: Missing or invalid method name
- 404 Method Not Found: API method doesn't exist (
MethodNotExist) - 500 Internal Error: LogSeq internal errors
{
"error": {
"message": "Error description",
"code": "ERROR_CODE"
}
}- No direct search endpoints available
- Would require expensive page-by-page iteration:
- Get all pages via
getAllPages() - Get content for each via
getPageBlocksTree() - Search content client-side
- Get all pages via
- Recommendation: Avoid implementing search through HTTP API
- HTTP API limited to methods exposed to plugin system
- Not all internal LogSeq functions available
- Some advanced operations may require direct database access
LOGSEQ_API_TOKEN: Bearer token for authenticationLOGSEQ_API_URL: API base URL (default:http://localhost:12315)
- LogSeq application running
- "Enable HTTP APIs server" checked in Settings → Features
- Valid API token generated
For complete page content, combine multiple API calls:
getPage(pageName)- Get page metadatagetPageBlocksTree(pageName)- Get content blocksgetPageProperties(pageName)- Get properties (if available)
Blocks returned by getPageBlocksTree() can be:
- Dictionary objects:
{"content": "text", "children": [...], ...} - Simple strings:
"plain text content" - Empty/null values for placeholder blocks
To create page with content:
createPage(pageName, {}, {"createFirstBlock": true})appendBlockInPage(pageName, content)(if content needed)
To create hierarchical block structures:
- Create parent block:
appendBlockInPage(pageName, "Parent content") - Get parent block UUID from the returned block data
- Insert child:
insertBlock(parentBlockUUID, "Child content", {"sibling": false}) - Insert another child:
insertBlock(parentBlockUUID, "Second child", {"sibling": false}) - Insert sibling:
insertBlock(parentBlockUUID, "Sibling content", {"sibling": true})
Block hierarchy example:
- Parent block
- Child block 1
- Child block 2
- Sibling block
15 tools implemented. Block CRUD is complete:
| Operation | Tool | Status |
|---|---|---|
| Read | get_page_content |
✅ |
| Create | insert_nested_block |
✅ |
| Delete | delete_block |
✅ |
| Update | update_block |
✅ |
- Graph context (
logseq.App.getCurrentGraph) — Expose which graph is active. Low effort, useful for multi-graph setups. - Advanced property management — Set block-level properties directly (
logseq.Editor.setBlockProperties). Currently only page properties are writable. Asset/file operations via— Not useful for AI assistant context.logseq.Assets.*UI interaction via— UI automation from AI is fragile; not worth pursuing.logseq.UI.*Git operations via— Too niche (requires Logseq's built-in git sync).logseq.Git.*
Last Updated: 2026-02-24 Based on LogSeq source analysis and MCP server implementation