← Back to Skills Marketplace
imchongliu

Dida365 滴答清单 (Open API)

by imchongliu · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
138
Downloads
1
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install dida365-api
Description
滴答清单 (Dida365) API 集成,支持自建 OAuth 认证。管理任务和项目。 当用户想要在滴答清单中创建、更新、完成或组织任务和项目时使用此 Skill。 需要用户在 developer.dida365.com 创建应用并配置 DIDA365_CLIENT_ID、DIDA365_CLIENT_SECR...
README (SKILL.md)

Dida365 滴答清单

通过 Dida365 官方 OAuth 认证访问滴答清单 API,支持任务和项目的完整 CRUD 操作。

前置准备

1. 创建 Dida365 开发者应用

  1. 登录 developer.dida365.com
  2. 点击「创建应用」
  3. 填写应用名称(任意)
  4. 在「回调地址 (Redirect URI)」中添加:http://127.0.0.1:36500/callback
  5. 创建完成后,记录下 Client IDClient Secret

2. 配置环境变量

export DIDA365_CLIENT_ID="YOUR_CLIENT_ID"
export DIDA365_CLIENT_SECRET="YOUR_CLIENT_SECRET"

建议将上述配置写入 ~/.bashrc~/.zshrc.env 文件。

获取 Access Token

首次使用需要通过 OAuth 授权获取 Access Token。以下流程会启动一个临时本地服务来接收回调。

一键获取 Token(Python)

python3 \x3C\x3C 'PYEOF'
import os, json, http.server, urllib.parse, urllib.request, threading, webbrowser

CLIENT_ID = os.environ["DIDA365_CLIENT_ID"]
CLIENT_SECRET = os.environ["DIDA365_CLIENT_SECRET"]
REDIRECT_URI = "http://127.0.0.1:36500/callback"
TOKEN_FILE = os.path.expanduser("~/.config/dida365/token")
code_holder = {}

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        params = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
        if "code" in params:
            code_holder["code"] = params["code"][0]
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b"Authorization successful! You can close this tab.")
        else:
            self.send_response(400)
            self.end_headers()
            self.wfile.write(b"Missing code parameter.")
    def log_message(self, *args): pass

server = http.server.HTTPServer(("127.0.0.1", 36500), Handler)
thread = threading.Thread(target=server.handle_request)
thread.start()

auth_url = (
    f"https://dida365.com/oauth/authorize"
    f"?client_id={CLIENT_ID}"
    f"&scope=tasks%3Aread+tasks%3Awrite"
    f"&state=random_state_string"
    f"&redirect_uri={urllib.parse.quote(REDIRECT_URI, safe='')}"
    f"&response_type=code"
)
print(f"请在浏览器中打开以下链接并点击授权:\
\
{auth_url}\
")
webbrowser.open(auth_url)

thread.join(timeout=120)
server.server_close()

if "code" not in code_holder:
    print("❌ 超时:未收到授权码,请重试。")
    exit(1)

code = code_holder["code"]
print(f"✅ 已获取授权码,正在交换 Token...")

data = urllib.parse.urlencode({
    "client_id": CLIENT_ID,
    "client_secret": CLIENT_SECRET,
    "code": code,
    "grant_type": "authorization_code",
    "redirect_uri": REDIRECT_URI,
}).encode()

req = urllib.request.Request(
    "https://dida365.com/oauth/token",
    data=data,
    method="POST"
)
req.add_header("Content-Type", "application/x-www-form-urlencoded")
resp = json.load(urllib.request.urlopen(req))
token = resp["access_token"]

os.makedirs(os.path.dirname(TOKEN_FILE), exist_ok=True)
with open(TOKEN_FILE, "w") as f:
    json.dump({"access_token": token}, f)
os.chmod(TOKEN_FILE, 0o600)

print(f"✅ Token 已保存到 {TOKEN_FILE}")
print(f"   有效期约 180 天,请注意及时重新授权。")
PYEOF

Token 存储

Token 保存在 ~/.config/dida365/token,格式:

{
  "access_token": "your_access_token_here"
}

⚠️ 重要提示:

  • Token 有效期约 180 天
  • 滴答清单当前 API 没有 refresh_token 机制
  • Token 过期后需重新执行上述授权流程
  • 请妥善保管 Token 文件,不要提交到版本控制系统

