Joplin API(中文)
/install joplin-api-china
Joplin Data API Skill
Access Joplin data via the local HTTP REST API (clipper server).
Architecture
Joplin data model:
Folders (笔记本/Notebooks) Notes (笔记)
├── 顶层笔记本 ├── 笔记属于某个 folder (parent_id → folder.id)
│ ├── 子笔记本 (parent_id→父ID) ├── 笔记内容是 Markdown 格式 (body 字段)
│ │ ├── 孙笔记本 └── 可附加标签(tags)、资源(resources)
│ │ │ └── ...无限层级
│ │ └── 孙笔记本
│ └── 子笔记本
└── 顶层笔记本
Key Concepts
- Folders(笔记本) = 目录/文件夹,通过
parent_id形成无限层级的树形结构。每个 folder 可以有任意多个子 folder,没有层级深度限制。顶级 folder 的parent_id为空或指向一个不在当前列表中的父 ID。 - Notes(笔记) = 内容载体,每条笔记通过
parent_id归属到一个且仅一个 folder 下。笔记内容是 Markdown 格式(body字段)。 - Tags(标签) = 跨笔记本的分类标记,可附加到任意笔记上,不受 folder 层级限制。
- Resources(资源) = 附件文件(图片、文档等),可关联到笔记上。
parent_id 关系说明
| 对象 | parent_id 含义 | 示例 |
|---|---|---|
| Folder | 指向父 folder ID;顶级 folder 为空/根 | parent_id: "abc123..." 表示该笔记本是 abc123... 的子目录 |
| Note | 指向所属 folder ID | parent_id: "folder_xyz" 表示该笔记在 folder_xyz 笔记本下 |
Configuration: Token Lifecycle
Token 存储在 OpenClaw 配置 skills.entries.joplin-api.env.JOPLIN_TOKEN。
每次操作 Joplin API 之前,必须按以下流程确认 token:
Step 0: 确认 Token(每次操作前必做)
# 从 OpenClaw 配置读取 token
_jtoken() {
python3 -c "import json; d=json.load(open('$HOME/.openclaw/openclaw.json')); print(d['skills']['entries']['joplin-api']['env'].get('JOPLIN_TOKEN', ''))"
}
TOKEN=$(_jtoken)
然后判断:
| 情况 | 动作 |
|---|---|
TOKEN 有值(非空字符串) |
→ 继续调用 API,用此 token |
TOKEN 为空 |
→ 问用户要 token(见下方提示文案) |
Token 缺失时的用户提示
当 token 为空时,告知用户以下内容:
Joplin API Token 尚未配置。请按以下步骤获取:
- 打开 Joplin 桌面端
- 进入 选项/偏好设置 → Web Clipper
- 找到 Access password(访问密码),这就是 token
- 把这段密码发给我,我会写入配置文件
同时请确认 Joplin Clipper Server 已启用(同一页面有开关)。
安全防护说明
本技能直接调用 Joplin 官方本地 REST API,具备完整的 CRUD 能力。为保护数据安全:
- 读取操作(GET):自由执行,无需批准
- 写入/删除操作(POST/PUT/DELETE):必须在用户明确确认后才执行
- 默认软删除:删除笔记默认移至回收站,除非用户明确要求永久删除
用户给出 Token 后:写入配置
# 将用户提供的 token 写入 OpenClaw 配置
_jset_token \x3CTOKEN_VALUE> {
python3 -c "
import json, sys
path = '$HOME/.openclaw/openclaw.json'
d = json.load(open(path))
d.setdefault('skills', {}).setdefault('entries', {}).setdefault('joplin-api', {}).setdefault('env', {})
d['skills']['entries']['joplin-api']['env']['JOPLIN_TOKEN'] = sys.argv[1]
json.dump(d, open(path, 'w'), indent=2)
print('Token saved.')
" "$1"
}
写入完成后向用户确认 "Token 已保存,下次操作自动使用。"
后续每次操作
重复 Step 0:先读配置确认 token → 有值则用,无值则再问。
Base URL: http://localhost:41184
Verify service:
curl -s http://localhost:41184/ping
# Expected: "JoplinClipperServer"
完整操作示例(含 token 确认)
# 1. 确认 token
TOKEN=$(python3 -c "import json; d=json.load(open('$HOME/.openclaw/openclaw.json')); print(d['skills']['entries']['joplin-api']['env'].get('JOPLIN_TOKEN', ''))")
# 2. 检查是否有值
if [ -z "$TOKEN" ]; then
echo "TOKEN_MISSING"
fi
# 3. 有 token 则调用 API
curl -s "http://localhost:41184/notes?token=$TOKEN&limit=5" | jq .
Workflow: Search for a Topic
The recommended workflow to find content about a topic:
Step 1: Find relevant notebooks (folders)
# Search folders by title (case-insensitive, supports * wildcard)
curl -s "$JOPLIN_BASE/search?query=r730&type=folder&token=$JOPLIN_TOKEN" | jq .
Step 2: List notes inside a notebook
# Get all notes in a specific folder
curl -s "$JOPLIN_BASE/folders/FOLDER_ID/notes?token=$JOPLIN_TOKEN&fields=id,title,updated_time&limit=50" | jq .
Step 3: Read note content
# Get note body (Markdown)
curl -s "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN&fields=id,title,body" | jq .
Alternative: Full-text search across all notes
# Search notes by keyword (full-text, returns id/title only for speed)
curl -s "$JOPLIN_BASE/search?query=r730+购买&token=$JOPLIN_TOKEN&fields=id,title" | jq .
# Then read the matching note
curl -s "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN&fields=body" | jq .
Tip: When searching with
bodyfield, response can be large. Search withid,titlefirst, then fetchbodyfor the specific note you want.
Folder Hierarchy Operations
List all folders (flat list with parent_id)
# Returns flat list; use parent_id to reconstruct tree
curl -s "$JOPLIN_BASE/folders?token=$JOPLIN_TOKEN&fields=id,title,parent_id" | jq .
Each folder has:
id— folder IDtitle— folder nameparent_id— parent folder ID (empty/null = top-level)deleted_time— 0 = active, >0 = soft-deleted
Reconstruct folder tree in code
# Get all folders and build tree structure
curl -s "$JOPLIN_BASE/folders?token=$JOPLIN_TOKEN&fields=id,title,parent_id" | python3 -c "
import sys, json
folders = json.load(sys.stdin)
if isinstance(folders, dict):
folders = folders.get('items', folders)
# Build lookup
by_id = {f['id']: f for f in folders if f.get('deleted_time', 0) == 0}
# Attach children
for f in by_id.values():
pid = f.get('parent_id', '')
if pid and pid in by_id:
by_id[pid].setdefault('children', []).append(f)
# Print tree (top-level only parents)
def show(items, indent=0):
for item in sorted(items, key=lambda x: x['title']):
print(' ' * indent + f'[{item[\"id\"][:8]}] {item[\"title\"]}')
show(item.get('children', []), indent + 1)
roots = [f for f in by_id.values() if not f.get('parent_id') or f['parent_id'] not in by_id]
show(roots)
"
Find folder ID by name
# Search for a notebook by title
curl -s "$JOPLIN_BASE/search?query=r730&type=folder&token=$JOPLIN_TOKEN&fields=id,title,parent_id" | jq .
Note Operations
List notes in a folder
curl -s "$JOPLIN_BASE/folders/FOLDER_ID/notes?token=$JOPLIN_TOKEN&limit=100&order_by=updated_time&order_dir=DESC&fields=id,title,updated_time" | jq .
Read note content
# Title + body only
curl -s "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN&fields=id,title,body" | jq .
# With metadata
curl -s "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN&fields=id,title,body,parent_id,created_time,updated_time" | jq .
Create note (POST /notes) — ⚠️ 高影响操作,需用户明确批准
在执行前向用户展示将要创建的笔记标题、内容和目标笔记本,获得确认后再执行:
# 预览后执行
curl -s -X POST "$JOPLIN_BASE/notes?token=$JOPLIN_TOKEN" \
--data '{"title":"Title","body":"Markdown content","parent_id":"FOLDER_ID"}' | jq .
Update note (PUT /notes/:id) — ⚠️ 高影响操作,需用户明确批准
在执行前向用户展示将要修改的笔记标题、当前内容摘要和拟修改内容,获得确认后再执行:
# 预览后执行
curl -s -X PUT "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN" \
--data '{"title":"New Title"}' | jq .
Delete note (DELETE /notes/:id) — ⚠️ 高影响操作,需用户明确批准
默认行为:移至回收站(软删除),用户可恢复。
除非用户明确请求永久删除,否则不使用 permanent=1。
# 移至回收站(默认,可恢复)
curl -s -X DELETE "$JOPLIN_BASE/notes/NOTE_ID?token=$JOPLIN_TOKEN" | jq .
执行前必须:
- 展示目标笔记的标题和 ID
- 说明操作后果(移至回收站 / 永久删除)
- 获得用户明确确认后再执行
Note tags & resources
# Tags on a note
curl -s "$JOPLIN_BASE/notes/NOTE_ID/tags?token=$JOPLIN_TOKEN" | jq .
# Resources (attachments) on a note
curl -s "$JOPLIN_BASE/notes/NOTE_ID/resources?token=$JOPLIN_TOKEN" | jq .
Tag Operations
# List all tags
curl -s "$JOPLIN_BASE/tags?token=$JOPLIN_TOKEN&fields=id,title" | jq .
# Search tags (supports * wildcard)
curl -s "$JOPLIN_BASE/search?query=project-*&type=tag&token=$JOPLIN_TOKEN" | jq .
# Notes with a specific tag
curl -s "$JOPLIN_BASE/tags/TAG_ID/notes?token=$JOPLIN_TOKEN" | jq .
Pagination
All list endpoints return { "items": [...], "has_more": true/false }.
# Page 2
curl -s "$JOPLIN_BASE/notes?token=$JOPLIN_TOKEN&limit=10&page=2" | jq .
Parameters: page (starts at 1), limit (max 100), order_by, order_dir (ASC/DESC).
Data Types
- Text: UTF-8
- Dates/times: Unix timestamps in milliseconds
- Booleans: Integer
0or1 deleted_time:0= active,>0= soft-deleted
Iron Rules(铁律)
- 每次操作前先确认 token — 从配置读取 → 有值则用 → 无值则问用户 → 用户给出后写入配置 → 下次再确认
- GET free — 读取笔记、笔记本、标签可自由执行,无需额外批准
- 写/删操作必须经过用户明确批准 — POST(创建)、PUT(更新)、DELETE(删除)均为高影响操作:
- 创建:展示标题、内容摘要、目标笔记本,确认后再执行
- 更新:展示笔记标题、当前内容摘要、拟修改内容,确认后再执行
- 删除:展示笔记标题和 ID,说明操作后果(移至回收站/永久删除),确认后再执行
- 默认软删除 — 删除笔记时默认移至回收站(可恢复);除非用户明确说"永久删除",否则不加
permanent=1 - Search without body first — 搜索时用
fields=id,title提速,找到目标后再获取body - Use parent_id for hierarchy — folders 和 notes 都通过
parent_id构建树形关系
See references/api-docs.md for the complete API reference (all endpoints, properties, error handling).
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install joplin-api-china - After installation, invoke the skill by name or use
/joplin-api-china - Provide required inputs per the skill's parameter spec and get structured output
What is Joplin API(中文)?
通过 Joplin 官方本地 Data API(Clipper Server,端口 41184)查询和管理笔记、笔记本、标签。本技能仅对原始 Joplin REST API 做了 AI 调用引导和中文交互封装,不引入第三方服务,所有请求直连本机 Joplin 实例。触发词:"查 Joplin... It is an AI Agent Skill for Claude Code / OpenClaw, with 138 downloads so far.
How do I install Joplin API(中文)?
Run "/install joplin-api-china" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Joplin API(中文) free?
Yes, Joplin API(中文) is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Joplin API(中文) support?
Joplin API(中文) is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Joplin API(中文)?
It is built and maintained by yangyangupday (@yangyangupday); the current version is v1.1.0.