跳到主要内容

API

TelegramOS HTTP API:使用 API 密钥进行身份验证,并以编程方式驱动账号、收件箱、机器人、分析和工作流。

仪表盘能做的一切,都是通过这套 HTTP API 完成的。下面的每一个路径、请求体和状态码,在本页发布之前都已在真实工作区中实际验证过。

基础 URL

https://telegramos.net

请求和响应均为 JSON(Content-Type: application/json)。导出接口返回文件(.xlsx / .csv),媒体下载接口返回字节流。

身份验证

在设置 → API 密钥下创建一个密钥,然后通过 X-API-Key 请求头发送它:

curl -H "X-API-Key: tgp_your_key_here" \
     https://telegramos.net/api/accounts

密钥只在创建时显示一次。它以 SHA-256 哈希形式存储,因此没有人——包括我们——能够恢复它。弄丢了就重新创建一个。

属性值
请求头X-API-Key
格式tgp_ 后跟 54 个 URL 安全字符
默认有效期90 天(expires_days,1–365)
每个工作区的密钥数20
撤销即时生效,在 设置 → API 密钥 中操作

修改密码、重置密码、关闭 2FA 或在所有设备上退出登录,都会永久撤销在那一刻之前签发的所有密钥。

浏览器会话则使用 Cookie。这两条路径从不混用:带 X-API-Key 的请求完全由该密钥完成身份验证,而密钥管理接口(/api-keys)有意拒绝密钥——一个密钥不能签发或撤销另一个密钥(403)。

权限

创建时勾选的权限会在每一个请求上强制执行。

动词 ——必须至少选择一个:

权限授予
readGET、HEAD
writePOST、PUT、PATCH、DELETE

区域 ——可选。不勾选任何区域的密钥可以访问所有区域;勾选一个或多个区域的密钥则被限制在这些区域内:

权限覆盖范围
accounts账号、代理、预热、抓取、利基查找器、群发私信、线索包
inbox会话、消息、群组、快捷回复、自动回复规则、通知
bots机器人、流程、营销活动、频道同步、机器人数据库
analytics分析和 AI 接口
tasks工作流和执行记录

仅 read 是一个覆盖整个平台的只读密钥。read + write + inbox 只能在收件箱内做任何事——它在 /api/accounts 上会得到 403。

请求 ID

每个响应都带有 X-Request-ID。你自己传一个,我们就用它;不传,我们就生成一个:

curl -i -H "X-API-Key: $KEY" -H "X-Request-ID: my-job-42" \
     https://telegramos.net/api/accounts
...
x-request-id: my-job-42

每个请求都会在我们这边连同该 ID、路径、状态、耗时、密钥前缀(绝不记录完整密钥)和工作区一起记录下来:

api.request service=account-service request_id=my-job-42 method=GET
path=/api/accounts status=200 duration_ms=144 auth=key:tgp_t24zIO user=<workspace>

在你这边也记录这个 ID。平台处于 Beta 阶段期间,这是我们定位你那次具体调用最快的方式——在支持工单中引用它,我们就能不靠猜测地调出完整的请求链路。

错误

状态码含义
400请求格式错误,或路径中的 ID 不是 UUID
401密钥缺失、未知、已过期或已撤销
402你的套餐不包含此功能,或钱包余额不足以支付本次运行
403密钥有效,但其权限不覆盖此调用
404资源不存在,或属于另一个工作区
409账号当前无法执行此操作(受垃圾信息限制、仍在预热中)
422请求体未通过验证——响应会指出具体字段
429请求过多,或账号已用完每小时/每日发送额度
503某个依赖服务不可用;请重试

错误响应带有 detail:

{"detail": "This API key is scoped to inbox — not 'accounts'."}

另一个工作区的对象返回 404,绝不会是 403——API 从不确认某个 ID 是否存在。

约定

  • ID 均为 UUID。非 UUID 的路径段会返回 400 或 404,绝不会是 500。
  • 发送是排队的,不是同步的。让账号执行动作的接口会返回 202 和一个 task_id。随后账号会按照防封禁节奏规则发送(参见限制与配额)。轮询该资源以查看结果。
  • 一切都以工作区为范围。你从不需要传工作区 ID;密钥已经携带了它。
  • 列表接口根据资源不同接受 limit/offset 或 page/page_size;两者都是可选的。

账号

区域:accounts。