Base URL

https://api.dida365.com/open/v1/

认证

所有请求需要在 Authorization 头中携带 Access Token:

Authorization: Bearer {ACCESS_TOKEN}

快速测试

# 读取 Token 并列出项目
python3 \x3C\x3C 'PYEOF'
import os, json, urllib.request

token_file = os.path.expanduser("~/.config/dida365/token")
with open(token_file) as f:
    token = json.load(f)["access_token"]

req = urllib.request.Request("https://api.dida365.com/open/v1/project")
req.add_header("Authorization", f"Bearer {token}")
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2, ensure_ascii=False))
PYEOF

API 参考

项目操作

列出所有项目

GET /open/v1/project

响应示例:

[
  {
    "id": "6984773291819e6d58b746a8",
    "name": "📝 收集箱",
    "sortOrder": 0,
    "viewMode": "list",
    "kind": "TASK"
  },
  {
    "id": "6984773291819e6d58b746a9",
    "name": "🏠 个人",
    "sortOrder": -1099511627776,
    "viewMode": "list",
    "kind": "TASK"
  }
]

获取项目及任务

GET /open/v1/project/{projectId}/data

响应示例:

{
  "project": {
    "id": "69847732b8e5e969f70e7460",
    "name": "📋 工作",
    "sortOrder": -3298534883328,
    "viewMode": "list",
    "kind": "TASK"
  },
  "tasks": [
    {
      "id": "69847732b8e5e969f70e7464",
      "projectId": "69847732b8e5e969f70e7460",
      "title": "完成报告",
      "content": "季度总结报告",
      "priority": 0,
      "status": 0,
      "tags": [],
      "isAllDay": false
    }
  ],
  "columns": [
    {
      "id": "69847732b8e5e969f70e7463",
      "projectId": "69847732b8e5e969f70e7460",
      "name": "待办",
      "sortOrder": -2199023255552
    }
  ]
}

创建项目

POST /open/v1/project
Content-Type: application/json

{
  "name": "我的新项目",
  "viewMode": "list"
}

响应示例:

{
  "id": "69870cbe8f08b4a6770a38d3",
  "name": "我的新项目",
  "sortOrder": 0,
  "viewMode": "list",
  "kind": "TASK"
}

viewMode 选项:

  • list - 列表视图
  • kanban - 看板视图
  • timeline - 时间线视图

删除项目

DELETE /open/v1/project/{projectId}

成功时返回空响应(状态码 200)。

任务操作

获取任务

GET /open/v1/project/{projectId}/task/{taskId}

响应示例:

{
  "id": "69847732b8e5e969f70e7464",
  "projectId": "69847732b8e5e969f70e7460",
  "sortOrder": -1099511627776,
  "title": "任务标题",
  "content": "任务描述/备注",
  "timeZone": "Asia/Shanghai",
  "isAllDay": true,
  "priority": 0,
  "status": 0,
  "tags": [],
  "columnId": "69847732b8e5e969f70e7461",
  "etag": "2sayfdsh",
  "kind": "TEXT"
}

创建任务

POST /open/v1/task
Content-Type: application/json

{
  "title": "新任务",
  "projectId": "6984773291819e6d58b746a8",
  "content": "任务描述",
  "priority": 0,
  "dueDate": "2026-03-15T10:00:00+0000",
  "isAllDay": false
}

响应示例:

{
  "id": "69870cb08f08b86b38951175",
  "projectId": "6984773291819e6d58b746a8",
  "sortOrder": -1099511627776,
  "title": "新任务",
  "timeZone": "Asia/Shanghai",
  "isAllDay": false,
  "priority": 0,
  "status": 0,
  "tags": [],
  "etag": "gl7ibhor",
  "kind": "TEXT"
}

优先级值:

  • 0 - 无
  • 1 - 低
  • 3 - 中
  • 5 - 高

更新任务

POST /open/v1/task/{id}
Content-Type: application/json

{
  "id": "69870cb08f08b86b38951175",
  "projectId": "6984773291819e6d58b746a8",
  "title": "更新后的任务标题",
  "priority": 1
}

响应示例:

