跳到主要内容

Webhook 自动化

Basic 及以上

自动化需要 Basic 及以上套餐。Basic:1 个自动化,Pro:3 个,Ultra:10 个。在 Free 上,这一行会显示升级以解锁自动化。

webhook 是一个能自动接收数据的网址。有了自动化,笔记一处理好,TellDone 就会把这条笔记连同它的任务和事件发送到该网址;每份新报告生成好后,也会发送,这样 Zapier、Make 或 n8n 等工具就可以据此执行操作。每个任务和每个事件都会作为单独的一次发送。

选择发送内容​

每个自动化在发送内容下都有各自的设置。可以选一项,也可以任意组合:

  • 笔记 - 处理完成的完整笔记(标题、转写文本、摘要、类型、标签、优先级、语言和创建日期)
  • 笔记 + 音频 - 在 Ultra 套餐中,会在每次笔记发送中加入一个 24 小时有效的音频文件下载链接。请保持笔记开启:没有它,就不会发送笔记
  • 任务 - 每个提取出的任务发送一次
  • 事件 - 每个提取出的日历事件发送一次
  • 报告 - 每份生成的每日、每周、每月或年度报告发送一次(你的套餐包含的报告类型)。安静日的占位报告和简短的安静周报告不会发送

你可以随时在自动化的设置中更改这些选项 - 更改只对之后的发送生效。

选择发送时机​

在数据选项下方,有四个独立的开关决定哪些更改会触发发送:已创建、已更新、已完成和已删除。触发条件必须与它上方对应的数据开关一起使用才有效。例如,只有任务开启时,已完成才会发送已完成的任务。

已创建会在 TellDone 根据录音或文字笔记生成笔记时发送,其中的任务和事件也一样。你手动添加的、或通过 AI 助手添加的任务和事件,以及来自语音补充的新条目,不会作为“已创建”发送。已更新、已完成和已删除会在你于 App 中或通过语音补充更改某个条目时发送。由 Smart Context、AI 助手,或在 Todoist、Notion、Microsoft To Do 中所做的更改不会触发发送。

每次发送的 event 字段会说明发生了什么,例如 task.created、task.completed 或 calendar_event.updated。

设置 webhook​

用于 Zapier、Make 和 n8n 的设置自动化界面

  1. 进入 设置 > 集成 > 自动化
  2. 轻点新建自动化

新建自动化 webhook 设置

  1. 输入名称(例如“My Zapier webhook”)
  2. 粘贴你的自动化服务提供的 webhook URL
  3. 选择要发送的数据(笔记、Ultra 上的笔记 + 音频、任务、事件、报告)以及要使用的触发条件(已创建、已更新、已完成、已删除)
  4. 还可以添加一个 auth header - 一个作为 Authorization 请求头发送的令牌,用于需要认证的端点
  5. 轻点保存
  6. 复制签名密钥 - 它只在你首次创建自动化时或更换密钥后完整显示。你需要用它来验证发送确实来自 TellDone(参阅验证 webhook 签名)
  7. 轻点测试发送,向你的端点发送一份示例数据,不会更改你的任何数据。你会看到带有 HTTP 状态码和响应时间的成功,或带有原因的错误。测试发送不会出现在发送日志中

发送的内容​

每次发送都是一个包含三个字段的 JSON 对象:event(事件类型)、timestamp 和 data(实际内容)。测试发送还会包含 "test": true。下面是每种事件类型的样子。

笔记(note.created)​

包含 AI 生成的标题、完整转写文本、摘要、笔记类型、标签、优先级、语言和创建日期。

{
"event": "note.created",
"timestamp": "2026-02-27T14:38:00.512345+00:00",
"data": {
"note_id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Meeting notes - Project Alpha",
"transcript": "Full transcript text...",
"summary": "Brief AI-generated summary...",
"type": "meeting",
"tags": ["work", "project-alpha"],
"priority": "high",
"language": "en",
"created_at": "2026-02-27T10:00:00.284117+00:00"
}
}

在 Ultra 套餐中,笔记发送还可以包含录音的链接(audio_url、audio_format、duration_seconds)。该链接 24 小时后失效。请在自动化中通过笔记 + 音频选项打开它。