方法路径作用
GET/api/accounts列出账号
POST/api/accounts添加账号
GET/api/accounts/{id}单个账号
PATCH/api/accounts/{id}重命名、重新打标签、修改设置
DELETE/api/accounts/{id}移除账号
POST/api/accounts/import导入会话文件
POST/api/accounts/batch-import一次导入多个
POST/api/accounts/login/phone/send-code开始手机号登录
POST/api/accounts/login/phone/verify-code提交验证码
POST/api/accounts/login/phone/verify-2fa提交 2FA 密码
POST/api/accounts/login/qr/start开始二维码登录
POST/api/accounts/login/qr/poll轮询登录状态(长轮询,约 20 秒)
POST/api/accounts/login/cancel放弃登录
POST/api/accounts/{id}/power让账号休眠或唤醒
POST/api/accounts/{id}/safety放宽或关闭防封禁限制(付费套餐)
POST/api/accounts/bulk/safety同上,一次作用于所有账号
POST/api/accounts/{id}/profile设置名称、简介、头像
POST/api/accounts/{id}/clone-profile复制另一个账号的资料
GET/api/accounts/{id}/privacy隐私设置
GET/api/accounts/{id}/photos头像照片
GET/api/accounts/{id}/stats今日已发送/已接收消息数
GET/api/accounts/{id}/health-log健康分数历史
GET/api/accounts/{id}/risk当前封禁风险读数
GET/api/accounts/{id}/connections连接审计日志
GET/api/accounts/{id}/sessions登录提示——仅限租用账号
GET/api/accounts/{id}/vault会话保险库状态
GET POST/api/accounts/{id}/backfill-history读取 / 启动旧聊天拉取(?discover_only=true = 仅拉取聊天列表)
POST/api/accounts/{id}/backfill-history/cancel停止正在运行的拉取
POST/api/accounts/{id}/reset-status将处于 error 或 paused 状态的账号恢复为 active
GET/api/accounts/{id}/avatar头像照片,以字节流返回
DELETE/api/accounts/{id}/photos/{photoId}删除一张头像照片
POST/api/accounts/{id}/username-check在占用之前检查用户名是否可用
POST/api/accounts/{id}/contact-policy“一人一账号”规则——{"single_contact": false} 允许此账号给你另一个账号已在联系的人发消息
POST/api/accounts/{id}/group-invites把人拉进群组——见下方说明
POST/api/accounts/{id}/skip-warmup把预热时钟回拨——自有账号随时可用,租用账号需满 3 天
GET/api/accounts/{id}/session/export下载会话——仅限自有账号
POST/api/accounts/{id}/sessions/{hash}/decision批准或拒绝一次登录提示
POST/api/accounts/bulk批量激活 / 停用 / 删除
POST/api/accounts/bulk/listener在整个账号群中开启或关闭入站监听器
POST/api/accounts/bulk/contact-policy对所有账号应用同一规则

一旦 worker 完成连接,每一行账号记录都会携带该账号自身的 Telegram 身份:tg_user_id(数字形式的 Telegram ID)、tg_username、tg_first_name、tg_last_name。当别人的会话线程指向此账号时,tg_user_id 就是显示为 peer_id 的那个值。

会话保险库挂在同一个账号下:POST /api/accounts/{id}/vault/enable、/disable、/lock、/unlock、/rotate,并用 GET /api/accounts/{id}/vault 查看当前状态。

注意 /group-invites 是整个产品中最严格的接口,因为拉人进群是丢失账号最快的方式。除非账号已完成预热、持有不到 36 小时的干净 @SpamBot 判定结果、且不处于仅回复模式,否则它会以 409 拒绝。
注意 /sessions 是给租用账号用的。在你自有的账号上它会回答 404 no live allocation for this account on your workspace——这是正确的响应,不是故障。

代理

方法路径作用
GET/api/proxies列出代理
POST/api/proxies添加一个
POST/api/proxies/bulk添加多个
PATCH/api/proxies/{id}编辑
POST/api/proxies/{id}/rotate轮换出口 IP
DELETE/api/proxies/{id}删除
PATCH DELETE/api/proxies/{id}/assign绑定 / 解绑账号
GET/api/proxies/{id}/usage已用流量
POST/api/proxies/{id}/check连通性测试

预热

方法路径作用
GET PUT/api/warmup/settings读取 / 替换预热设置
GET/api/warmup/overview整个账号群的预热状态
GET/api/warmup/plan生成的计划
POST/api/warmup/plan/apply应用该计划
DELETE/api/warmup/plan丢弃该计划
POST/api/warmup/dry-run预览而不应用
GET/api/warmup/pairs哪些账号之间互相对话
GET/api/warmup/groups计划中的群组
GET/api/warmup/events预热实际执行了什么
GET POST/api/warmup/channels账号群加入的频道
DELETE/api/warmup/channels/{id}移除一个
GET/api/warmup/accounts每个账号的预热状态
POST/api/warmup/accounts/{id}/social切换社交预热

防封禁限制

本 API 中的每一项节流——冷启动外联和回复额度、预热爬坡、PeerFlood 减速、营销活动每日上限、同群间隔以及拟人化延迟——都是平台自身的保护措施,而非 Telegram 的。在付费套餐上,你可以用 POST /api/accounts/{id}/safety 按账号修改或关闭它,或用 POST /api/accounts/bulk/safety 一次作用于所有账号:

{
  "mode": "custom",
  "cold_hourly": 30, "cold_daily": 200,
  "reply_hourly": 120, "reply_daily": 600,
  "per_minute": 6, "min_gap_seconds": 3,
  "campaign_daily": 200, "group_spacing_minutes": 30,
  "content_filter": true, "spam_circuit": true,
  "warmup_ramp": false, "human_delay": true,
  "trial_cap": true, "spambot_throttle": true,
  "join_hourly": 40, "join_daily": 60,
  "forward_hourly": 20, "forward_daily": 200,
  "invite_hourly": 4, "invite_daily": 20,
  "report_hourly": 5, "report_daily": 20,
  "massdm_daily": 30, "massdm_delay_min": 45, "massdm_delay_max": 120,
  "massdm_warmup_ramp": true, "massdm_flood_hold": true, "massdm_circuit": true
}

