Возможности и текущие ограничения
Публичный Base URL: https://new.rootactivation.ru/api/partner/v1. Локальная mock-среда запускается отдельно по адресу http://127.0.0.1:8765/api/partner/v1; её синтетические коды не предназначены для production.
Партнёр может проверять код, предварительно проверить аккаунт, запустить разрешённую активацию и читать свои операции. Вызов запуска возвращает оболочку {"operation": ...}, а выполнение продолжается в фоне. Для обновления состояния вызывайте POST /status с тем же кодом.
Доступность зависит от кода и конфигурации. Live-потоки покрывают Dorin ChatGPT Plus; ByPrice ChatGPT Plus Direct, ChatGPT Pro 20× Direct, ChatGPT Plus/Go iOS, SuperGrok Pro/Plus и Grok 7 дней; vip666ai для поддержанного продукта за префиксом PRO5SPECIAL- с типом погашения, возвращённым probe; и тарифы Gpay, которые подтвердил поставщик. Неизвестный тариф не становится поддерживаемым по одному префиксу. Dorin, ByPrice и vip666ai требуют серверный live-флаг, настройки/ключ (если требуется) и включённый провайдер; Gpay отдельно требует включения администратором и ключа. Партнёр также должен иметь разрешение allowActivation.
Проверка не запускает активацию. canActivate учитывает точный результат проверки, известный продукт, доступность провайдера и разрешение партнёра. Поддерживаемый VIP probe может выбрать тип chatgpt_account_id или chatgpt_session_json; передавайте сессию и путь аккаунта, указанные в ответе.
Успех подтверждается только распознанным ответом конкретного поставщика: Dorin activation.completed или проверкой статуса исходного кода used; ByPrice — completed для GPT или done для Grok на ожидаемом заказе; VIP — подтверждённый статус успеха на ожидаемом idempotency key/заказе; Gpay — совпадающий заказ с status=completed и terminal=true. Неизвестный ответ, review и истёкшее локальное ожидание не подтверждают подписку. Claude пока не поддерживается: для него нужна отдельная настройка учётных данных.
Маршруты, авторизованные ключом партнёра, показывают только операции этого партнёра. Если такой маршрут отклоняет код из-за чужого закрепления, ответ — общий 404 code_not_found, не раскрывающий владельца или наличие операции. Ошибки неизвестного или некорректного кода зависят от проверки и не обязаны иметь тот же статус. Клиентский API остаётся доступен по коду: покупатель, уже знающий код, может проверить его результат по обычному клиентскому сценарию.
Доступ и управление ключами
Администратор создаёт партнёра в панели. Полный ключ API показывается только при создании или ротации. Сервер хранит SHA-256-дайджест и последние четыре символа для подсказки; повторно показать полный ключ нельзя. Храните секрет на сервере интеграции и не передавайте его в браузер, URL, журнал или репозиторий. Управление партнёром и его ключом выполняет администратор; отдельного партнёрского API для этого или настройки поставщиков нет.
Все шесть маршрутов требуют заголовок:
Authorization: Bearer <PARTNER_API_KEY>
Accept: application/json
Для POST-запроса добавьте Content-Type: application/json; charset=utf-8. Cookie администратора не заменяет Bearer-ключ. Ключ партнёра не открывает панель администратора и не даёт доступа к секретам поставщиков.
Администратор может отключить партнёра, ограничить лимит, запретить новые preview/activate, отозвать ключ или выпустить новый. Лимит requestsPerMinute по умолчанию равен 60; допустимое значение — от 1 до 600 запросов в минуту. Отключение партнёра, allowActivation=false, ротация или отзыв ключа не отменяют уже выполняющиеся фоновые операции. При allowActivation=false вызовы preview и activate возвращают 403 activation_disabled; проверка, конфигурация и чтение списка операций остаются доступны, а проверка может вернуть canActivate:false.
Общие правила запросов
- Успешный вызов возвращает HTTP
200 и JSON. Ошибка использует оболочку {"error":{"code":"...","message":"..."}}.
- POST принимает JSON-объект только с полями маршрута; лишние поля отклоняются с
400 invalid_request. POST query-параметры не поддерживает. Передавайте код в теле, не в URL.
session — строка, внутри которой находится JSON-сессия, принятая существующим клиентским потоком для этого кода. Передавайте её как JSON-строку, а не вложенный объект. Общий предел — 32 768 символов; сценарий поставщика может ограничивать её сильнее.
- Максимальный размер HTTP-тела — 64 КиБ. Формат сессии и её более строгие пределы зависят от поставщика. Синтетические сессии и mock-сценарии доступны только в локальной среде.
- Лимит партнёра действует на все маршруты в общем скользящем 60-секундном окне. Он задаётся администратором в
requestsPerMinute (по умолчанию 60, диапазон 1–600). При превышении API возвращает 429 rate_limited. Проверки также могут иметь отдельный лимит поставщика и вернуть 429 check_rate_limited.
- Production-запросы должны идти по HTTPS на
new.rootactivation.ru. Сервер-серверный клиент может опустить Origin; если он передан, используйте origin https://new.rootactivation.ru. Локальный mock-клиент обращается только к loopback адресу http://127.0.0.1:8765.
- Cookie запрещены на маршрутах партнёра (
400 bearer_only). Сырая сессия обрабатывается во время вызова; она не возвращается, не записывается в партнёрский журнал и не попадает в HTTP-логи. Для восстановления операции сервис может сохранять маскированный ID/email и данные, нужные рабочему процессу.
Маршруты
GET/api/partner/v1/config
Возвращает версию API, разрешение активации для этого партнёра и рекомендуемую частоту опроса статуса.
{
"apiVersion": "v1",
"activationEnabled": true,
"pollIntervalMs": 1500
}
activationEnabled отражает только партнёрскую настройку allowActivation. Она не включает поставщика и не гарантирует, что конкретный код можно активировать. Проверяйте canActivate в ответе /check. Конфигурация не раскрывает локальные сценарии, sample session, секреты или внутренние параметры поставщиков.
POST/api/partner/v1/check
Проверяет код, не запуская активацию.
{"code":"<CODE>"}
Обычный тестовый ответ содержит product, codeStatus, canActivate, instruction, accountField, operation и checkedAt. Если операции ещё нет, operation равен null.
Синтетический пример ответа
{
"product": "ChatGPT Plus",
"codeStatus": "available",
"canActivate": true,
"instruction": "Для реальной активации введите код и проверьте нужный аккаунт.",
"accountField": "user.id",
"operation": null,
"checkedAt": "2026-10-11T10:00:00Z"
}
Ответ нормализован сервисом и не раскрывает сырые ответы поставщика, его секреты или внутренние поля заказов. Неизвестные поля API-контракта игнорируйте.
POST/api/partner/v1/preview
Проверяет допустимость кода и аккаунта по текущим настройкам. Код и сессия обязательны:
{"code":"<CODE>","session":"<JSON_SESSION_STRING>"}
В ответе — тариф и публичное представление аккаунта; поля account всегда содержат только email, маскированный ID, тип ID и источник.
{
"product": "ChatGPT Plus",
"account": {
"email": "demo@example.invalid",
"maskedId": "dem••••123",
"idType": "user.id",
"source": "customer"
}
}
preview не запускает активацию и не закрепляет код. Если партнёрский маршрут отклоняет код из-за операции другого владельца, он возвращает общий 404 code_not_found; другие ошибки проверки, отсутствующего или некорректного кода могут отличаться.
POST/api/partner/v1/activate
Запускает разрешённую операцию. Оба поля обязательны:
{"code":"<CODE>","session":"<JSON_SESSION_STRING>"}
Успешный вызов возвращает HTTP 200 с конвертом operation:
{
"operation": {
"id": "op_<32 lowercase hex characters>",
"product": "ChatGPT Plus",
"state": "queued",
"codeStatus": "processing",
"executionMode": "mock",
"createdAt": "2026-10-11T10:00:00Z",
"updatedAt": "2026-10-11T10:00:00Z",
"lastCheckedAt": "2026-10-11T10:00:00Z",
"account": {
"email": "demo@example.invalid",
"maskedId": "dem••••123",
"idType": "user.id",
"source": "customer"
},
"publicCode": null,
"message": "Тестовый запрос принят и ожидает обработки.",
"events": [
{"at":"2026-10-11T10:00:00Z","state":"queued","label":"Тестовый запрос принят в очередь"}
]
}
}
Ответ означает, что операция принята или уже существует, а не то, что она завершена. При первом запуске код атомарно закрепляется за партнёром. Партнёрские маршруты не раскрывают операции других владельцев; это ограничение авторизации партнёрского API не меняет поведение существующего клиентского API для покупателя, который уже передал тот же код.
Реальный код может запустить реальную активацию. Для mock-тестов используйте только синтетические TEST-… коды в локальной среде. Live-запуск возможен только для известного поддерживаемого продукта при включённом провайдере и разрешении партнёра. Не запускайте production-код ради проверки интеграции.
POST/api/partner/v1/status
Принимает исходный код:
{"code":"<CODE>"}
Возвращает тот же клиентский ответ, что и /check, включая вложенный operation, если он существует. Вложенный объект очищен от внутренних ID заказов и сырых статусов поставщика. Маршрут принимает код, а не operation.id; сохраните исходный код для последующего опроса.
GET/api/partner/v1/operations?page=1
Возвращает до 20 собственных операций, отсортированных от новых к старым. Если операций нет, ответ содержит пустую первую страницу.
{
"items": [
{
"id": "op_<32 lowercase hex characters>",
"product": "ChatGPT Plus",
"state": "running",
"codeStatus": "processing",
"executionMode": "mock",
"createdAt": "2026-10-11T10:00:00Z",
"updatedAt": "2026-10-11T10:00:02Z",
"lastCheckedAt": "2026-10-11T10:00:02Z",
"account": {"email":"demo@example.invalid","maskedId":"dem••••123","idType":"user.id","source":"customer"},
"publicCode": null,
"message": "Выполняется локальная тестовая операция.",
"events": [
{"at":"2026-10-11T10:00:00Z","state":"queued","label":"Тестовый запрос принят в очередь"},
{"at":"2026-10-11T10:00:02Z","state":"running","label":"Локальная тестовая операция началась"}
]
}
],
"total": 1,
"page": 1,
"pages": 1
}
Элементы используют ту же очищенную схему operation, что и ответ activate; список не содержит исходный код. Номер страницы должен быть положительным целым числом в существующем диапазоне.
Поля ответов
Ответ проверки похож на клиентский API. В партнёрском ответе могут присутствовать дополнительные поля проверки поставщика; этот список описывает основные стабильные поля и не является закрытым перечнем.
| Поле | Форма и смысл |
product | Название тарифа или продукта. |
codeStatus | Статус кода/заказа, а не состояние операции. Часто встречаются available, processing, used, unavailable и unknown. Не используйте это поле вместо operation.state и допускайте новые значения. |
canActivate | Булево разрешение для проверенного кода, известного продукта и текущих настроек провайдера/партнёра. При allowActivation=false проверка может успешно вернуть canActivate:false. |
accountField | Ожидаемый путь ID в JSON-строке session: user.id — $.user.id; account.id — $.account.id; userId для Grok — текущий путь $.session.userId (устаревший вариант $.userId тоже распознаётся). null означает, что проверка только для чтения не требует аккаунт. |
operation | null до создания операции или объект текущей операции. В ответах партнёра нет сырых ответов, статусов, идентификаторов заказа или других внутренних полей поставщика. |
operation.state | queued, running, reconciling, review, succeeded или failed. Это состояние приложения; оно отдельно от codeStatus. |
operation.executionMode | mock для локального сценария или real для реальной операции поставщика. |
operation.account | Публичные поля email, maskedId, idType, source. Email и ID маскируются и могут отсутствовать. |
operation.publicCode | Публичный код ситуации или null; не содержит сырой ответ поставщика. |
operation.events | История приложения: элементы с at, state, label. Время передаётся в ISO 8601 UTC с суффиксом Z. |
Для preview и activate поле session — строка с сериализованным JSON. Например, тело запроса для синтетического ChatGPT-кода (вложенные кавычки экранированы, секретов здесь нет):
{"code":"TEST-success-012345ABCDEF","session":"{\"status\":\"authenticated\",\"user\":{\"id\":\"synthetic-chatgpt-user-123456\",\"email\":\"chatgpt@example.invalid\"}}"}
Для Grok текущий формат использует вложенное session.userId; в этом примере код должен соответствовать локальному Grok-сценарию:
{"code":"TEST-grok-012345ABCDEF","session":"{\"status\":\"authenticated\",\"session\":{\"userId\":\"synthetic-grok-user-123456\",\"email\":\"grok@example.invalid\"}}"}
Отправляйте сессию только по защищённому каналу в теле запроса. Не подставляйте в документацию, тесты или журналы реальные пользовательские сессии.
Состояния и опрос
| Состояние | Значение |
queued | Запрос принят и ожидает обработки. |
running | Локальная операция или задача поставщика выполняется. |
reconciling | Сервис уточняет результат уже запущенной операции. |
review | Операция ожидает ручной проверки. |
succeeded | Успех подтверждён. |
failed | Операция завершена для приложения. При коде тайм-аута исход у поставщика может оставаться неизвестным. |
Типичный путь: queued → running → succeeded или queued → running → failed. Сценарии поставщика могут включать reconciling или review. succeeded и failed — терминальные состояния этой операции; новые версии могут добавлять промежуточные состояния, поэтому неизвестное состояние не должно ломать клиент.
После запуска опрашивайте POST /status с тем же кодом с рекомендуемым интервалом из /config — сейчас 1500 мс. Состояние сохраняется сервером и может оставаться прежним между запросами. Опрос API не управляет частотой внутренних запросов к поставщику.
Если клиент потерял ответ /activate или получил сетевой тайм-аут, не запускайте активацию повторно автоматически: запуск мог уже начаться. Проверьте тот же код через /status или найдите операцию через /operations. Dorin, ByPrice и vip666ai прекращают локальное ожидание после более чем 180 секунд без подтверждённого изменения статуса. Это не отменяет запрос у поставщика и не доказывает отсутствие подписки. У Gpay собственное восстановление по заказу. При неопределённом результате передайте продавцу publicCode, если он есть, и уточните исход.
Операция не возвращает исходный код. Партнёру следует хранить код у себя с соответствующими мерами защиты. Ответы партнёра исключают внутренние идентификаторы заказов и статусы поставщиков.
Ошибки и восстановление
Все ошибки используют оболочку:
{"error":{"code":"invalid_partner_key","message":"Проверьте ключ партнёра."}}
| HTTP | Коды | Действие |
| 400 | invalid_request, invalid_json, invalid_code, invalid_session, missing_account_id, invalid_page, invalid_host, bearer_only | Исправить тело, формат входных данных, страницу или Host; на этих маршрутах не передавать Cookie. |
| 401 | invalid_partner_key | Проверить Bearer-заголовок и статус ключа; после ротации использовать новый ключ. |
| 403 | partner_disabled, activation_disabled, same_origin_required | Доступ или запуск запрещён настройкой, либо переданный Origin не совпал с origin запроса. |
| 404 | code_not_found | При отказе по владению ответ не раскрывает, кому принадлежит код или существует ли операция. Для некорректного/неизвестного кода и ошибки проверки возможны другие статусы и коды. |
| 409 | activation_in_progress, code_not_activatable, provider_disabled, Gpay preflight-коды | Сначала выяснить текущий статус; не повторять activate вслепую. Случаи Gpay описаны ниже. |
| 429 | rate_limited, check_rate_limited | Снизить частоту. Сообщение объясняет общий лимит партнёра или ограничение проверки поставщика. |
| 502–503 | Ошибка поставщика или provider_disabled | Проверка или поставщик временно недоступны; ошибка не подтверждает допустимость активации. |
| 500 | internal_error | Для запроса активации сначала выяснить текущее состояние через status/operations. |
Клиенту следует ветвиться по HTTP-коду и error.code. Текст message можно показать пользователю, но не использовать как машинный идентификатор.
Предварительная проверка Gpay
Для реального Gpay код и аккаунт должны пройти предварительную проверку до запуска; после preview используйте тот же аккаунт и ту же сессию в activate. Предварительная проверка действует пять минут.
| HTTP / код | Восстановление |
409 preflight_required | Выполнить POST /preview с кодом и сессией предполагаемого аккаунта, затем вызвать /activate с той же сессией. |
409 preflight_expired | Повторить /preview с тем же аккаунтом и сессией, затем оперативно повторить запуск. Это безопасно лишь если предшествующая попытка запуска точно не началась; при сетевом тайм-ауте сначала опросить /status. |
409 preflight_account_mismatch | Сессия не соответствует предварительно проверенному аккаунту. Не переключать аккаунт между /preview и /activate; повторно выполнить проверку с нужной сессией, если запуск ещё не начинался. |
409 account_unusable | Поставщик не разрешил запуск для этого аккаунта. Не повторять с тем же аккаунтом; уточнить у продавца, какой аккаунт допустим. |
Повторяйте запуск только при однозначном ответе, что он не был принят. Если соединение оборвалось после отправки /activate, опрашивайте тот же код и не отправляйте новый запуск автоматически.
Локальная mock-проверка (опционально)
Этот пример обращается только к локальному серверу 127.0.0.1:8765, а не к production API. Тестовые коды и sample session недоступны на публичном сервере.
- Запустите приложение и создайте партнёра в панели администратора. Сохраните ключ на сервере интеграции, включите партнёра и разрешите ему запуск теста (
allowActivation).
- В клиентском интерфейсе откройте Тестовые сценарии и создайте код для сценария «Успешная активация». Он имеет вид
TEST-success-<12 заглавных hex-символов>. Это локальная имитация; она не отправляет заказ поставщику и не оформляет подписку.
- Установите переменные окружения
PARTNER_API_KEY и TEST_CODE. Пример ниже прекращает работу до первого сетевого запроса, если код не соответствует точному формату этого тестового сценария.
Пример Python 3 с urllib выполняет полный mock-путь: /config → /check → /preview → один вызов /activate → опрос /status. Для ChatGPT тестовая сессия использует только синтетические значения:
import json
import os
import re
import time
import urllib.error
import urllib.request
BASE = "http://127.0.0.1:8765/api/partner/v1"
API_KEY = os.environ["PARTNER_API_KEY"]
TEST_CODE = os.environ["TEST_CODE"]
# Fail closed before sending any request; never substitute a real code.
if not re.fullmatch(r"TEST-success-[A-F0-9]{12}", TEST_CODE):
raise SystemExit("TEST_CODE must be a locally generated TEST-success code")
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Accept": "application/json"}
SESSION = json.dumps({
"status": "authenticated",
"user": {"id": "synthetic-chatgpt-user-123456", "email": "chatgpt@example.invalid"},
})
def call(method, path, payload=None):
data = None if payload is None else json.dumps(payload).encode("utf-8")
headers = dict(HEADERS)
if data is not None:
headers["Content-Type"] = "application/json; charset=utf-8"
request = urllib.request.Request(BASE + path, data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(request, timeout=15) as response:
return response.status, json.load(response)
except urllib.error.HTTPError as error:
return error.code, json.load(error)
def require_ok(result):
status, body = result
if status != 200:
raise RuntimeError(f"HTTP {status}: {body}")
return body
config = require_ok(call("GET", "/config"))
if not config["activationEnabled"]:
raise SystemExit("Enable this partner's test activation in local admin first")
checked = require_ok(call("POST", "/check", {"code": TEST_CODE}))
if checked.get("codeStatus") != "available" or not checked.get("canActivate"):
raise SystemExit("The generated mock code is not available for this partner")
require_ok(call("POST", "/preview", {"code": TEST_CODE, "session": SESSION}))
# Send activate once only. If the connection times out, recover by polling status;
# do not send a second activate request.
try:
launch = require_ok(call("POST", "/activate", {"code": TEST_CODE, "session": SESSION}))
print("Accepted:", launch["operation"].get("state"))
except (TimeoutError, urllib.error.URLError) as error:
print("Launch response was ambiguous; polling the same test code:", error)
terminal = {"succeeded", "failed"}
deadline = time.monotonic() + 30
while time.monotonic() < deadline:
status = require_ok(call("POST", "/status", {"code": TEST_CODE}))
operation = status.get("operation")
if operation:
print("Current state:", operation.get("state"))
if operation.get("state") in terminal:
break
time.sleep(config["pollIntervalMs"] / 1000)
else:
print("Still unresolved; inspect GET /operations?page=1. Do not launch again.")
Активация в этом примере строго ограничена синтетическим TEST-success-… кодом и выполняется ровно один раз. Для Grok используйте отдельный синтетический TEST-grok-… код и строку сессии с session.userId, показанную выше. Не передавайте реальные коды, пользовательские сессии или GPAY-…. Партнёрский API не создаёт тест-коды и не выдаёт список сценариев; тесты не должны обращаться к внешним API.
Совместимость и эксплуатация
apiVersion обозначает контракт v1. Клиент должен игнорировать неизвестные поля, учитывать operation: null и не полагаться на наличие email или publicCode. Даты — ISO 8601 UTC с суффиксом Z. Элементы /operations используют ту же очищенную схему операции, что и ответ запуска. Партнёрские ответы содержат только нормализованные поля этого документа и не раскрывают сырые ответы поставщиков или секреты.