任务(task.created)​

每个任务发送一次。一条包含 3 个任务的笔记会发送 3 次独立的数据。

{
"event": "task.created",
"timestamp": "2026-02-27T14:38:01.204718+00:00",
"data": {
"note_id": "550e8400-...",
"note_title": "Meeting notes - Project Alpha",
"task_id": "660f9511-...",
"title": "Send proposal to client",
"description": "Include pricing for Q2",
"priority": "high",
"due_date": "2026-03-01",
"reminder_at": "2026-02-28T09:00:00+00:00",
"tags": ["work"],
"status": "todo",
"cancel_reason": null,
"cancelled_at": null,
"created_at": "2026-02-27T10:00:00.284117+00:00"
}
}

事件(calendar_event.created)​

每个日历事件发送一次。

{
"event": "calendar_event.created",
"timestamp": "2026-02-27T14:38:02.093361+00:00",
"data": {
"note_id": "550e8400-...",
"note_title": "Meeting notes",
"event_id": "770a0622-...",
"title": "Team standup",
"description": "Weekly sync",
"start": "2026-03-03T07:00:00+00:00",
"end": "2026-03-03T07:30:00+00:00",
"location": "Zoom",
"is_all_day": false,
"attendees": ["alice@example.com"],
"tags": ["work"],
"created_at": "2026-02-27T10:00:00.284117+00:00",
"timezone": "Europe/Istanbul",
"start_local": "2026-03-03T10:00:00+03:00",
"end_local": "2026-03-03T10:30:00+03:00",
"start_date": "2026-03-03",
"end_date": "2026-03-03"
}
}

start 和 end 使用 UTC。start_local、end_local、start_date 和 end_date 使用你的时区(timezone)。对于全天事件,end_date 是事件的最后一天。

报告(report.created)​

在每日、每周、每月或年度报告生成时发送。

{
"event": "report.created",
"timestamp": "2026-02-28T00:05:00.731902+00:00",
"data": {
"report_id": "880b1733-...",
"report_type": "daily",
"period_start": "2026-02-27",
"period_end": "2026-02-27",
"content_md": "# Daily Report\n\n...",
"content_json": {
"productivity_score": 72,
"day_type": "planning",
"tasks_created": 5,
"tasks_completed": 3
},
"created_at": "2026-02-28T00:05:00.418253+00:00"
}
}

安全性​

每次发送都会用你的自动化的签名密钥,通过 HMAC-SHA256 签名。每次发送都会带有以下请求头:

  • X-LP-Signature - HMAC-SHA256 签名(sha256=...)
  • X-LP-Timestamp - 用于签名的 Unix 时间戳
  • X-LP-Event - 事件类型(例如 note.created、task.completed、calendar_event.updated、report.created)
  • X-LP-Delivery-Id - 唯一的发送 ID(可用于去重)
  • User-Agent - 始终为 TellDone-Webhooks/1.0

只有当你在自动化中添加了 auth header 时,TellDone 才会发送 Authorization 请求头。可以使用两种格式:Header-Name: value 会发送一个指定名称的请求头,只写一个值则会发送 Authorization: <value>。你的签名密钥绝不会通过请求头发送。

每个自动化都有自己的签名密钥,所以更换其中一个不会影响你的其他 webhook。密钥只在你首次创建自动化时或更换后完整显示。其他任何时候,只显示预览(whsec_...last4)。要换成新的密钥,请在自动化设置中轻点更换密钥 - 这会生成新的 HMAC 密钥,URL 和 auth header 保持不变。旧密钥会立即失效。

只接受带域名的 HTTPS URL。HTTP、IP 地址(公网或内网)、带用户名或密码的 URL,以及指向内网地址的域名都会被拒绝。TellDone 每次发送时都会重新检查该地址。如果检查失败,例如域名在那一刻无法解析,这次发送就会停止,也不会重试。

验证 webhook 签名​

每个 webhook 都经过签名,方便你确认它确实来自 TellDone。签名的计算方式如下:

HMAC-SHA256(signing_secret, timestamp + "." + raw_body)

