Query and Edit a SiYuan Knowledge Base via API with Hermes Agent
Query and edit a SiYuan knowledge base via its API.
Written by Neura Market from the official Hermes Agent documentation for Siyuan. Commands, paths, and version numbers are reproduced from the source unchanged.
Read the official documentationSiYuan Kernel API Reference
This reference documents how to interact with a self-hosted SiYuan knowledge base through its kernel API using curl. All operations are performed via POST requests with JSON bodies. The API enables full programmatic management of blocks, documents, and notebooks without a graphical interface.
Prerequisites
Before using the API, ensure SiYuan is installed and running (desktop or Docker). Obtain your API token from Settings > About > API token. Store the token and optionally the base URL in ${HERMES_HOME:-~/.hermes}/.env as shown below. The tools curl and jq should be installed for JSON processing.
SIYUAN_TOKEN=your_token_here
SIYUAN_URL=http://127.0.0.1:6806
If SIYUAN_URL is not set, the default http://127.0.0.1:6806 is used.
General API Call Structure
All API calls use the same pattern: a POST request with an Authorization header and a JSON body. The generic template is:
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/..." \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"param": "value"}'
A successful response has the structure:
{"code": 0, "msg": "", "data": { ... }}
Always check the code field: code: 0 means success. Any other value indicates an error; inspect the msg field for details. A non-zero code (code != 0) signals failure.
Search and Query
Full-Text Search
Search across all blocks using the endpoint /api/search/fullTextSearchBlock. Provide a query string and a 0-based page number. Results are in .data.blocks.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/search/fullTextSearchBlock" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "meeting notes", "page": 0}' | jq '.data.blocks[:5]'
SQL Query
Execute SELECT-only SQL statements against the blocks database using /api/query/sql. Useful columns include id, parent_id, root_id, box (notebook ID), path, content, type, subtype, created, and updated. Use LIMIT to control result size. Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/query/sql" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"stmt": "SELECT id, content, type, box FROM blocks WHERE content LIKE '\''%keyword%'\'' AND type='\''p'\'' LIMIT 20"}' | jq '.data'
Only SELECT statements are allowed. INSERT, UPDATE, DELETE, or DROP statements are dangerous and prohibited.
Reading Blocks and Documents
Read Block Content
Get the Kramdown content of a block using /api/block/getBlockKramdown. Provide the block id. Response data is in .data.kramdown.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/block/getBlockKramdown" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "20210808180117-6v0mkxr"}' | jq '.data.kramdown'
Read Child Blocks
Retrieve child blocks of a given block using /api/block/getChildBlocks. Provide the parent block id. Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/block/getChildBlocks" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "20210808180117-6v0mkxr"}' | jq '.data'
Get Human-Readable Path
Get the human-readable path for a block or document using /api/filetree/getHPathByID. Provide the block or document id. Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/filetree/getHPathByID" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "20210808180117-6v0mkxr"}' | jq '.data'
Get Block Attributes
Retrieve custom attributes of a block using /api/attr/getBlockAttrs. Provide the block id. Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/attr/getBlockAttrs" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "20210808180117-6v0mkxr"}' | jq '.data'
Managing Notebooks
List Notebooks
List all notebooks using /api/notebook/lsNotebooks. Response data is in .data.notebooks, each with id, name, and closed.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/notebook/lsNotebooks" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{}' | jq '.data.notebooks[] | {id, name, closed}'
List Documents in a Notebook
List documents in a notebook by path using /api/filetree/listDocsByPath. Provide notebook (notebook ID) and path (e.g., /). Response data is in .data.files, each with id and name.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/filetree/listDocsByPath" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"notebook": "NOTEBOOK_ID", "path": "/"}' | jq '.data.files[] | {id, name}'
Create a Notebook
Create a new notebook using /api/notebook/createNotebook. Provide a name. Response contains .data.notebook.id.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/notebook/createNotebook" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "My New Notebook"}' | jq '.data.notebook.id'
Delete a Notebook
Delete a notebook using /api/notebook/removeNotebook. Provide {"notebook": "NOTEBOOK_ID"}.
Managing Documents
Create a Document
Create a new document with initial Markdown content using /api/filetree/createDocWithMd. Provide notebook (notebook ID), path (document path, e.g., /Meeting Notes/2026-03-22), and markdown (initial content). Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/filetree/createDocWithMd" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"notebook": "NOTEBOOK_ID",
"path": "/Meeting Notes/2026-03-22",
"markdown": "# Meeting Notes\n\n- Discussed project timeline\n- Assigned tasks"
}' | jq '.data'
Rename a Document
Rename a document using /api/filetree/renameDocByID. Provide id (document ID) and title (new title).
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/filetree/renameDocByID" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "DOCUMENT_ID", "title": "New Title"}'
Delete a Document
Delete a document using /api/filetree/removeDocByID. Provide {"id": "DOC_ID"}.
Export Document as Markdown
Export a document's Markdown content using /api/export/exportMdContent. Provide the document id. Response data is in .data.content. Use jq -r to get the raw string.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/export/exportMdContent" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "DOCUMENT_ID"}' | jq -r '.data.content'
Block Operations
Append, Prepend, or Insert Blocks
Append a block to a parent using /api/block/appendBlock. Provide parentID (document or block ID), data (content string), and dataType (e.g., markdown). Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/block/appendBlock" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"parentID": "DOCUMENT_OR_BLOCK_ID",
"data": "New paragraph added at the end.",
"dataType": "markdown"
}' | jq '.data'
For inserting at the beginning, use /api/block/prependBlock with the same parameters (parentID, data, dataType). To insert after a specific sibling block, use /api/block/insertBlock with previousID instead of parentID.
Update Block Content
Update a block's content using /api/block/updateBlock. Provide id (block ID), data (new content), and dataType (e.g., markdown). Response data is in .data.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/block/updateBlock" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "BLOCK_ID",
"data": "Updated content here.",
"dataType": "markdown"
}' | jq '.data'
Set Block Attributes
Set custom attributes on a block using /api/attr/setBlockAttrs. Provide id (block ID) and attrs (object of key-value pairs). Keys must be prefixed with custom-.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/attr/setBlockAttrs" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "BLOCK_ID",
"attrs": {
"custom-status": "reviewed",
"custom-priority": "high"
}
}'
Delete a Block
Delete a single block using /api/block/deleteBlock. Provide the block id.
curl -s -X POST "${SIYUAN_URL:-http://127.0.0.1:6806}/api/block/deleteBlock" \
-H "Authorization: Token $SIYUAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "BLOCK_ID"}'
Constraints and Caveats
- All API calls must be POST with JSON bodies. GET requests are not supported.
- SQL queries must only be SELECT statements. Non-SELECT SQL may corrupt the database.
- Block IDs follow the pattern
YYYYMMDDHHmmss-xxxxxxx(14-digit timestamp + 7 alphanumeric characters). An example is20210808180117-6v0mkxr. - Custom attributes must be prefixed with
custom-. - Large documents may produce large responses. Use
LIMITin SQL and pipe throughjqto extract needed data. - Notebook IDs must be obtained via
lsNotebooksbefore use. - The API token must be stored in
${HERMES_HOME:-~/.hermes}/.envasSIYUAN_TOKEN. SIYUAN_URLdefaults tohttp://127.0.0.1:6806if not set.
Failure Modes
- A non-zero
codein the response indicates an error. Check themsgfield for details. - Using GET instead of POST will fail.
- Sending non-SELECT SQL statements may corrupt the database.
- Invalid block ID format will cause errors.
- Missing or incorrect API token results in authentication failure.
- Network issues or SiYuan not running will cause connection errors.
MCP Server Configuration
For integration with an MCP server, configure as follows in ~/.hermes/config.yaml:
# In ~/.hermes/config.yaml under mcp_servers:
mcp_servers:
siyuan:
command: npx
args: ["-y", "@porkll/siyuan-mcp"]
env:
SIYUAN_TOKEN: "your_token"
SIYUAN_URL: "http://127.0.0.1:6806"