文档

将 SublimeKeys 接入你的应用所需的一切。无需账户即可阅读。

$SUBLIMEKEYS_API_KEY

下面的每个请求都用它作为你真实密钥的占位符。 登录 (免费,无需信用卡)获取属于你自己的密钥,并查看用你自己的产品填充后的这些示例。

快速上手 — 3 次调用

1. 注册你的产品 (只需在“产品”中做一次)

curl -X POST https://api.sublimearts.io/v1/products \
  -H "Authorization: Bearer $SUBLIMEKEYS_API_KEY" \
  -d '{"slug":"my-app","key_prefix":"MYAPP"}'

2. 每次销售时签发一个密钥

curl -X POST https://api.sublimearts.io/v1/licenses \
  -H "Authorization: Bearer $SUBLIMEKEYS_API_KEY" \
  -d '{"product":"my-app","email":"buyer@mail.com","max_activations":3}'

→ {"key":"MYAPP-K3F7Q-9WZ2M-P8RT4-XN5CB", ...}
product必填——来自第 1 步的产品 slug
email可选——会显示在你控制台的许可证列表中
max_activations可选,默认值为 1——这一个密钥可以同时在多少个不同的 machine_id 上处于激活状态。请按照你自己的定价承诺来设置(例如“个人使用,3 台设备”套餐设为 3)。上限由你自己的 SublimeKeys 套餐决定,而非你终端客户的套餐——Free 为 5,Pro 为 25,Business 为 100(详见价格)。
expires_at可选——ISO 日期;留空则为永久密钥
notes可选——自由文本,仅供你自己参考

或者完全跳过这次调用——见下方 AUTOMATE。

3. 在你的应用内验证

Python — 官方 SDK(推荐)
# pip install sublimekeys
from sublimekeys import SublimeKeysClient

client = SublimeKeysClient(product_id="my-app")
result = client.activate(license_key=key)   # first run
result = client.verify(license_key=key)     # every launch after — offline-first,
                                             # verifies a signed lease locally,
                                             # zero network calls for up to 7 days
if result.valid:
    unlock_full_version()
Node.js / Electron — 官方 SDK(推荐)
// npm install sublimekeys
import { SublimeKeysClient } from "sublimekeys";

const client = new SublimeKeysClient("my-app");
const activated = await client.activate(key);     // first run
const result = await client.verify(key);          // every launch after — offline-first,
                                                   // verifies a signed lease locally,
                                                   // zero network calls for up to 7 days
if (result.valid) unlockFullVersion();

不用 Python 或 Node.js,或者想自己调用原始 API? PyPI 上的 Python SDK · npm 上的 Node.js SDK 或直接使用下方的接口。

Python — 原始 API
import requests

r = requests.post("https://api.sublimearts.io/activate", json={
    "license_key": key,
    "machine_id": machine_id,
    "product_id": "my-app",
})
if r.json()["valid"]:
    unlock_full_version()
Node.js — 原始 API
const r = await fetch("https://api.sublimearts.io/activate", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ license_key, machine_id, product_id: "my-app" }),
});
const { valid } = await r.json();
if (valid) unlockFullVersion();
cURL
curl -X POST https://api.sublimearts.io/activate \
  -d '{"license_key":"...","machine_id":"...","product_id":"my-app"}'
▸ 第一次接触?这些调用在你的应用中实际应该放在哪里

上面的示例只单独展示了 /activate ——在实际应用中,你会在不同时刻调用不同的接口:

应用启动
├─ 尚未保存许可证密钥(首次运行)
│    → 显示你的“输入许可证密钥”界面
│    → 用户提交后 → 调用一次 /activate → 将结果保存在本地
│
├─ 已保存许可证密钥(之后每次启动)
│    → 改为调用 /verify(而不是再次调用 /activate)——确认它
│      在这台机器上依然有效
│
├─ API 无法访问(用户处于离线状态)
│    → /activate 和 /verify 都会返回一个已签名的“租约”(有效期 7 天)
│    → 在本地验证其签名,而不是盲目信任上一次的
│      结果——Python 和 Node.js SDK 会自动完成这一步;其他
│      语言可以自行验证 Ed25519 签名(公钥
│      位于 GET /public-key)
│
└─ 用户卸载/退出登录(可选)
     → 调用 /deactivate,让名额释放给另一台机器

在 Python 或 Node.js/Electron 中,官方 SDK(PyPI·npm)已经自动处理了这一切——包括对离线租约的真实加密验证。下方的原始版本跳过了这一步(离线时只是简单信任上一次保存的结果)——更简单,但没有经过加密校验。如果你不使用 Python/Node.js,或者想要完全掌控,可以使用它。

Python — 完整的应用启动流程(原始 API,不使用 SDK)
import requests, json, os

STATE_FILE = "license_state.json"

