Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Query and edit a SiYuan knowledge base via its API.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | 66% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 89% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 195% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 117% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 142% | 0% |
Use the SiYuan kernel API via curl to search, read, create, update, and delete blocks and documents in a self-hosted knowledge base. No extra tools needed -- just curl and an API token.
${HERMES_HOME:-~/.hermes}/.env: SIYUAN_TOKEN=your_token_here SIYUAN_URL=http://127.0.0.1:6806 SIYUAN_URL defaults to http://127.0.0.1:6806 if not set.
All SiYuan API calls are POST with JSON body. Every request follows this pattern:
bashcurl -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"}'
Responses are JSON with this structure:
json{"code": 0, "msg": "", "data": { ... }}
code: 0 means success. Any other value is an error -- check msg for details.
ID format: SiYuan IDs look like 20210808180117-6v0mkxr (14-digit timestamp + 7 alphanumeric chars).
| Operation | Endpoint | |-----------|----------| | Full-text search | /api/search/fullTextSearchBlock | | SQL query | /api/query/sql | | Read block | /api/block/getBlockKramdown | | Read children | /api/block/getChildBlocks | | Get path | /api/filetree/getHPathByID | | Get attributes | /api/attr/getBlockAttrs | | List notebooks | /api/notebook/lsNotebooks | | List documents | /api/filetree/listDocsByPath | | Create notebook | /api/notebook/createNotebook | | Create document | /api/filetree/createDocWithMd | | Append block | /api/block/appendBlock | | Update block | /api/block/updateBlock | | Rename document | /api/filetree/renameDocByID | | Set attributes | /api/attr/setBlockAttrs | | Delete block | /api/block/deleteBlock | | Delete document | /api/filetree/removeDocByID | | Export as Markdown | /api/export/exportMdContent |
bashcurl -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]'
Query the blocks database directly. Only SELECT statements are safe.
bashcurl -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'
Useful columns: id, parent_id, root_id, box (notebook ID), path, content, type, subtype, created, updated.
Returns block content in Kramdown (Markdown-like) format.
bashcurl -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'
bashcurl -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'
bashcurl -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'
bashcurl -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'
bashcurl -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}'
bashcurl -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}'
bashcurl -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'
bashcurl -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'
bashcurl -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'
Also available: /api/block/prependBlock (same params, inserts at the beginning) and /api/block/insertBlock (uses previousID instead of parentID to insert after a specific block).
bashcurl -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'
bashcurl -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"}'
Custom attributes must be prefixed with custom-:
bashcurl -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" } }'
bashcurl -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"}'
To delete a whole document: use /api/filetree/removeDocByID with {"id": "DOC_ID"}. To delete a notebook: use /api/notebook/removeNotebook with {"notebook": "NOTEBOOK_ID"}.
bashcurl -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'
Common type values in SQL queries:
| Type | Description | |------|-------------| | d | Document (root block) | | p | Paragraph | | h | Heading | | l | List | | i | List item | | c | Code block | | m | Math block | | t | Table | | b | Blockquote | | s | Super block | | html | HTML block |
YYYYMMDDHHmmss-xxxxxxx. Reject anything else.code != 0 in responses before processing data.LIMIT in SQL and pipe through jq to extract only what you need.lsNotebooks.If you prefer a native integration instead of curl, install the SiYuan MCP server:
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"
Other measured skills in the registry, with their headline benchmark lift.