mode 可以是 default(平台规则)、custom(你发送的数值;未提供的字段保持平台默认值;per_minute、min_gap_seconds、campaign_daily 或 group_spacing_minutes 为 0 表示不限制)或 off(完全没有平台侧节流)。join_*、forward_*、invite_* 和 report_* 各对字段是按动作划分的额度;massdm_* 字段控制群发私信调度器(massdm_daily 提高单个任务可申请的每账号上限,massdm_circuit 决定当任务的账号返回泛洪或被封锁状态时任务是否中止;只要任务中任一账号保持开启,该任务就仍受保护)。当前配置以 safety 字段随账号对象返回,并在下一次发送时生效——无需重新连接。无论你如何设置,Telegram 自身的 FloodWait 和垃圾信息限制仍然适用,放宽限制后账号的封禁风险由你自行承担。免费套餐会返回 402。“一人一账号”规则独立于此配置,在 off 模式下依然生效;可通过 /api/accounts/{id}/contact-policy 按账号切换。

抓取

方法路径作用
POST GET/api/scraping/jobs启动 / 列出任务
GET/api/scraping/jobs/{id}状态
POST/api/scraping/jobs/{id}/cancel取消
GET/api/scraping/jobs/{id}/results以 JSON 返回结果
GET/api/scraping/jobs/{id}/export以 .xlsx 返回结果
GET/api/scraping/jobs/{id}/export.csv以 CSV 返回结果
POST/api/scraping/jobs/{id}/webhook将结果推送到你的 URL
GET/api/scraping/usage本周期已用配额

抓取是一次性的提取,而不是持续监控:一个账号遍历目标的消息历史一次,从中提取电话号码(或你给定的模式)。广播频道可以作为目标,但其帖子来自频道本身,所以对频道的抓取很少能得到号码。若要跟踪频道发布的内容,请改用监控频道。免费试用按结果计数,而不是按扫描的消息数计数,因此一次一无所获的运行不花费任何额度。

POST /api/scraping/jobs
{
  "name": "leads",
  "group_links": ["https://t.me/somepublicgroup"],
  "limit_per_group": 300,
  "max_accounts": 5,
  "patterns": [],
  "keyword_filter": []
}

patterns 为空表示提取电话号码;其他预设类型有 email、 username、url 和 price,而 custom 模式接受你自己的正则表达式。 group_links 同时接受公开群组和公开频道。

付费深度运行按扫描的消息数计费,如果钱包余额无法覆盖最坏情况,则返回 402。免费试用的计数方式不同:它是 50 条 结果,因此一次一无所获的运行不花费任何额度。它在另一侧也有边界—— 免费运行在总共读取 2,000 条消息后停止,无论返回了什么。 GET /api/scraping/usage 会报告两个计数器(used / limit 和 scanned / scan_limit)。

利基查找器

方法路径作用
POST/api/niche/suggest关键词建议
POST GET/api/niche/jobs启动 / 列出任务
GET/api/niche/jobs/{id}状态
GET/api/niche/jobs/{id}/sources它读取了哪些群组
POST/api/niche/jobs/{id}/cancel取消
GET/api/niche/jobs/{id}/results发现的受众
GET/api/niche/jobs/{id}/export同上,以 .xlsx 返回
POST /api/niche/jobs
{
  "name": "crypto traders",
  "keywords": ["trading", "signals"],
  "active_within_days": 30,
  "msg_scan_limit": 3000,
  "max_accounts": 5,
  "extract_members": false
}

extract_members 会导出原始成员列表;它默认关闭,因为这是有封禁风险的读取操作。

线索包与监视任务

方法路径作用
GET/api/packages在售的线索包
GET/api/packages/{id}单个线索包
POST/api/packages/{id}/buy购买(从钱包扣费)
GET/api/packages/{id}/download下载已购买的线索包
POST/api/packages/{id}/publish将你自己的一个线索包上架出售
DELETE/api/packages/{id}下架
GET/api/watches/plans周期性抓取方案
GET POST/api/watches列出 / 创建监视任务
GET/api/watches/{id}单个监视任务
POST/api/watches/{id}/pause暂停
POST/api/watches/{id}/resume恢复
DELETE/api/watches/{id}删除

群发私信