def check_license(machine_id):
    saved = json.load(open(STATE_FILE)) if os.path.exists(STATE_FILE) else None

    try:
        if saved is None:
            # first run — ask the user for their key once
            key = prompt_for_license_key()
            r = requests.post("https://api.sublimearts.io/activate", json={
                "license_key": key, "machine_id": machine_id, "product_id": "my-app",
            }, timeout=5)
        else:
            # every later launch — re-check the saved key, don't ask again
            r = requests.post("https://api.sublimearts.io/verify", json={
                "license_key": saved["license_key"], "machine_id": machine_id, "product_id": "my-app",
            }, timeout=5)

        result = r.json()
        json.dump(result, open(STATE_FILE, "w"))
        return result["valid"]

    except requests.RequestException:
        # offline — trust the last known result instead of locking the user out
        return saved["valid"] if saved else False

已经熟悉这个概念了?可以跳过这部分——上面的调用就是你所需要的全部。

官方 SDK

🐍 Python — sublimekeys

封装了整个 API,并为你处理离线验证——通过本地校验的签名租约完成 activate/verify/deactivate,因此大多数启动都不产生任何网络请求,试用检查也能挺过一段离线时间。还会安装一个 sublimekeys 命令行工具,方便你从终端测试集成。

pip install sublimekeys
在 PyPI 上查看 →

⚡ Node.js / Electron — sublimekeys

同样具备离线能力的设计,零运行时依赖——Ed25519 验证使用 Node 内置的加密模块,因此不会有任何东西让 Electron 的 asar 打包机制出问题。

npm install sublimekeys
在 npm 上查看 →

更多语言正在路线图中。与此同时,下面的每个接口都是一个普通的 REST 调用——任何能发起 HTTPS 请求的东西都可以调用它。

接口参考 — 公开(由你的应用调用)

POST /activate

请求体: { "license_key", "machine_id", "product_id" }

▸ 详情

首次运行——将一个许可证密钥绑定到某个 machine_id。在同一台机器上重复调用是安全的——不会消耗额外的激活名额。如果无法完成(例如在另一台机器上已达到激活上限),会返回 valid:false 并附带说明信息。成功时,响应中的 lease 字段还会返回一个签名租约(7 天离线信任窗口)——Python SDK 会在之后的启动中本地验证它,而不是每次都调用 API。

POST /verify

请求体: { "license_key", "machine_id", "product_id" }

▸ 详情

此后每次启动都会调用——确认该密钥在这台机器上依然有效。不会影响你的激活计数,因此可以随意频繁调用。每次成功调用还会刷新签名租约(参见 /activate)。

POST /deactivate

请求体: { "license_key", "machine_id", "product_id" }

▸ 详情

用户退出登录/卸载——释放名额给另一台机器使用。

POST /trial/start

请求体: { "machine_id", "product_id" }

▸ 详情

为某台机器获取或创建一个 7 天试用期。幂等操作——重新安装永远不会重置计时。

POST /trial/status

请求体: { "machine_id", "product_id" }

▸ 详情

只读的试用状态检查——绝不会启动一个新的试用。

这些接口不需要 Authorization 请求头——license_key 本身就是凭证。完整的账户级 API(创建/列出/吊销)位于 /v1/* 下,详见控制台。

⚡ AUTOMATE — 无需后端的密钥发放

完全跳过上面的第 2 步。将你支付服务商的 webhook 指向你产品的 URL,每笔销售就会自动签发一个密钥并通过邮件发送给你的买家。

  1. Stripe 控制台 → Developers → Webhooks → Add endpoint
  2. 粘贴你产品的 URL (登录并创建一个产品即可获取你的 URL)
  3. 选择事件: checkout.session.completed
  4. 保存。就这么简单——无需服务器,无需代码。
  5. 可选但推荐:Stripe 在此之后会显示一个 Signing secret——把它粘贴到“产品”页面的“Signature verification”中,这样我们就能拒绝任何并非真正来自 Stripe 的请求(而不只是拥有这个 URL 的任何人)。

🔔 也想在每次销售时收到通知邮件?在“产品”页面此区块旁打开“Notify me”。

从 GUMROAD、KEYGEN 或自建服务器迁移

将现有客户导出为一个只含 email 列的 CSV 文件,然后针对每个产品运行一次这段脚本。它会为每一行批量签发一个全新的、带有你品牌前缀的 SublimeKeys 许可证。

migrate.py
import csv, os, requests

API_KEY = os.environ["SUBLIMEKEYS_API_KEY"]
PRODUCT = "my-app"

with open("customers.csv") as f:
    for row in csv.DictReader(f):
        r = requests.post("https://api.sublimearts.io/v1/licenses",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={"product": PRODUCT, "email": row["email"]})
        print(row["email"], "->", r.json()["key"])

这会签发全新的密钥——不会保留你原有的密钥字符串(出于设计考虑,我们不接受自定义密钥值)。可以将新密钥通过邮件发给客户,或者在过渡期内于应用中并行运行新旧两种校验,之后再淘汰旧系统。

套餐限制

FREE

1 个产品 · 100 个密钥 · 每个密钥 5 台设备

PRO

5 个产品 · 1,000 个密钥 · 每个密钥 25 台设备

BUSINESS

产品和密钥数量不限 · 每个密钥 100 台设备

达到限制永远不会破坏已有的密钥——它们会一直持续验证下去。你只是无法签发新密钥,直到升级为止。降级或取消同样也永远不会删除任何东西。