结果采用十六进制编码,并在签名请求头中加上 sha256= 前缀。

使用原始请求体

TellDone 序列化 JSON 时,分隔符后面带有空格(例如 {"event": "note.created"})。如果你先解析再重新序列化请求体,签名就对不上。请务必对请求体的原始字节进行验证。

Python​

import hmac
import hashlib

def verify_signature(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
payload = f"{timestamp}.".encode() + raw_body
expected = "sha256=" + hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)

# Flask example
@app.route("/webhook/telldone", methods=["POST"])
def telldone_webhook():
raw_body = request.get_data() # raw bytes, NOT request.json
signature = request.headers.get("X-LP-Signature", "")
timestamp = request.headers.get("X-LP-Timestamp", "")

if not verify_signature(raw_body, signature, timestamp, SIGNING_SECRET):
abort(403)

data = request.json
# process webhook...

Node.js​

const crypto = require("crypto");

function verifySignature(rawBody, signature, timestamp, secret) {
const payload = `${timestamp}.${rawBody}`;
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(payload).digest("hex");
const a = Buffer.from(signature);
const b = Buffer.from(expected);
// timingSafeEqual throws if the lengths differ, e.g. when the header is missing
return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express example (use express.raw to get the raw body)
app.post("/webhook/telldone", express.raw({ type: "application/json" }), (req, res) => {
const rawBody = req.body.toString();
const signature = req.headers["x-lp-signature"] || "";
const timestamp = req.headers["x-lp-timestamp"] || "";

if (!verifySignature(rawBody, signature, timestamp, SIGNING_SECRET)) {
return res.status(403).send("Invalid signature");
}

const data = JSON.parse(rawBody);
// process webhook...
});

重放保护(可选)​

为防止重放攻击,请检查时间戳是否足够新:

import time

def verify_timestamp(timestamp: str, tolerance_seconds: int = 300) -> bool:
try:
return abs(time.time() - int(timestamp)) < tolerance_seconds
except (ValueError, TypeError):
return False

常见错误​

错误解决办法
使用解析后再重新序列化的请求体使用原始请求体
在 JS 中使用 JSON.stringify()(紧凑格式,没有空格)使用原始请求体
忘了加时间戳前缀签名内容的格式是 timestamp + "." + body
直接比较字符串使用 hmac.compare_digest 或 timingSafeEqual

重试策略​

如果你的端点出错,TellDone 会按以下时间表重试每次发送:

次数延迟
第 1 次重试30 秒
第 2 次重试2 分钟
第 3 次重试15 分钟
第 4 次重试1 小时
第 5 次重试4 小时

如果第 5 次重试也失败,这次发送会被标记为失败,不再重试。在 App 中它会显示一个红色叉号。你仍然可以在完整的发送日志中自己重新发送:打开全部发送(某个自动化的发送记录超过 5 条后会出现这个链接),然后在失败的发送上轻点重试。简短的最近发送列表不提供重试。

TellDone 对不同响应的处理方式:

  • 2xx - 发送成功
  • 4xx(429 除外)- 立即标记为失败,不再重试(你的端点明确拒绝了这些数据)
  • 429(Too Many Requests)- 按 Retry-After 中的秒数后重试(如果没有则为 60 秒)。这些重试不受 5 次的限制,但每一次都会计入导致自动化被关闭的 20 次失败
  • 5xx 或超时 - 按上面的时间表重试

发送反复失败时​

如果发送一直失败,TellDone 会通知你,并最终关闭这个自动化。

失败 3 次后:收件箱提醒​

连续失败 3 次后(重试也计算在内),TellDone 会向你的收件箱发送一条消息,标题为你的自动化“名称”正在失败,引号中是你的自动化名称。然后你可以在 设置 > 集成 > 自动化 中打开它,查看它的发送记录,并决定怎么做。

失败 20 次后:自动关闭​

自动关闭

如果同一个自动化连续 20 次尝试都失败(重试也计算在内),TellDone 会把这个自动化关闭,这样它就不会继续向一个无法使用的地址发送。请在你的自动化工具中修复问题,然后在 设置 > 集成 > 自动化 中把它的已启用开关重新打开。重新打开不会重置失败次数,所以在有一次发送成功之前,只要再失败一次,它就会再次被关闭。

每一次失败的尝试都会计数,所以一次把 5 次重试全部用完的发送会让计数增加 6。因此,一个自动化在大约 4 次失败的发送后就可能自动关闭。下一次发送成功时,计数会归零。

管理 webhook​

  • 已启用 - 关闭这个开关可以在不删除自动化的情况下让它停止,之后随时可以重新打开。关闭期间不会发送任何内容:这段时间内的笔记和报告之后不会补发,等待重试的发送也会被丢弃
  • 发送记录 - 最近发送显示最近 5 条,包含状态、HTTP 状态码和响应时间。超过 5 条后,全部发送会打开最近 30 天的日志,你可以按全部、已送达或失败筛选,并在失败的发送上轻点重试,无需等待下一次计划的重试就能重新发送
  • 测试发送 - 无论你选择了哪些数据类型,都会发送一条示例笔记(note.created,请求体中带有 "test": true),不会更改你的任何数据。自动化保存后可用。测试发送不计入你的月度上限
  • 更换密钥 - 生成新的 HMAC 签名密钥,URL 和 auth header 保持不变
  • 编辑 - 更新 URL、auth header、数据选项(笔记 / 笔记 + 音频 / 任务 / 事件 / 报告)或触发条件(已创建 / 已更新 / 已完成 / 已删除)。更改立即生效
  • 删除自动化 - 永久删除该自动化及其所有发送日志

每次发送的状态会以图标显示:

图标含义
绿色对勾已送达
黄色时钟等待中或正在发送
红色三角形失败,TellDone 会重试
红色叉号失败,不再自动重试

在完整日志中,你可以在带红色三角形或红色叉号的发送上轻点重试。

发送上限​

有两种上限:取决于你的套餐的月度上限,以及所有付费套餐都适用的每小时 100 次发送上限,用来防止突发的流量高峰。

套餐自动化数量每月发送次数每小时上限
Free00-
Basic1300100
Pro33,000100
Ultra1015,000100

上限的具体表现:

  • 达到月度上限 - 这次发送会等待。它会显示为失败(“Monthly webhook limit exceeded”),TellDone 每 5 分钟重试一次。它会在你的上限于 1 日 00:00 UTC 重置后发出,除非那时它已超过 30 天。重置之后发送的内容计入新的一个月。
  • 达到每小时上限 - 这次发送会被推迟,约 5 分钟后重试,所以短时间的突发不会丢失数据。

只有成功的发送才计入月度上限。每小时上限则统计每一次尝试,包括重试。测试发送不计入这两种上限。

如果你更改套餐,你的自动化及其设置会保留。在 Free 上,它们会停止发送,并且在你升级之前无法打开。在 Basic 上,你已有的自动化可以在每月 300 次发送的范围内继续发送,但你不能添加或开启多于一个。

过滤测试事件​

轻点测试发送时,数据的顶层会包含 "test": true。在你的自动化工具中,可以检查这个字段,存在时就跳过处理。

平台指南​

使用你的自动化工具的分步设置说明:

  • Zapier - 用 Zap 把 TellDone 连接到数千个 App
  • Make - 搭建可视化的自动化场景(原 Integromat)
  • n8n - 在自行托管或云端的工作流中使用 TellDone webhook
  • 自定义端点 - 任何接受 HTTPS POST 请求的服务都可以使用 TellDone webhook

创意​

  • 通过 Zapier 把任务发送到 Google 表格
  • 通过 Make 根据笔记创建 Slack 消息
  • 通过 n8n 把事件记录到自定义 CRM
  • 把所有笔记备份到云存储
  • 把报告转发到团队看板

另请参阅​

  • 收件箱和支持 - 如果 webhook 反复失败,你会在收件箱中看到一条消息
  • Zapier - Zapier 分步设置
  • Make - Make 分步设置
  • n8n - n8n 分步设置
  • Todoist - 专用的任务双向同步(无需 webhook)
  • Notion - 专用的 Notion 集成
  • 邮件转发 - 通过邮件接收笔记数据