方法路径作用
GET/api/mass-dm/accounts有资格发送的账号
POST GET/api/mass-dm/jobs创建 / 列出营销活动
GET/api/mass-dm/jobs/{id}进度
GET/api/mass-dm/jobs/{id}/recipients每个收件人的状态
GET/api/mass-dm/jobs/{id}/replies谁回复了
GET/api/mass-dm/jobs/{id}/export全部内容,以 .xlsx 返回
GET POST/api/mass-dm/suppression禁止联系名单
DELETE/api/mass-dm/suppression/{tgUserId}移除一条记录
POST/api/mass-dm/jobs/{id}/pause暂停正在运行的活动
POST/api/mass-dm/jobs/{id}/resume恢复已暂停的活动
POST/api/mass-dm/jobs/{id}/cancel永久停止
GET/api/mass-dm/contacts/{tgUserId}我们对某个联系人的已知信息
POST /api/mass-dm/jobs
{
  "recipients": [{"tg_user_id": 123456789, "username": "someone"}],
  "message_text": "hi {first_name}",
  "account_ids": ["<account-uuid>"],
  "per_account_daily_cap": 20,
  "followups": []
}

提供 recipients 或 niche_job_id 二者之一,不能同时提供。禁止联系名单接受一个列表:

POST /api/mass-dm/suppression
{"tg_user_ids": [777000777], "reason": "opted out"}

收件箱

区域:inbox。

方法路径作用
GET/api/conversations列出会话
POST/api/conversations开始新聊天(202)
GET/api/conversations/search全文搜索(?q=)
GET/api/conversations/{id}/messages某个线程中的消息
POST/api/conversations/{id}/messages发送回复(202)
PATCH/api/conversations/{id}分配、打标签、标记已解决、静音
POST/api/conversations/{id}/mark-read标记为已读
DELETE/api/conversations/{id}移除该线程
POST/api/conversations/media上传附件,获得一个 media_key
GET/api/conversations/{id}/messages/{msgId}/media下载附件
POST/api/conversations/{id}/messages/{msgId}/fetch-media拉取占位符对应的媒体
GET POST/api/conversations/{id}/notes内部备注
DELETE/api/conversations/{id}/notes/{noteId}删除一条备注
POST/api/conversations/{id}/block屏蔽对方
POST/api/conversations/{id}/leave退出群组
GET/api/conversations/sla-stats响应时间统计
GET/api/conversations/account-stats每个账号的消息量
GET/api/conversations/activity-series随时间变化的消息量
GET/api/conversations/reply-stats回复率——需要 ?source=

列表接口的筛选参数:account_id、peer_type(user / bot / group / channel)、status、tags、unread_only、source(campaign / mass_dm)、campaign_id、job_id、page、page_size。

reply-stats 需要 source=campaign&campaign_id=... 或 source=mass_dm&job_id=...;缺少它们时会返回 422/400 并指出缺失的内容。

监控频道

广播频道和其他会话一样——peer_type 是 channel ——但它的帖子是选择加入的。一个活跃的频道每天可能通过账号的代理推送数百兆字节的数据,因此监听器会丢弃所有你未主动请求的频道的帖子。这就是为什么你加入的频道在添加之前不显示任何内容:不是缺少支持,而是被关闭了。

开启一个频道:

  1. 用你的一个账号(在 Telegram 客户端中)加入该频道。
  2. 把它加入监控列表:POST /api/groups,请求体为 {"identifier": "@thechannel", "type": "channel", "via_account_id": "<uuid>"}。
  3. 读取帖子:GET /api/conversations?peer_type=channel,然后 GET /api/conversations/{id}/messages?after_msg_id=<last seen>。

identifier 接受公开的 @username、t.me/name 链接或数字形式的 peer id。type 可以是 group、supergroup 或 channel;无论你传什么,都会在首次同步时根据 Telegram 的数据校正,连同 members_count、 posts_per_day 和带标记的 peer id 一起更新。

私有频道没有 @username,而邀请链接(t.me/+…)不携带 peer id,所以两者都无法识别它。同步一次该账号的聊天列表,频道就会带着数字 ID 出现,然后你按常规方式添加即可:

POST /api/accounts/{account_id}/backfill-history?discover_only=true
   → registers the account's chats, pulls no messages, costs almost no proxy data

GET /api/conversations?peer_type=channel
   → the private channel is now listed, with its peer_id

POST /api/groups
{"identifier": "-1001234567890", "type": "channel", "via_account_id": "<uuid>"}

在仪表盘中,同样的流程就是 群组 → 跟踪群组 里的频道选择器。

一旦被跟踪,新帖子就会像其他入站消息一样到达:通过 inbox.new_message WebSocket 事件,以及订阅了该事件的 Webhook。你在 Telegram 中已静音的频道仍会同时投递两者,并带有 conversation.muted: true,因此集成永远不会漏掉帖子;只有仪表盘保持静默。

peer_type 有四个值:user、bot、group 和 channel。超级群组属于 group——这一区分只对 /api/groups 有意义,它在首次同步后会报告 supergroup。

一旦频道被监控,其帖子就会像其他消息一样到达:出现在 GET /api/conversations/{id}/messages 中、inbox.new_message WebSocket 事件中,以及订阅了 inbox.new_message 的 Webhook 中。

有两样东西*不是*这个功能:/api/channel-syncs 把一个频道的帖子镜像到你控制的另一个频道中(它是转发器,不是读取器),而 /api/warmup/channels 是新账号在预热期间加入的频道列表。两者都不返回频道内容。POST /api/groups/{id}/sync 只刷新成员数和帖子数——它不会拉取帖子。