{
  "id": "69870cb08f08b86b38951175",
  "projectId": "6984773291819e6d58b746a8",
  "title": "更新后的任务标题",
  "priority": 1,
  "status": 0,
  "etag": "hmb7uk8c",
  "kind": "TEXT"
}

完成任务

POST /open/v1/project/{projectId}/task/{taskId}/complete

成功时返回空响应(状态码 200)。

删除任务

DELETE /open/v1/project/{projectId}/task/{taskId}

成功时返回空响应(状态码 200)。

任务字段说明

字段 类型 说明
id string 任务 ID
projectId string 所属项目 ID
title string 任务标题
content string 任务描述/备注(支持 Markdown)
priority integer 优先级:0=无, 1=低, 3=中, 5=高
status integer 状态:0=进行中, 2=已完成
dueDate string 截止日期(ISO 8601 格式)
startDate string 开始日期(ISO 8601 格式)
isAllDay boolean 是否全天任务
timeZone string 时区(如 "Asia/Shanghai")
tags array 标签列表
columnId string 看板列 ID(看板视图时使用)
sortOrder number 项目内的排序
kind string 任务类型:"TEXT"、"CHECKLIST"

代码示例

Python(requests)

import os, json

# 读取 Token
with open(os.path.expanduser("~/.config/dida365/token")) as f:
    token = json.load(f)["access_token"]

headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json"
}

# 列出所有项目
import requests
resp = requests.get("https://api.dida365.com/open/v1/project", headers=headers)
projects = resp.json()
print(json.dumps(projects, indent=2, ensure_ascii=False))

# 创建任务
resp = requests.post("https://api.dida365.com/open/v1/task", headers=headers, json={
    "title": "新任务",
    "projectId": "YOUR_PROJECT_ID",
    "content": "通过 API 创建的任务",
    "priority": 3,
    "dueDate": "2026-04-01T09:00:00+0800"
})
print(resp.json())

# 完成任务
resp = requests.post(
    "https://api.dida365.com/open/v1/project/YOUR_PROJECT_ID/task/TASK_ID/complete",
    headers=headers
)
print(f"状态: {resp.status_code}")

JavaScript(fetch)

import { readFileSync } from "fs";

// 读取 Token
const { access_token: token } = JSON.parse(
  readFileSync(process.env.HOME + "/.config/dida365/token", "utf-8")
);

const headers = {
  Authorization: `Bearer ${token}`,
  "Content-Type": "application/json",
};

// 列出所有项目
const projects = await fetch("https://api.dida365.com/open/v1/project", {
  headers,
}).then((r) => r.json());
console.log(projects);

// 创建任务
const task = await fetch("https://api.dida365.com/open/v1/task", {
  method: "POST",
  headers,
  body: JSON.stringify({
    title: "新任务",
    projectId: "YOUR_PROJECT_ID",
    content: "通过 API 创建的任务",
    priority: 3,
  }),
}).then((r) => r.json());
console.log(task);

// 完成任务
await fetch(
  `https://api.dida365.com/open/v1/project/YOUR_PROJECT_ID/task/TASK_ID/complete`,
  { method: "POST", headers }
);

curl 示例

