Доки
Всё необходимое, чтобы подключить 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 | обязательно — slug продукта из шага 1 |
| опционально — отображается в списке лицензий вашей панели | |
| max_activations | опционально, по умолчанию 1 — на скольких разных machine_id этот ключ может быть активен одновременно. Установите значение исходя из того, что обещает ваш собственный тариф (например, 3 для плана «личное использование, 3 устройства»). Ограничено вашим планом SublimeKeys, а не планом вашего конечного клиента — 5 на Free, 25 на Pro, 100 на Business (см. цены). |
| expires_at | опционально — дата в формате ISO; не указывайте для вечного ключа |
| notes | опционально — произвольный текст, только для вашей собственной справки |
Или полностью пропустите этот запрос — см. AUTOMATE ниже.
3. Проверяйте внутри вашего приложения
# 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()// 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 самостоятельно? Python SDK на PyPI · Node.js SDK на npm или используйте эндпоинты напрямую ниже.
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()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 -X POST https://api.sublimearts.io/activate \
-d '{"license_key":"...","machine_id":"...","product_id":"my-app"}'▸ Впервые с этим сталкиваетесь? Куда именно эти вызовы попадают в вашем приложении
Пример выше показывает только /activate сам по себе — в реальном приложении вы вызываете разные эндпоинты в разные моменты:
Приложение запускается
├─ Лицензионный ключ ещё не сохранён (первый запуск)
│ → покажите экран «введите лицензионный ключ»
│ → пользователь отправляет его → вызовите /activate один раз → сохраните результат локально
│
├─ Лицензионный ключ уже сохранён (каждый последующий запуск)
│ → вызывайте /verify вместо этого (не /activate снова) — подтверждает,
│ что он всё ещё действителен на этой машине
│
├─ API недоступен (пользователь офлайн)
│ → и /activate, и /verify возвращают подписанный «lease» (действителен 7 дней)
│ → проверяйте его подпись локально, а не слепо доверяйте последнему
│ результату — SDK для Python и Node.js делают это автоматически; другие
│ языки могут самостоятельно проверить подпись Ed25519 (публичный ключ
│ на GET /public-key)
│
└─ Пользователь удаляет приложение / выходит из системы (опционально)
→ вызовите /deactivate, чтобы место освободилось для другой машиныВ Python или Node.js/Electron официальные SDK (PyPI · npm) уже делают это за вас — включая настоящую криптографическую проверку офлайн-lease. Сырая версия ниже пропускает этот шаг (она просто доверяет последнему сохранённому результату в офлайне) — проще, но без криптографической проверки. Используйте её, если вы не на Python/Node.js или хотите полный контроль.
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 с подписанным lease, проверяемым локально, так что большинство запусков не делает сетевых вызовов, плюс проверки пробного периода, переживающие офлайн-паузу. Также устанавливает CLI sublimekeys для тестирования интеграции из терминала.
pip install sublimekeys
⚡ Node.js / Electron — sublimekeys
Тот же дизайн с поддержкой офлайн-режима, ноль зависимостей во время выполнения — проверка Ed25519 использует встроенную криптографию Node, так что упаковке Electron в asar не за что зацепиться.
npm install sublimekeys
Другие языки — в планах. А пока каждый эндпоинт ниже — обычный REST-вызов: вызывайте его из чего угодно, что умеет делать HTTPS-запросы.
СПРАВОЧНИК ПО ЭНДПОИНТАМ — ПУБЛИЧНЫЕ (вызываются вашим приложением)
POST /activate
тело: { "license_key", "machine_id", "product_id" }
▸ Подробности
Первый запуск — привязывает лицензионный ключ к machine_id. Безопасно вызывать повторно на той же машине — это не расходует ещё один слот активации. Возвращает valid:false с сообщением, если не может (например, лимит активаций достигнут на другой машине). При успехе также возвращает подписанный lease (окно офлайн-доверия на 7 дней) в поле lease ответа — Python SDK проверяет его локально при последующих запусках вместо того, чтобы каждый раз вызывать API.
POST /verify
тело: { "license_key", "machine_id", "product_id" }
▸ Подробности
Каждый последующий запуск — подтверждает, что ключ всё ещё действителен на этой машине. Не влияет на счётчик активаций, так что вызывайте его сколько угодно часто. Также обновляет подписанный lease (см. /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 выше. Направьте вебхук вашего платёжного провайдера на URL вашего продукта, и каждая продажа автоматически выдаст ключ и отправит его покупателю по email.
- Панель Stripe → Developers → Webhooks → Add endpoint
- Вставьте URL вашего продукта (войдите и создайте продукт, чтобы получить свой)
- Выберите событие: checkout.session.completed
- Сохраните. Вот и всё — без сервера, без кода.
- Необязательно, но рекомендуется: сразу после этого Stripe покажет Signing secret — вставьте его в «Signature verification» на странице Продуктов, чтобы мы отклоняли всё, что не является настоящим запросом от Stripe (а не просто от того, кто узнал этот URL).
🔔 Хотите тоже получать email при каждой продаже? Включите «Notify me» рядом с этим блоком на странице Продуктов.
ПЕРЕНОС С GUMROAD, KEYGEN ИЛИ СОБСТВЕННОГО СЕРВЕРА
Экспортируйте существующих клиентов в CSV с одной колонкой email, затем запустите это один раз для каждого продукта. Это массово выпустит по одной новой лицензии SublimeKeys на строку, с префиксом вашего бренда.
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"])Это выпускает совершенно новые ключи — старые строки ключей не сохраняются (мы принципиально не принимаем произвольные значения ключей). Отправьте клиентам их новый ключ по email, либо запускайте обе проверки параллельно в приложении в переходный период перед отключением старой системы.
ЛИМИТЫ ПЛАНА
FREE
1 продукт · 100 ключей · 5 устройств/ключ
PRO
5 продуктов · 1 000 ключей · 25 устройств/ключ
BUSINESS
неограниченно продуктов и ключей · 100 устройств/ключ
Достижение лимита никогда не ломает существующие ключи — они продолжают проверяться вечно. Вы просто не можете выпускать новые, пока не сделаете апгрейд. Понижение плана или отмена подписки тоже никогда ничего не удаляют.