跟踪线程

只有消息监听器已开启的账号才会记录入站消息。在 GET /api/accounts 中 power_sender_only: true 的账号只发不收,因此无论你轮询多少次,它的线程都保持为空——请先为它开启监听器。

GET /api/conversations/{id}/messages 默认向后分页(before、before_msg_id、limit 最多 200)——这正是 UI 在你向上滚动时需要的。

监控程序需要的恰恰相反。传入 after_msg_id,值为你已持有的最新消息的 telegram_msg_id,你就只会得到此后到达的消息,按从旧到新排序:

GET /api/conversations/{id}/messages?after_msg_id=19626585&limit=200

telegram_msg_id 在同一聊天内单调递增,因此该游标永远不会重复一条消息,也永远不会跳过一条。保存你见过的最大 ID,用它轮询,就没有任何需要去重的东西。如果同时传了 after_msg_id 和 before/before_msg_id,前者优先。

每条消息都带有 direction:in 表示账号收到的消息,out 表示通过本平台发送的消息。在同一账号的 Telegram 客户端中手动输入的消息不会被记录——Telegram 将它们作为你自己的出站更新投递,监听器会忽略它们。

若要推送而非轮询,请参见下方的 Webhook 和实时事件。

发送

在现有线程中回复:

POST /api/conversations/{id}/messages
{"content": "Thanks — one moment.", "media_key": null}

与尚未出现在收件箱中的人开始一个线程:

POST /api/conversations
{
  "account_id": "<account-uuid>",
  "recipient_type": "username",
  "recipient": "someone",
  "content": "hello"
}

recipient_type 可以是 username、phone 或 user_id。两个接口都返回 202:

{"task_id": "...", "conversation_id": null, "queued": true,
 "note": "Message queued. It will appear in the inbox once Telegram acknowledges the send."}

一旦 Telegram 确认发送,消息就会出现在 GET /api/conversations/{id}/messages 中——通常只需几秒,如果账号已达到每小时节奏上限则会更久。

防封禁守卫会在任何内容入队之前就作出响应,所以要处理它们:

  • 受垃圾信息限制的账号冷启动一个聊天:Telegram has limited this account, so it can't start new conversations right now — it can still reply to people who messaged it.
  • 正在预热的账号不能主动发起,只能回复。
  • 内容过滤器以 422 拒绝文本,并附带一个方括号代码——[REPEATED_CHARS]、[EXCESSIVE_CAPS]、[TOO_MANY_LINKS]、[BLOCKED_LINK]、[SPAM_PATTERN]。修改文本后重新发送;重试相同的请求体总是失败。
  • 滚动发送额度以 429 响应,并附带 [HOURLY_MESSAGE_LIMIT] 或 [DAILY_MESSAGE_LIMIT]。冷启动外联的上限为每个账号每小时 10 条、每天 40 条。一旦对方回信,该线程中之后的每条消息都算作回复,改为每小时 60 条、每天 300 条——无论你是通过 POST /api/conversations/{id}/messages 发送,还是继续用相同的收件人调用 POST /api/conversations。每小时窗口是连续滚动的,所以应当退避等待,而不是改写消息。健康分数下降的账号会得到按比例缩减的额度。付费套餐可以按账号修改或移除这些额度——参见防封禁限制;自定义配置会在可能的 429 代码中增加 [MINUTE_MESSAGE_LIMIT] 和 [MESSAGE_GAP_LIMIT]。

只有 202 才表示发送已在路上。如果之后仍然失败——收件人屏蔽了该账号、账号掉线——原因会以带有相同 task_id 的 inbox.message_failed Webhook 送达。

群组、快捷回复、规则、通知

方法路径作用
GET POST/api/groups已跟踪的群组和频道
PATCH DELETE/api/groups/{id}编辑 / 取消跟踪
POST/api/groups/{id}/sync刷新成员数和帖子数
GET/api/groups/{id}/stats活跃度
GET POST/api/saved-replies预设回复
PUT DELETE/api/saved-replies/{id}编辑 / 删除
GET POST/api/auto-reply-rules自动回复规则
POST/api/auto-reply-rules/bulk批量创建
PATCH DELETE/api/auto-reply-rules/{id}编辑 / 删除
GET/api/notifications通知流
GET/api/notifications/unread-count角标计数
PATCH/api/notifications/read-all全部标为已读
GET PUT/api/notifications/preferences按类别的偏好设置
PATCH/api/notifications/{id}/read将一条标为已读
DELETE/api/notifications/{id}忽略一条
GET POST/api/api-connectors外部回复连接器
GET/api/api-connectors/kinds你可以创建的连接器类型
PATCH DELETE/api/api-connectors/{id}编辑 / 移除
POST/api/api-connectors/{id}/test测试一个
GET/api/conversations/{id}/avatar聊天头像,以字节流返回
GET/api/conversations/{id}/peer-avatar对方的头像
POST /api/groups
{"identifier": "https://t.me/somepublicgroup", "type": "group", "via_account_id": "<uuid>"}