# 读取 Token
TOKEN=$(cat ~/.config/dida365/token | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# 列出项目
curl -s -H "Authorization: Bearer $TOKEN" https://api.dida365.com/open/v1/project | python3 -m json.tool

# 创建任务
curl -s -X POST https://api.dida365.com/open/v1/task \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"测试任务","projectId":"YOUR_PROJECT_ID"}' | python3 -m json.tool

注意事项

  • Open API 仅提供任务和项目的访问
  • 习惯、专注/番茄钟等功能不通过 Open API 提供
  • 任务 status 值:0 = 进行中,2 = 已完成
  • 优先级值:0 = 无,1 = 低,3 = 中,5 = 高
  • 日期使用 ISO 8601 格式带时区偏移(如 2026-03-15T10:00:00+0800
  • 项目的 viewMode 选项:listkanbantimeline
  • columns 字段用于看板视图的列定义
  • Token 有效期约 180 天,无 refresh_token,过期需重新授权

错误处理

状态码 含义 处理方式
400 请求参数错误 检查请求体格式和必填字段
401 Token 无效或已过期 重新执行 OAuth 授权流程获取新 Token
404 资源未找到 确认项目 ID / 任务 ID 是否正确
429 请求频率超限 降低请求频率,等待后重试
5xx 服务端错误 稍后重试

故障排除

Token 过期(401 错误):

# 重新运行授权脚本获取新 Token
# 参考上方「获取 Access Token」章节

检查 Token 有效性:

TOKEN=$(cat ~/.config/dida365/token | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $TOKEN" https://api.dida365.com/open/v1/project
# 返回 200 表示有效,返回 401 表示已过期

环境变量未设置:

echo $DIDA365_CLIENT_ID
echo $DIDA365_CLIENT_SECRET

资源

Usage Guidance
This skill is internally consistent for integrating with Dida365, but take these practical precautions before installing: 1) Only provide DIDA365_CLIENT_ID and DIDA365_CLIENT_SECRET if you trust the skill source — this package has no homepage/source URL in the metadata. 2) The OAuth flow stores a long-lived access token (~180 days) at ~/.config/dida365/token; protect that file (permissions are set to 600 in the example) and do not commit it to version control. 3) Because there is no refresh token, you will need to re-authorize when the token expires. 4) The runtime instructions will cause the agent (or you running the snippet) to open a browser and start a local listener on 127.0.0.1:36500 — ensure that port/redirect URI are acceptable for you. 5) Avoid pasting client secrets or access tokens into third-party chats; if you are unsure of the registry publisher (owner ID present but no homepage), consider manually following the SKILL.md steps yourself rather than granting the agent autonomous access. If you want higher assurance, request a skill package with a verifiable source or an install spec from an official repository.
Capability Analysis
Type: OpenClaw Skill Name: dida365-api Version: 1.0.0 The skill provides a standard integration for the Dida365 (TickTick) API. It includes a Python setup script in SKILL.md to handle the OAuth 2.0 flow, which runs a local server to capture the authorization code and exchanges it for a token via the official dida365.com endpoint. The token is stored locally at ~/.config/dida365/token with appropriate file permissions (0600), and no evidence of data exfiltration or malicious command execution was found.
Capability Assessment
Purpose & Capability
Name/description match the required environment variables (DIDA365_CLIENT_ID, DIDA365_CLIENT_SECRET) and the SKILL.md exclusively documents OAuth + API calls to dida365 endpoints — the requested secrets are exactly what an OAuth integration needs.
Instruction Scope
Instructions are limited to: creating a developer app, running a local temporary HTTP listener for OAuth callback, exchanging code for an access token, saving the token to ~/.config/dida365/token, and making API requests with that token. They do not ask to read unrelated system files, other credentials, or to exfiltrate data to third-party endpoints.
Install Mechanism
No install spec or external downloads — this is instruction-only. Nothing will be written to disk by an installer beyond the token file the script itself creates under the user's home directory.
Credentials
Only DIDA365_CLIENT_ID and DIDA365_CLIENT_SECRET are required, which are proportionate for an OAuth integration. The skill also stores an access token in ~/.config/dida365/token (documented) — expected for this workflow.
Persistence & Privilege
always:false and default autonomous invocation are used (normal). The skill does not request system-wide config changes or access to other skills' settings; it only writes/reads its own token file.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install dida365-api
  3. After installation, invoke the skill by name or use /dida365-api
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release: Self-hosted OAuth via official Dida365 Open API, full task/project CRUD
Metadata
Slug dida365-api
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Dida365 滴答清单 (Open API)?

滴答清单 (Dida365) API 集成,支持自建 OAuth 认证。管理任务和项目。 当用户想要在滴答清单中创建、更新、完成或组织任务和项目时使用此 Skill。 需要用户在 developer.dida365.com 创建应用并配置 DIDA365_CLIENT_ID、DIDA365_CLIENT_SECR... It is an AI Agent Skill for Claude Code / OpenClaw, with 138 downloads so far.

How do I install Dida365 滴答清单 (Open API)?

Run "/install dida365-api" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Dida365 滴答清单 (Open API) free?

Yes, Dida365 滴答清单 (Open API) is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Dida365 滴答清单 (Open API) support?

Dida365 滴答清单 (Open API) is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Dida365 滴答清单 (Open API)?

It is built and maintained by imchongliu (@imchongliu); the current version is v1.0.0.

💬 Comments