跳到主要内容

试用扩展程序开发者 API

如果您想构建 Chastify 扩展、托管 iframe 扩展页面或从您自己的后端调用开发者 API,请使用本指南。

本页是起点:选择哪种模式,首先拨打什么电话,以及下一步该去哪里。

有关具体的扩展行为,例如解锁障碍物、常规所需操作、奖励和惩罚,请参阅**扩展 API 功能**。

提示

只想控制自己的锁?

如果您不需要构建公共扩展程序,外部 API 和程序 页面是入门的最简单方法。您只需创建一个 DEV 令牌并调用简单的 REST 端点——无需设置扩展程序、无需 iframe、无需会话管理。它支持添加/删除时间、冻结、任务、设备命令等功能。

此 API 的用途

Extensions Developer API 允许您构建在 Chastify 锁定会话中运行的第三方扩展体验。

有了它,你可以:

  • 读取会话和锁定上下文(扩展程序为 session.get,您自己的锁定自动化程序为 /api/apps/v1/session
  • 读取每个锁定会话的扩展拥有的数据 (state.get),并从您的后端写入 (PUT/PATCH /state)
  • 将扩展程序拥有的图像文件存储在 Chastify 管理的 R2 存储 (files.*) 中
  • 在锁定卡片上添加扩展 UI 操作 (metadata.homeActions)
  • 带有扩展程序拥有的解锁阻止器的门解锁流程 (metadata.unlockBlockers)
  • 从可信后端触发锁定操作(添加/删除时间、冻结/解冻、设置补丁)
  • 触发任务和卫生操作(task.assigntask.start_timertask.completehygienic_unlock.start
  • 提交带有计数器/节奏支持的定期行动
  • 如有支持的设备命令,请发送。
  • 写入自定义扩展日志条目以锁定历史记录

你可以建造什么

合适的功能集取决于信任的根基所在。

仅支持前端的 iframe 扩展可以构建以 UI 为先的体验,而无需可信锁变更:

  • 设置页面以收集扩展配置
  • 读取会话上下文的仪表板
  • 拼图、清单或游戏用户界面,能够读取会话状态并通过后端发送已验证的进度。
  • 读取 Chastify 已存储的扩展文件的基于媒体的流
  • 首页操作入口点,通过意图打开您的 iframe。

服务器端支持的扩展程序可以构建影响锁的功能,因为后端会在调用特权 API 之前验证结果:

  • 具有解锁要求的任务或习惯系统
  • 每日或每周的要求,并设有错过规定的惩罚措施
  • 通过锁定时间变更来奖励成功或惩罚失败的游戏
  • 服务器端验证后,清除解锁障碍的验证流程
  • 使用受支持的设备命令的设备控制配套流程
  • 将扩展状态保存在 iframe 之外的 Webhook/数据库工作流

外部程序用于对您自己的活动锁进行私有自动化控制:

  • 本地脚本
  • 个人仪表盘
  • 使用用户级 DEV 密钥的自动化工具

选择您的模式

请选择以下模式之一:

  1. Hosted iframe extension:在 Cloudflare Pages 或类似服务上托管静态 iframe UI。使用此桥接模式进行设置、会话上下文和安全读取。请勿单独使用此模式进行状态写入、奖励、惩罚、解锁完成或可信需求进度记录。
  2. Server-backed extension:托管 iframe UI 并运行您自己的后端。iframe 会将启动信息 mainToken 发送到您的后端,您的后端会使用应用范围的开发者 API 密钥和 x-chastify-main-token 调用 Chastify 扩展 API。此模式可用于特权操作、解锁障碍、可信进度、奖励、惩罚、Webhook 和外部数据库。
  3. External API & Programs:使用用户全局密钥 DEV 来控制您自己的活动锁,该密钥适用于脚本、本地程序或自动化操作。第三方用户安装您的扩展程序时,请勿使用此模式。

如果要快速测试,请先使用 iframe 模式实现 UI 和安全读取。在实现状态写入、可信奖励、时间变更、计划任务进度或解锁阻塞完成等功能之前,再添加后端。

警告

iframe 代码并非信任边界。iframe 中可见的任何内容,包括哈希有效载荷和启动令牌,都可能被用户检查和重放。

前 10 分钟(Iframe 模式)

  1. 从 Chastify iframe 打开中读取 location.hash 有效载荷。
  2. 创建 session.get 的桥接请求。
  3. 使用 type: "chastify:ext:resp"ok: true 确认回复。
  4. 使用 state.get 读取测试状态。
  5. 添加自动调整大小和主题支持,以便 iframe 在 UI 中正确运行。

主题支持是生产就绪型 iframe 的一部分。Chastify 会在启动哈希中传递 ui 值,并在 iframe 打开期间发送实时主题更新。有关浅色/深色示例和对比度安全的 Tailwind 模式,请参阅Iframe 主题

必需的有效载荷值:

  • bridge.nonce
  • bridge.parentOrigin
  • sessionId
  • lockId

桥接请求示例:

{
"type": "chastify:ext:req",
"v": 1,
"id": "request-id", // unique id per request
"nonce": "nonce-from-hash",
"action": "session.get",
"payload": {}
}

桥接响应示例:

{
"type": "chastify:ext:resp",
"v": 1,
"id": "request-id",
"ok": true,
"data": {}
}

首先要学习的核心行动

  • session.get
  • state.get
    读取扩展程序拥有的 JSON 存储中的锁定会话信息。使用开发者 API 凭据从后端写入状态。
  • files.capabilities, files.list, files.get 对拼图图像或生成的预览等二进制媒体使用文件存储读取。将文件 ID 存储在后端写入状态中,然后使用 files.get 刷新签名 URL。
  • metadata.get 读取锁定会话解锁阻止程序和扩展卡主页操作/意图。
  • regularActions.get

会话变更(例如状态写入、常规操作提交、运行时文件上传/删除、时间更改、解锁阻止程序更新、任务完成、卫生启动和设备命令)必须使用开发者 API 密钥从后端调用。浏览器 iframe 代码不被信任用于这些操作。

完整 API URL(支持)

基础域名:https://chastify.net

扩展会话 API (/api/extensions/*)

这些路由具有不同的访问模式。请勿将整个 /api/extensions/* 表面视为 iframe 安全的。

安全的 iframe 桥接路由在 postMessage 桥接请求之后,通过 Chastify 父级进行路由:

  • GET https://chastify.net/api/extensions/sessions/:sessionId
  • GET https://chastify.net/api/extensions/sessions/:sessionId/state
  • GET https://chastify.net/api/extensions/sessions/:sessionId/metadata
  • GET https://chastify.net/api/extensions/sessions/:sessionId/regular-actions
  • GET https://chastify.net/api/extensions/sessions/:sessionId/files/capabilities
  • GET https://chastify.net/api/extensions/sessions/:sessionId/files
  • GET https://chastify.net/api/extensions/sessions/:sessionId/files/:fileId

仅限后端安装的扩展程序路由需要应用范围的开发者 API 密钥和 iframe 启动令牌:

Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
信息

此双令牌模型将后端请求绑定到扩展程序开发者 (Authorization) 和当前打开的扩展程序会话 (x-chastify-main-token)。

  • PATCH https://chastify.net/api/extensions/sessions/:sessionId/metadata
  • PUT https://chastify.net/api/extensions/sessions/:sessionId/state
  • PATCH https://chastify.net/api/extensions/sessions/:sessionId/state
  • PATCH https://chastify.net/api/extensions/sessions/:sessionId/regular-actions/config
  • POST https://chastify.net/api/extensions/sessions/:sessionId/regular-actions
  • POST https://chastify.net/api/extensions/sessions/:sessionId/files
  • DELETE https://chastify.net/api/extensions/sessions/:sessionId/files/:fileId
  • POST https://chastify.net/api/extensions/sessions/:sessionId/logs/custom
  • POST https://chastify.net/api/extensions/sessions/:sessionId/notifications/custom
  • POST https://chastify.net/api/extensions/sessions/:sessionId/device-command
  • POST https://chastify.net/api/extensions/sessions/:sessionId/action
  • POST https://chastify.net/api/extensions/sessions/:sessionId/requirements/progress

后端令牌 API (/api/apps/v1/*)

使用 Authorization: Bearer <user-wide DEV token>。这些端点管理令牌所有者自己的活动锁定会话,并且是为外部 API 脚本/程序设计的,而不是为已安装的第三方扩展会话设计的。

  • GET https://chastify.net/api/apps/v1/session
  • GET https://chastify.net/api/apps/v1/state
  • PUT https://chastify.net/api/apps/v1/state
  • PATCH https://chastify.net/api/apps/v1/state
  • GET https://chastify.net/api/apps/v1/metadata
  • PATCH https://chastify.net/api/apps/v1/metadata
  • POST https://chastify.net/api/apps/v1/action
  • POST https://chastify.net/api/apps/v1/lock/apply-time
  • POST https://chastify.net/api/apps/v1/lock/freeze
  • POST https://chastify.net/api/apps/v1/lock/unfreeze
  • POST https://chastify.net/api/apps/v1/logs/custom

Iframe 桥接命令

桥接命令有效载荷通过 iframe (chastify:ext:req) 发送,并由父级 iframe (Chastify) 路由。该桥接器有意限制于安全/会话 UI 操作。

  • session.get -> GET https://chastify.net/api/extensions/sessions/:sessionId
  • state.get -> GET https://chastify.net/api/extensions/sessions/:sessionId/state
  • files.capabilities -> GET https://chastify.net/api/extensions/sessions/:sessionId/files/capabilities
  • files.list -> GET https://chastify.net/api/extensions/sessions/:sessionId/files
  • files.get -> GET https://chastify.net/api/extensions/sessions/:sessionId/files/:fileId{ "fileId": "file_record_id" }
  • metadata.get -> GET https://chastify.net/api/extensions/sessions/:sessionId/metadata
  • regularActions.get -> GET https://chastify.net/api/extensions/sessions/:sessionId/regular-actions

会话变更端点是直接调用后端 API,而非 iframe 桥接命令。这包括状态写入、常规操作提交以及运行时文件上传/删除,因为 iframe 代码可以由用户控制。

后端会话 API 示例

对于已安装扩展的特权调用,您的后端必须发送这两个标头:

Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

后端操作示例:

  • metadata.patch -> PATCH /api/extensions/sessions/:sessionId/metadata
  • regularActions.submit -> POST /api/extensions/sessions/:sessionId/regular-actions
  • files.upload -> POST /api/extensions/sessions/:sessionId/files
  • files.delete -> DELETE /api/extensions/sessions/:sessionId/files/:fileId
  • lock.applyTime -> POST /api/extensions/sessions/:sessionId/action{ "name": "add_time", "params": <deltaSeconds> }
  • lock.freeze -> POST /api/extensions/sessions/:sessionId/action{ "name": "freeze", "params": { "durationSeconds": 900 } }
  • lock.unfreeze -> POST /api/extensions/sessions/:sessionId/action{ "name": "unfreeze", "params": {} }
  • lock.settings.patch -> POST /api/extensions/sessions/:sessionId/action{ "name": "settings.patch", "params": { ... } }
  • task.assign -> POST /api/extensions/sessions/:sessionId/action
  • task.start_timer -> POST /api/extensions/sessions/:sessionId/action{ "name": "task.start_timer", "params": {} }
  • task.complete -> POST /api/extensions/sessions/:sessionId/action{ "name": "task.complete", "params": { "successful": true } }
  • hygienic_unlock.start -> POST /api/extensions/sessions/:sessionId/action{ "name": "hygienic_unlock.start", "params": { "durationSeconds": 900 } }
  • pillory.end -> POST /api/extensions/sessions/:sessionId/action{ "name": "pillory.end", "params": {} }
  • device.command -> POST /api/extensions/sessions/:sessionId/device-command
  • logs.custom -> POST /api/extensions/sessions/:sessionId/logs/custom
  • notifications.custom -> POST /api/extensions/sessions/:sessionId/notifications/custom
  • requirements.progress -> POST /api/extensions/sessions/:sessionId/requirements/progress

令牌、作用域、撤销和审计行为

使用正确的令牌来建立正确的信任边界。

注意

开发者 API 密钥是机密信息。如果密钥暴露给浏览器代码,请立即撤销该密钥并轮换后端环境变量。

Iframe启动令牌(mainToken

  • 当用户打开已安装的扩展程序页面时,通过 iframe 哈希传递。
  • 浏览器可见,这是设计使然。它能识别已打开的扩展程序会话,但并非后端机密信息。
  • 有效期短暂。当前的启动令牌将在 10 小时后过期;请重新打开扩展程序页面以刷新令牌。
  • 当您的后端调用已安装扩展程序会话路由时,需要 x-chastify-main-token,以便 Chastify 可以将后端请求绑定到打开扩展程序的用户/会话。
  • 不得单独使用来授权时间更改、解锁阻塞程序完成、任务完成、设备命令、运行时上传/删除、自定义日志或自定义通知。

应用范围的开发者 API 密钥

  • 由开发者界面创建,适用于一个扩展应用程序。
  • 仅限后端使用的密钥。切勿将其放在 iframe JavaScript 代码、移动应用包、静态主机配置或浏览器可读日志中。
  • Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEYx-chastify-main-token 一起使用。
  • 只能对与扩展程序应用和启动令牌匹配的会话调用已安装扩展程序会话 API。
  • 不会自动过期。如果泄露,请立即撤销,并轮换后端环境变量。

用户级开发者 API 密钥

  • 通过开发者界面创建,未选择扩展应用。
  • /api/apps/v1/* 的后端专用密钥。
  • 控制钥匙所有者当前/未来的活动锁定会话。
  • 不能用作已安装的第三方扩展后端凭据。

撤销

  • 被撤销的开发者API密钥将停止授权新的请求。
  • 已撤销的密钥可以从开发者界面永久删除。
  • 新启动的 iframe 会获得新的启动令牌。请勿将 mainToken 存储为长期凭证。

职责范围和角色

  • 扩展应用程序的作用域描述了应用程序可以请求的内容。
  • 安全的 iframe 桥接调用仅限于 UI 引导、会话读取、扩展拥有的状态、元数据读取、常规操作读取和文件读取。
  • 即使扩展程序具有匹配的作用域,特权安装会话变更也需要后端凭据。
  • 根据启动操作属于佩戴者还是钥匙持有者,角色相关的操作仍然可能被拒绝。

审计和限额

  • 当密钥被使用时,开发者 API 密钥的上次使用元数据会更新。
  • 特权操作路由有速率限制,当使用错误的凭据类型时,会返回 server_credentials_requireduser_wide_dev_key_required 等明确错误。
  • 自定义日志会写入可见的锁定历史记录条目。
  • 自定义通知会为请求的目标创建 Chastify 通知。
  • 对每个特权扩展变更进行全面审计覆盖,并将其作为生产环境加固措施进行跟踪。

支持的命令值

/api/extensions/sessions/:sessionId/action/api/apps/v1/action

name 支持:

  • add_time
  • remove_time
  • freeze
  • pillory
  • unfreeze
  • toggle_freeze
  • settings.patch
  • task.assign
  • task.start_timer
  • task.complete
  • hygienic_unlock.start
  • pillory.end

行动限制:

  • 任务操作需要锁定设备上启用“任务”扩展/模块。
  • hygienic_unlock.start 需要启用卫生开启功能,且没有正在进行的卫生会话。

session.get 锁定数据助手

session.get / GET /api/apps/v1/session 还包含 lockData,其中包含运行时友好的布尔值、数字和字符串,适用于规则引擎。

例如:

  • 布尔值:frozenunlockabletrustedtaskAssigned(当存在打开的 TaskRun 时,则为 true
  • 数字:timeLockedSecondstimeRemainingSecondsmaxTimeRemainingSecondstaskPoints
  • 字符串:lockTitle,佩戴者/钥匙持有者个人资料字段

隐私:

  • 当该用户禁用在线状态时,wearerLastSeenTimestampkeyholderLastSeenTimestampnullshowOnlineStatus === false)。

设备命令

扩展会话可以使用基于会话的端点:

POST /api/extensions/sessions/:sessionId/device-command

拥有 DEV 令牌的外部程序可以使用更简单的 v1 端点(无需会话 ID):

POST /api/apps/v1/device-command

两者都接受相同的请求体并返回相同的响应。详情请参阅外部API和程序

如果您的扩展程序有设置/配置界面:

  1. 父级发送 chastify:ext:setup:init(已保存的配置 + 上下文)。
  2. 您的设置 iframe 返回更新,更新内容为 chastify:ext:setup:config
  3. 家长可以使用 chastify:ext:setup:get_config 请求当前配置。

后端令牌流(当您需要服务器端调用时)

对于简单的脚本和外部程序,请使用开发者 API 页面上的用户级 DEV 令牌。请参阅外部 API 和程序

扩展程序 iframe 模式下的默认流程:

  1. Chastify 为活动的扩展会话颁发一个短暂的、浏览器可见的启动令牌。
  2. 启动令牌以 mainToken 的形式嵌入到 iframe 哈希有效负载中。
  3. 您的 iframe 将 mainToken 转发到您的后端。
  4. 您的后端调用 https://chastify.net/api/extensions/sessions/:sessionId/*,并传入 Authorization: Bearer <app-scoped Developer API key>x-chastify-main-token: <mainToken>

请勿将开发者 API 密钥发送到 iframe/浏览器代码。mainToken 用于标识已打开的扩展会话;它并非后端密钥,不能单独用于执行特权操作。

手动回退:

  • 如果需要从第一方 UI 显式获取/轮换 iframe 启动令牌,请调用 GET https://chastify.net/api/extensions/sessions/:sessionId/auth

如果 Chastify 页面未打开时需要定时任务、Webhook 或自动化操作,请使用后端模式。当前已安装扩展程序的会话变更仍然需要有效的 10 小时 iframe 启动令牌,因此,除非您使用的是专为后台执行而设计的第一方/内置服务器流程,否则无人值守任务应存储待处理的验证信息,并在下次有效启动时提交。

信息

为了实现完全无人值守的生产环境运行,建议使用内置/第一方服务器流程,或等待明确的后台扩展授权。应用范围的会话 API 目前依赖于启动令牌。

后端 vs Cloudflare Pages(无服务器)

在以下情况下使用 Cloudflare Pages(无需后端服务器):

  • 您想要最简单、最便宜的方案(可以免费托管)。
  • 你只需要在用户主动访问你的扩展程序页面时执行 UI 驱动的操作即可。
  • 您不需要服务器持久化的扩展状态写入。
  • 您正在快速构建轻量级扩展程序或原型。

本地测试示例(PowerShell):

cloudflared tunnel --url http://localhost:5174

测试时,请使用生成的公共 URL 作为 iframe URL。

在以下情况下使用后端服务器:

  • 你需要定时任务(类似 cron 的行为)。
  • 您需要使用 Webhook 或外部集成。
  • 当扩展程序页面无人访问时,您需要自动化/后台处理。
  • 你需要由服务器控制的、必须持续运行的工作流。

没有后端的一个重要限制:

  • 不进行后台执行。 只有当用户当前打开扩展程序 iframe 并与之交互时,您的扩展程序才能执行操作。

常见问题

  • 403 extension_not_enabled:此锁未启用扩展功能。
  • 409 lock_ended:锁定已解除。
  • 429:已达到速率限制。
  • iframe 中没有响应:请检查 noncetargetOrigin (parentOrigin) 和允许的来源。

Next 指南