POST /api/saved-replies
{"title": "greeting", "content": "Hi {first_name}", "variables": ["first_name"]}

POST /api/auto-reply-rules
{
  "account_id": "<account-uuid>",
  "match_type": "contains",
  "match_value": "price",
  "reply_text": "Our pricing is on the site.",
  "is_active": true,
  "delay_min": 2,
  "delay_max": 8
}

match_type 是 any、exact、contains、regex 之一。

机器人

区域:bots。

方法路径作用
GET POST/api/bots列出 / 注册机器人
DELETE/api/bots/{id}移除
POST/api/bots/{id}/active启用 / 禁用
POST/api/bots/{id}/delivery-mode轮询或 Webhook
POST/api/bots/{id}/broadcast向其聊天广播
GET/api/bots/{id}/chats它能触达的聊天
GET POST/api/bots/{id}/flows可视化流程
GET/api/bots/flows/templates入门模板
POST/api/bots/{id}/flows/templates/{templateId}/instantiate从模板创建流程
GET PUT DELETE/api/bots/{id}/flows/{flowId}单个流程
POST/api/bots/{id}/flows/{flowId}/test试运行
GET/api/bots/{id}/runs流程运行历史
GET/api/bots/{id}/runs/{runId}/steps每一步的详情

营销活动

方法路径作用
GET POST/api/campaigns列出 / 创建(创建后处于草稿状态)
GET/api/campaigns/{id}单个活动
POST/api/campaigns/{id}/start启动
POST/api/campaigns/{id}/pause暂停
POST/api/campaigns/{id}/stop停止
PATCH/api/campaigns/{id}/assignments重新分配账号和群组
POST/api/campaigns/{id}/import-chatlist批量添加目标群组
GET/api/campaigns/{id}/metrics发送数、失败数、触达数
DELETE/api/campaigns/{id}删除
POST /api/campaigns
{
  "name": "launch",
  "message_a": {"text": "..."},
  "message_b": {"link": "https://t.me/channel/123"},
  "interval_minutes": 30,
  "delay_min_seconds": 15,
  "delay_max_seconds": 90,
  "assignments": [{"account_id": "<uuid>", "group_chat_ids": [-1001234567890]}]
}

创建并不会启动它——请调用 /start。

频道同步与机器人数据库

方法路径作用
GET POST/api/channel-syncs频道到频道的镜像——转发帖子,不为你读取帖子
GET PATCH DELETE/api/channel-syncs/{id}单个镜像
POST/api/channel-syncs/{id}/arm启用
POST/api/channel-syncs/{id}/disarm停用
POST/api/channel-syncs/{id}/run立即运行一次
GET POST/api/botdb/collections集合
GET PUT DELETE/api/botdb/collections/{id}单个集合
GET POST/api/botdb/collections/{id}/records记录
POST/api/botdb/collections/{id}/query筛选 / 排序 / 分页
PUT DELETE/api/botdb/collections/{id}/records/{recordId}单条记录
GET POST/api/botdb/collections/{id}/views已保存的视图
POST /api/botdb/collections
{"name": "leads", "schema": {"fields": [{"key": "email", "type": "text"}]}}

POST /api/botdb/collections/{id}/records
{"data": {"email": "a@b.com"}}

字段定义使用 key(而不是 name),data 中含有未声明键的记录会被拒绝,并提示 unknown field(s): ...。

分析

区域:analytics。

方法路径作用
GET/api/analytics/summary该周期的汇总数据
GET/api/analytics/daily逐日序列
GET/api/analytics/timeline事件时间线
GET/api/analytics/accounts/{id}/timeline单个账号的时间线
GET/api/analytics/velocity发送速度
GET/api/analytics/anomalies检测到的异常
GET/api/analytics/anomalies/{accountId}单个账号的异常
POST/api/analytics/ai/anomalies/detect立即运行检测
GET/api/analytics/ai-insights针对整个账号群的叙述性洞察
GET/api/analytics/report完整报告数据
GET/api/analytics/ai/summaryAI 叙述性摘要
GET/api/analytics/ai/daily-digest每日摘要(单位为秒,而非毫秒)
POST/api/analytics/ai/suggest-replies回复建议
POST/api/analytics/ai/summarize-conversation总结一个线程
POST/api/analytics/ai/sentiment线程的情感倾向
POST/api/analytics/ai/send-risk草稿的封禁风险评分
POST/api/analytics/ai/compose-message起草一条消息
POST/api/analytics/ai/suggest-posts内容创意
POST/api/analytics/ai/template-variations生成模板变体
GET/api/analytics/ai/quota剩余 AI 额度

工作区的分析开关关闭时,这些接口返回空序列而不是错误。AI 接口消耗 AI 额度:先查看 /api/analytics/ai/quota,额度用完后会返回 429。

工作流

区域:tasks。

方法路径作用
GET POST/api/workflows列出 / 创建
GET PUT DELETE/api/workflows/{id}单个工作流
POST/api/workflows/{id}/run立即运行
GET/api/workflows/{id}/stats运行次数和成功率
POST DELETE/api/workflows/{id}/schedule附加 / 移除 cron 计划
GET/api/executions运行历史
POST/api/executions启动一次运行
GET/api/executions/{id}单次运行
GET/api/executions/{id}/steps每个节点的状态
DELETE/api/executions/{id}取消正在运行的执行
POST /api/workflows
{"name": "nightly", "definition": {"nodes": [], "edges": []}}

支持

无区域限制——任何密钥都可以访问这些接口。

方法路径作用
GET POST/api/support/tickets列出 / 开启工单
GET/api/support/tickets/{id}单个工单及其对话线程
POST/api/support/tickets/{id}/messages回复
POST/api/support/tickets/{id}/close关闭工单
POST/api/support/tickets/{id}/seen将线程标为已读
GET/api/support/unread-count角标计数

身份

方法路径作用
GET/auth/me此密钥属于谁,以及所用套餐

编辑个人资料(PATCH /auth/me)与密钥管理一样,需要浏览器会话——密钥会得到 403。

Webhook

Webhook 是接收事件的持久化方式:我们先把事件写入数据库,然后 POST 到你的 URL,失败时重试。在你部署期间断开的 Socket 会丢失事件;Webhook 不会。

图 8. 一次 Webhook 投递:头部、签名、重试阶梯和去重。

在设置 → API 密钥 → Webhook下管理它们,或通过 API(区域 inbox):

方法路径作用
GET/api/webhooks列出你的端点
POST/api/webhooks注册一个——响应中带有签名用的 secret
PATCH/api/webhooks/{id}修改 URL、事件列表,或将其关闭
DELETE/api/webhooks/{id}移除
GET/api/webhooks/events事件目录
GET/api/webhooks/{id}/secret读回签名密钥
POST/api/webhooks/{id}/rotate-secret签发新的签名密钥
POST/api/webhooks/{id}/test排队一次 webhook.test 投递(202)
GET/api/webhooks/{id}/deliveries最近的投递记录,含状态和错误
POST /api/webhooks
{"url": "https://your-server.example/telegramos",
 "events": ["inbox.new_message"],
 "description": "prod monitor"}

events 列表为空表示所有类型。每个用户最多十个端点;URL 必须是公网 http(s) 地址(私有地址和回环地址会被拒绝)。

事件

类型触发时机
inbox.new_message某个会话收到或发出了一条消息
inbox.message_failed一次已排队的发送未能成功——携带 error_code、可读的 message、task_id 和 recipient
inbox.read某个会话被标记为已读
account.status_change账号状态发生变化(active、paused、error、banned)
account.health_update账号的健康分数发生变化
account.trust_changed账号的信任等级发生变化
account.power_changed账号被置于休眠或被唤醒
account.presence账号的 worker 连接到或断开了 Telegram
notification.new平台发出了一条通知
webhook.test仅由测试按钮/接口触发

闭合一次发送的回路。发送只返回 202 和一个 task_id,别无其他——账号仍需让它通过 Telegram 的节奏限制。同时订阅 inbox.new_message 和 inbox.message_failed,你就能知道结果是哪一种:成功会以 direction: "out" 的消息到达,失败则以 inbox.message_failed 到达,携带相同的 task_id、一个 error_code(blocked_by_user、privacy_restricted、account_offline、cannot_write、account_banned……)以及一句可以展示给用户的说明。

我们发送的请求

POST /your-path
Content-Type: application/json
X-TGP-Event: inbox.new_message
X-TGP-Delivery: 82a91c75-7446-4ebe-8f79-3013cceaa1d7
X-TGP-Timestamp: 1787308800
X-TGP-Signature: v1=<hex>

{"id": "<delivery id>", "type": "inbox.new_message",
 "created_at": "2026-08-20T10:27:04+00:00",
 "data": {"user_id": "...", "account_id": "...", "conversation_id": "...",
          "message": {"id": "...", "direction": "in", "sender_id": 123, "sender_username": "...",
                      "content": "...", "sent_at": "..."},
          "conversation": {"id": "...", "title": "...", "peer_id": 123,
                           "peer_username": "...", "peer_type": "channel", "muted": false}}}

对于一个账号与一个对方之间的线程,conversation.id 是稳定的,无论消息往哪个方向走:账号的出站消息和对它的回复携带相同的 conversation.id,所以这就是你应当据以订阅的键。peer_id 始终是对方的 Telegram ID,绝不是账号自己的,而 message.direction 说明是谁写的:out 是账号,in 是对方。message.sender_id / message.sender_username 把这一点写得更明确:in 时是对方的 Telegram ID 和用户名,out 时是账号自己的(群组或频道成员为 null,我们不携带其身份)。你自己的两个账号互相对话会产生两个线程(每个账号一个),各有自己的 ID。

验证签名。用你的密钥对 {timestamp}.{raw body} 做 HMAC-SHA256,与 v1= 之后的十六进制值比较。使用原始字节——重新序列化 JSON 会改变它们。

import hmac, hashlib

def verify(secret: str, headers, raw_body: bytes) -> bool:
    ts = headers["X-TGP-Timestamp"]
    expected = "v1=" + hmac.new(
        secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(headers["X-TGP-Signature"], expected)

时间戳包含在签名内容之中,因此拒绝任何超过几分钟的投递,被截获的投递就无法在之后对你重放。

投递规则

  • 任何 2xx 都算作已接受。快速响应,事后再处理——我们在 10 秒后放弃请求并将其视为失败。
  • 失败后分别在 10 秒、1 分钟、5 分钟、30 分钟和 2 小时后重试——总共六次尝试——然后该投递被标记为 failed。
  • 连续五个事件耗尽所有重试会关闭该端点;仪表盘会显示原因。重新开启会清零计数器。
  • 不跟随重定向。请把我们指向最终 URL。
  • 投递 ID 在多次重试间保持稳定——以它作为去重的键。
  • 已投递的记录保留 7 天,失败的记录保留 30 天。

实时事件

仪表盘通过 Socket.IO 流式接收实时更新:

wss://telegramos.net/ws

使用会话 JWT(auth.token)、会话 Cookie 或 API 密钥进行身份验证——在握手中以 auth.apiKey 传入,或作为 X-API-Key 请求头传入。密钥需要 read 权限,如果它限定了区域,则必须包含 inbox。

import { io } from 'socket.io-client'

const socket = io('https://telegramos.net', {
  path: '/ws',
  transports: ['websocket'],
  auth: { apiKey: process.env.TGP_API_KEY },
})
socket.on('inbox.new_message', (e) => console.log(e.conversation_id, e.message.content))

事件以命名的 Socket.IO 消息形式到达:连接时是 system.connected,随后是 inbox.new_message、notification.new、account.status_change、account.power_changed 等;用 subscribe:account 订阅单个账号。

在此基础上构建之前要了解两件事:

  • 浏览器受限。握手会检查 Origin,只允许我们自己的域名。服务端客户端不发送 Origin,可以正常连接;你自己域名下的页面会被拒绝。请通过你的后端代理。
  • Socket 只投递一次。你断开连接期间发布的任何内容都会丢失。对于不能错过的投递请使用 Webhook,或在重连时用 after_msg_id 进行对账。

API 不覆盖的内容

  • 团队、计费、钱包和市场仅限会话访问:/wallet、/payments/*、/subscriptions/*、/billing/*、/bundles/purchase、/account-resale/*、/referrals/* 和 /teams/* 对 API 密钥一律返回 401,无论其范围如何。没有任何密钥路径可以花钱、租用账号或更改席位——请在仪表盘中完成这些操作。两个例外是公开目录的读取接口 GET /listings 和 GET /bundles/availability,它们完全不需要身份验证。
  • 没有 SDK。纯 HTTP;用你手头任何客户端即可。
  • 没有按密钥的速率限制。请求本身很廉价,但其背后的动作会按限制与配额中的防封禁限制逐账号控制节奏,因此一批突发的发送会排队而不是立即发出。

一个完整示例

回复最新的未读会话,并等待发送落地:

KEY="tgp_your_key_here"
BASE="https://telegramos.net"

CONV=$(curl -s -H "X-API-Key: $KEY" \
  "$BASE/api/conversations?unread_only=true&page_size=1" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['id'])")

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
     -H "X-Request-ID: reply-$CONV" \
     -d '{"content":"Thanks for reaching out — one moment."}' \
     "$BASE/api/conversations/$CONV/messages"
# -> 202 {"task_id": "...", "queued": true, ...}

curl -s -H "X-API-Key: $KEY" "$BASE/api/conversations/$CONV/messages" | tail -c 400

监控一个会话

三个组成部分,按你设置它们的顺序排列。

1. 如果需要历史记录,先回填一次。 POST /api/accounts/{id}/backfill-history 会排队一次性导入现有聊天(自有账号,不含媒体,每个聊天最多 1000 条消息;广播频道只有在通过 POST /api/groups 被跟踪后才会包含在内)。轮询 GET /api/accounts/{id}/backfill-history 直到 state 为 done——状态有 queued、running、done、cancelled,而 idle 表示没有记录任何任务(要么从未启动,要么状态在 6 小时后已过期)。每个账号只运行一次;它非常消耗代理流量,而之后的一切都会自行到达。

2. 接入实时流。为 inbox.new_message 注册一个 Webhook。要让消息持续流入收件箱,不需要其他任何东西——账号的 worker 已经在监听了。

3. 对账。你这边发生任何中断之后,用你存储的最后一个 ID 作为 after_msg_id,把每个会话向前推进。这样就能补上缺口而无需重读整个线程。

KEY="tgp_your_key_here"
BASE="https://telegramos.net"

curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
     -d '{"url":"https://your-server.example/telegramos","events":["inbox.new_message"]}' \
     "$BASE/api/webhooks"
# -> 201 {"id": "...", "secret": "whsec_...", ...}   <- store the secret

curl -s -H "X-API-Key: $KEY" \
     "$BASE/api/conversations/$CONV/messages?after_msg_id=$LAST_SEEN&limit=200"
报告此页面的问题
API | TelegramOS文档