StealthSurf VPNStealthSurf VPN
Доступные методыПрофиль

Конструктор подписок

Методы для управления пользовательскими подписками: создание, изменение, удаление.

Обзор

Модуль для работы с пользовательскими подписками. Базовый путь: /profile/custom-subscriptions. Доступны методы GET/POST/PATCH/PUT/DELETE. Позволяет собирать собственные подписки из конфигов/платных опций, управлять устройствами, настройками отображения, маршрутизацией и Xray JSON-режимом.

Общие схемы раздела

  • CustomSubscriptionData: { id, title, subscription_key (расшифрован), items_count }.
  • CustomSubscriptionDetailData: CustomSubscriptionData + items: CustomSubscriptionItemData[].
  • CustomSubscriptionItemData: { id, item_type, item_reference_id, item_index?, position, resolved_title, is_valid, server_config? }.
  • CustomSubscriptionItemBody (используется при создании/замене items): item_type (@IsIn(['user_config','cloud_server_config','paid_option','paid_option_index','paid_option_config'])), item_reference_id (@IsInt @Min(1)), item_index? (@IsInt @Min(0) @Max(20)).

GET /profile/custom-subscriptions

Получить список пользовательских подписок (сортировка по created_at DESC).

Rate Limit: глобальный (60 req/min)

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: Array<{
    id: number
    title: string
    subscription_key: string
    items_count: number
  }>
}

GET /profile/custom-subscriptions/available-items

Получить доступные элементы для создания подписки.

Rate Limit: глобальный (60 req/min)

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/available-items" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    configs: Array<{
      id: number
      title: string
      location_emoji?: string
      expires_at: number
      is_online: boolean
      source: "user_config" | "cloud_server_config"
      cloud_server_id?: number   // только для source: "cloud_server_config"
    }>
    paid_options: Array<{
      id: number
      title: string
      expires_at: number
      configs: Array<{
        type: "index"
        users_paid_option_id: number
        expires_at: number
        index: number
        original_title: string
        custom_title: string | null
        is_online: boolean
      } | {
        type: "server"
        users_paid_option_id: number
        expires_at: number
        id: number
        server_id: number
        title: string             // Пользовательское название конфига
        resolved_title: string    // Итоговое отображаемое название
        is_online: boolean
      }>
    }>
  }
}

Конфиги с протоколом amnezia-wg исключены из выдачи.


GET /profile/custom-subscriptions/:id

Получить детали пользовательской подписки (items по position ASC).

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    id: number
    title: string
    subscription_key: string
    items_count: number
    items: Array<{
      id: number
      item_type: string
      item_reference_id: number
      item_index: number | null
      position: number
      resolved_title: string | null
      is_valid: boolean
      server_config: {
        id: number
        server_id: number
        location_id: number
        title: string
        protocol: string
      } | null
    }>
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

POST /profile/custom-subscriptions

Создать пользовательскую подписку.

Rate Limit: 3 req / 5 sec

Request Body

FieldTypeRequiredDescription
titlestringДаНазвание (1-64 символа)
itemsArrayДаЭлементы подписки (1-50)
items[].item_typestringДаuser_config | cloud_server_config | paid_option | paid_option_index | paid_option_config
items[].item_reference_idnumberДаID элемента
items[].item_indexnumberНетИндекс для paid_option_index (0-20)

Пример запроса

curl -X POST "https://api.stealthsurf.net/profile/custom-subscriptions" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Моя подписка",
    "items": [
      { "item_type": "user_config", "item_reference_id": 123 },
      { "item_type": "paid_option_index", "item_reference_id": 456, "item_index": 0 }
    ]
  }'

Ответ

{
  status: true,
  statusCode: 201,
  data: {
    id: number
    title: string
    subscription_key: string
    items_count: number
    items: Array<{
      id: number
      item_type: string
      item_reference_id: number
      item_index: number | null
      position: number
      resolved_title: string | null
      is_valid: boolean
      server_config: {
        id: number
        server_id: number
        location_id: number
        title: string
        protocol: string
      } | null
    }>
  }
}

Ошибки

errorCodemessageКогда
28custom subscription limit reachedУ пользователя уже 25 кастомных подписок
3bad requestПередано больше 50 элементов
30custom subscription invalid itemЭлемент не принадлежит пользователю, истёк срок его действия либо item_index выходит за пределы доступных конфигов

PATCH /profile/custom-subscriptions/:id/title

Обновить название подписки.

Rate Limit: 5 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
titlestringДаНовое название (1-64 символа)

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/title" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Новое название"
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    id: number
    title: string
    subscription_key: string
    items_count: number
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PUT /profile/custom-subscriptions/:id/items

Заменить элементы подписки.

Rate Limit: 3 req / 2 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
itemsArrayДаНовые элементы (заменяют существующие, 1-50)
items[].item_typestringДаuser_config | cloud_server_config | paid_option | paid_option_index | paid_option_config
items[].item_reference_idnumberДаID элемента
items[].item_indexnumberНетИндекс для paid_option_index (0-20)

Пример запроса

curl -X PUT "https://api.stealthsurf.net/profile/custom-subscriptions/123/items" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "item_type": "user_config", "item_reference_id": 789 }
    ]
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    id: number
    title: string
    subscription_key: string
    items_count: number
    items: Array<{
      id: number
      item_type: string
      item_reference_id: number
      item_index: number | null
      position: number
      resolved_title: string | null
      is_valid: boolean
      server_config: {
        id: number
        server_id: number
        location_id: number
        title: string
        protocol: string
      } | null
    }>
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
3bad requestПередано больше 50 элементов
30custom subscription invalid itemЭлемент не принадлежит пользователю, истёк срок его действия либо item_index выходит за пределы доступных конфигов

PATCH /profile/custom-subscriptions/:id/items/order

Изменить порядок элементов подписки.

Rate Limit: 5 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
item_idsnumber[]ДаID элементов в нужном порядке (1-50, ровно существующие ID, без дубликатов)

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/items/order" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "item_ids": [3, 1, 2]
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    id: number
    title: string
    subscription_key: string
    items_count: number
    items: Array<{
      id: number
      item_type: string
      item_reference_id: number
      item_index: number | null
      position: number
      resolved_title: string | null
      is_valid: boolean
      server_config: {
        id: number
        server_id: number
        location_id: number
        title: string
        protocol: string
      } | null
    }>
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
3bad requestНабор item_ids не совпадает с текущими элементами подписки или содержит дубликаты

POST /profile/custom-subscriptions/:id/reset-key

Переиздать ключ подписки.

Rate Limit: 2 req / 10 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X POST "https://api.stealthsurf.net/profile/custom-subscriptions/123/reset-key" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    id: number
    title: string
    subscription_key: string    // Новый ключ
    items_count: number
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

После переиздания ключа старый ключ перестанет работать. Убедитесь, что обновили ключ во всех приложениях.


POST /profile/custom-subscriptions/:id/share/vk-document

Поделиться подпиской через VK-документ: конфиги выгружаются в текстовый документ, в ответе возвращается прямая ссылка на него.

Rate Limit: 2 req / 10 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X POST "https://api.stealthsurf.net/profile/custom-subscriptions/123/share/vk-document" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    url: string           // Прямая ссылка на VK-документ
    expires_at: number    // Unix timestamp истечения ссылки
    ttl: number           // Время жизни ссылки в секундах
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
3bad requestНе удалось расшифровать ключ подписки
90vk share failedПодписка не содержит конфигов либо загрузка документа в VK не удалась

DELETE /profile/custom-subscriptions/:id

Удалить подписку вместе с её элементами и привязанными устройствами.

Rate Limit: 3 req / 2 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X DELETE "https://api.stealthsurf.net/profile/custom-subscriptions/123" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

Получить зашифрованные ссылки на подписку для клиентов Happ и INCY.

Rate Limit: 3 req / 60 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/encrypted-subscription-link" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    happ: string    // Ссылка вида happ://crypt4/...
    incy: string    // Ссылка вида incy://crypt1/...
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
3bad requestНе удалось расшифровать ключ подписки

Настройки отображения подписки

Методы для управления настройками отображения кастомной подписки в приложениях (заголовок профиля, объявление, ссылки, кастомные заголовки ответа).


GET /profile/custom-subscriptions/:id/display/settings

Получить настройки отображения подписки.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/display/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    profile_title: string | null
    announce: string | null
    announce_url: string | null
    support_url: string | null
    profile_web_page_url: string | null
    custom_headers: Array<{
      name: string
      value: string
    }> | null
    profile_update_interval: number   // по умолчанию 12 (часы)
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PATCH /profile/custom-subscriptions/:id/display/settings

Обновить настройки отображения подписки. Передаются только изменяемые поля, остальные сохраняются.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
profile_titlestringНетЗаголовок профиля (MaxLength 25)
announcestringНетТекст объявления с разметкой цвета {#HEX}текст{/} (MaxLength 200)
announce_urlstringНетСсылка объявления (валидный URL)
support_urlstringНетСсылка поддержки (валидный URL)
profile_web_page_urlstringНетСсылка на веб-страницу профиля (валидный URL)
custom_headersobject[] | nullНетКастомные заголовки ответа при отдаче подписки (макс. 20), null очищает список. Каждый: name (string, 1-64), value (string, MaxLength 1024). Нормализуются на сервере (имена в нижнем регистре, проверка blacklist, без дубликатов, суммарный размер имён и значений не более 8192 символов)
profile_update_intervalnumberНетИнтервал автообновления, ч (@IsInt, @Min(1), @Max(12))

Имя заголовка должно соответствовать регулярному выражению:

/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/

Запрещены служебные заголовки (cookie, authorization, content-type, host, announce, profile-title и т. п.), а также имена, начинающиеся с access-control-, x-accel-, x-sendfile, x-forwarded-, cross-origin-.

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/display/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "profile_title": "My VPN",
    "announce": "ℹ️ {#2181CD}Update{/} subscription",
    "support_url": "https://t.me/my_support",
    "custom_headers": [
      { "name": "x-subscription-owner", "value": "family" }
    ]
  }'

Ответ

Такой же как GET /profile/custom-subscriptions/:id/display/settings.

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
3bad requestНекорректные custom_headers: не массив, больше 20 элементов, пустое или слишком длинное имя, недопустимые символы, дубликат имени, запрещённый заголовок либо превышение суммарного размера 8192 символа

XRay шаблон подписки

Методы для управления XRay шаблоном (JSON mode) кастомной подписки.


GET /profile/custom-subscriptions/:id/xray-template/settings

Получить настройки XRay JSON mode для подписки.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/xray-template/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    json_mode: boolean
    json_default_config_tag: string | null    // устарело
    fragment: boolean
    auto_select_enabled: boolean
    auto_select_name: string | null
    global_quick_toggles: {
      ruDirect: boolean
      androidAutoDirect: boolean
      ruWhitelistDirect: boolean
      lanDirect: boolean
      bittorrentDirect: boolean
      blockQuic: boolean
      blockAds: boolean
      gameDownloadsDirect: boolean
      blockPorn: boolean
    }
    custom_auto_selects: Array<{
      id: number
      name: string
      strategy: "leastPing" | "leastLoad" | "random" | "roundRobin"
      config_tags: string[]
    }>
    global_routing_rules: object[]     // Глобальные правила маршрутизации XRay
    dns: {
      resolve_direct_ipv4: boolean     // Главный выключатель клиентского DNS-блока
      dns_preset?: string              // Пресет DoH-резолвера
      custom_dns_url?: string          // Пользовательский DoH URL при dns_preset: "custom"
    }
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PATCH /profile/custom-subscriptions/:id/xray-template/settings

Обновить настройки XRay JSON mode для подписки. При выключении json_mode сбрасываются fragment, авто-выбор, быстрые переключатели, DNS-блок, пользовательские балансировщики и сохранённый XRay-шаблон подписки.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
json_modebooleanНетВключить JSON mode для подписки
json_default_config_tagstringНет(Устарело) Тег исходящего по умолчанию. Формат ^(config|cloud|option|ext)-\d+$
fragmentbooleanНетВключить TLS-фрагмент (обход DPI)
auto_select_enabledbooleanНетВключить виртуальный конфиг авто-выбора с балансировщиком leastPing
auto_select_namestringНетОтображаемое имя конфига авто-выбора (MaxLength 128)
global_quick_togglesobjectНетЧастичное слияние. Допустимые ключи: ruDirect, androidAutoDirect, ruWhitelistDirect, lanDirect, bittorrentDirect, blockQuic, blockAds, gameDownloadsDirect, blockPorn. Каждое значение — boolean
custom_auto_selectsobject[]НетНабор авто-выборов (заменяет существующие). @ArrayMaxSize(10), @ValidateNested({each})
global_routing_rulesunknown[]НетПолная замена глобальных правил маршрутизации XRay (макс. 100)
dnsobjectНетБлок клиентского DNS (частичное обновление)

CustomAutoSelectBody: id? (@IsInt, @Min(1); для новых записей не указывается и назначается сервером), name (@Length(1,64)), strategy? (@IsIn(['leastPing','leastLoad','random','roundRobin']), по умолчанию leastPing), config_tags (@ArrayMinSize(2) @ArrayMaxSize(50), формат config-N/option-N/cloud-N/ext:N:M). Все поля тела необязательны.

DnsSettingsBody:

FieldTypeRequiredDescription
resolve_direct_ipv4booleanНетРезолвить прямой (не-VPN) трафик по IPv4; главный выключатель клиентского DNS-блока
dns_presetstringНетПресет DoH-резолвера: cloudflare, google, quad9, adguard, adguard_family, yandex, comss, mullvad или custom
custom_dns_urlstringНетПользовательский DoH URL (только https), обязателен при dns_preset: "custom"

Правила для global_routing_rules: каждое правило — объект с type: "field"; допустимые поля type, domain, ip, protocol, port, network, outboundTag; outboundTag обязателен и может быть только direct, block или proxy; должно присутствовать хотя бы одно условие (domain, ip, protocol либо port/network); protocol — из набора http, tls, quic, bittorrent; networktcp, udp или tcp,udp.

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/xray-template/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "json_mode": true,
    "fragment": false,
    "global_quick_toggles": {
      "ruDirect": true
    }
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    json_mode: boolean
    json_default_config_tag: string | null    // устарело
    fragment: boolean
    auto_select_enabled: boolean
    auto_select_name: string | null
    global_quick_toggles: {
      ruDirect: boolean
      androidAutoDirect: boolean
      ruWhitelistDirect: boolean
      lanDirect: boolean
      bittorrentDirect: boolean
      blockQuic: boolean
      blockAds: boolean
      gameDownloadsDirect: boolean
      blockPorn: boolean
    }
    custom_auto_selects: Array<{
      id: number
      name: string
      strategy: "leastPing" | "leastLoad" | "random" | "roundRobin"
      config_tags: string[]
    }>
    global_routing_rules: object[]     // Глобальные правила маршрутизации XRay
    dns: {
      resolve_direct_ipv4: boolean     // Главный выключатель клиентского DNS-блока
      dns_preset?: string              // Пресет DoH-резолвера
      custom_dns_url?: string          // Пользовательский DoH URL при dns_preset: "custom"
    }
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
75no xray-compatible configs available for json modeВключение json_mode, когда в подписке нет конфигов, совместимых с XRay
3bad requestВ global_quick_toggles передан неизвестный ключ или не-boolean значение
77invalid routing rulesНекорректные global_routing_rules: больше 100 правил, недопустимые поля, отсутствие условия или недопустимый outboundTag
55invalid dns serverПри dns_preset: "custom" не передан custom_dns_url или указан небезопасный хост

GET /profile/custom-subscriptions/:id/xray-template (устарело)

Получить XRay шаблон подписки.

Эндпоинт устарел, используйте xray-template/settings.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/xray-template" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    template: string          // XRay шаблон (JSON)
    is_custom: boolean
    created_at: number        // Unix timestamp
    updated_at: number        // Unix timestamp
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PUT /profile/custom-subscriptions/:id/xray-template (устарело)

Сохранить XRay шаблон подписки.

Эндпоинт устарел, используйте xray-template/settings.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
templatestringДаXRay JSON-шаблон (без outbounds, MaxLength 32768)

Пример запроса

curl -X PUT "https://api.stealthsurf.net/profile/custom-subscriptions/123/xray-template" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "{...}"
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    template: string          // XRay шаблон (JSON)
    is_custom: boolean
    created_at: number        // Unix timestamp
    updated_at: number        // Unix timestamp
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
73xray template invalidНеверный Xray-шаблон

DELETE /profile/custom-subscriptions/:id/xray-template (устарело)

Сбросить XRay шаблон подписки к значениям по умолчанию.

Эндпоинт устарел, используйте xray-template/settings.

Rate Limit: 3 req / 2 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X DELETE "https://api.stealthsurf.net/profile/custom-subscriptions/123/xray-template" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

Устройства подписки

Методы для управления устройствами кастомной подписки.


GET /profile/custom-subscriptions/:id/devices

Получить список устройств подписки (по last_seen_at DESC).

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Query Parameters

ParameterTypeRequiredDescription
pagenumberНетНомер страницы (по умолчанию: 1)
limitnumberНетЗаписей на странице (1-100, по умолчанию: 20)

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices?page=1&limit=20" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    devices: Array<{
      id: number
      title: string | null
      device_name: string
      device_type: string           // ios, android, windows, macos, linux
      device_model: string
      os_version: string
      is_blocked: boolean
      is_approved: boolean          // Подтверждено владельцем подписки
      country: string | null
      city: string | null
      isp: string | null
      last_seen_at: number          // Unix timestamp
      created_at: number            // Unix timestamp
    }>
    total: number
    page: number
    limit: number
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

GET /profile/custom-subscriptions/:id/devices/settings

Получить настройки устройств подписки.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    block_unknown_devices: boolean
    device_limit: number            // 0 = безлимит
    require_approval: boolean       // Требовать подтверждение новых устройств
    force_ipv6: boolean
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PATCH /profile/custom-subscriptions/:id/devices/settings

Обновить настройки устройств подписки. Передаются только изменяемые поля, остальные сохраняются.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Request Body

FieldTypeRequiredDescription
block_unknown_devicesbooleanНетБлокировать приложения без идентификатора устройства
device_limitnumberНетЛимит устройств (0-100, 0 = безлимит)
require_approvalbooleanНетТребовать подтверждение владельцем для каждого нового устройства. Новые устройства без hardware ID отклоняются, ранее подтверждённые продолжают работать
force_ipv6booleanНетПринудительно отдавать IPv6-адреса в подписке

При включении block_unknown_devices (переход из false в true) все ранее записанные fingerprint-устройства подписки удаляются.

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/settings" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "block_unknown_devices": false,
    "device_limit": 5
  }'

Ответ

Такой же как GET /profile/custom-subscriptions/:id/devices/settings.

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

PATCH /profile/custom-subscriptions/:id/devices/:deviceId/title

Переименовать устройство.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
deviceIdnumberДаID устройства

Request Body

FieldTypeRequiredDescription
titlestringДаНазвание устройства (1-64 символа)

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/456/title" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "mom"
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
40device not foundУстройство не найдено

PATCH /profile/custom-subscriptions/:id/devices/:deviceId/blocked

Заблокировать или разблокировать устройство. При разблокировке устройство одновременно помечается подтверждённым.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
deviceIdnumberДаID устройства

Request Body

FieldTypeRequiredDescription
is_blockedbooleanДаЗаблокировать (true) или разблокировать (false) устройство

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/456/blocked" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "is_blocked": true
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
40device not foundУстройство не найдено

PATCH /profile/custom-subscriptions/:id/devices/:deviceId/approval

Подтвердить устройство, ожидающее одобрения: снимает блокировку и выставляет is_approved: true.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
deviceIdnumberДаID устройства

Пример запроса

curl -X PATCH "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/456/approval" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
40device not foundУстройство не найдено

DELETE /profile/custom-subscriptions/:id/devices/:deviceId

Удалить устройство из подписки.

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
deviceIdnumberДаID устройства

Пример запроса

curl -X DELETE "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices/456" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена
40device not foundУстройство не найдено

DELETE /profile/custom-subscriptions/:id/devices

Удалить все устройства из подписки.

Rate Limit: 1 req / 2 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Пример запроса

curl -X DELETE "https://api.stealthsurf.net/profile/custom-subscriptions/123/devices" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    deleted_count: number  // Количество удалённых устройств
  }
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

Маршрутизация подписки

Методы для управления маршрутизацией (routing) и туннелями на уровне отдельных конфигов кастомной подписки.


GET /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_id

Получить настройки маршрутизации для конкретного конфига подписки. Если запись не сохранена, возвращаются пустые правила и эффективные значения, унаследованные от глобальных настроек.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
config_typestringДаОдин из: user_config, paid_option_config, paid_option_index, cloud_server_config, auto_select
config_reference_idnumberДаID конфига соответствующего типа (для auto_select — ID балансировщика из custom_auto_selects, 0 для встроенного)

Query Parameters

ParameterTypeRequiredDescription
config_indexnumberНетИндекс конфига (по умолчанию: 0)

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/routing/configs/user_config/2?config_index=0" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    routing_rules: object[]
    tunnels: Array<{
      tag: string
      source_config_type: string
      source_config_id: number
      source_config_index: number
      source_config_label: string
    }>
    quick_toggle_overrides: object | null
    effective_quick_toggles: {
      ruDirect: boolean
      androidAutoDirect: boolean
      ruWhitelistDirect: boolean
      lanDirect: boolean
      bittorrentDirect: boolean
      blockQuic: boolean
      blockAds: boolean
      gameDownloadsDirect: boolean
      blockPorn: boolean
    }
    dns_overrides: object | null    // null = наследуются глобальные настройки
    effective_dns: {
      resolve_direct_ipv4: boolean
      dns_preset?: string
      custom_dns_url?: string
    }
  }
}

Ошибки

errorCodemessageКогда
3bad requestНедопустимый config_type
27custom subscription not foundПодписка не найдена

PUT /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_id

Сохранить настройки маршрутизации для конкретного конфига подписки (полная замена сохранённой записи).

Rate Limit: 3 req / 1 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
config_typestringДаОдин из: user_config, paid_option_config, paid_option_index, cloud_server_config, auto_select
config_reference_idnumberДаID конфига соответствующего типа (для auto_select — ID балансировщика из custom_auto_selects, 0 для встроенного)

Query Parameters

ParameterTypeRequiredDescription
config_indexnumberНетИндекс конфига (по умолчанию: 0)

Request Body

FieldTypeRequiredDescription
routing_rulesunknown[]ДаМассив правил маршрутизации XRay (макс. 100). Каждое правило: type: "field", обязательный outboundTag или balancerTag и поля только из набора type, domain, ip, port, sourcePort, network, source, user, inboundTag, protocol, attrs, outboundTag, balancerTag
tunnelsobject[]ДаМассив туннелей (макс. 50). Для config_type: "auto_select" должен быть пустым
tunnels[].tagstringДаТег исходящего для этого туннеля. Не может быть direct, block, dns-out, fragment, proxy и не должен повторяться
tunnels[].source_config_typestringДаТип конфига-источника
tunnels[].source_config_idnumberДаID конфига-источника
tunnels[].source_config_indexnumberНетИндекс конфига-источника (для paid_option_index)
quick_toggle_overridesobject | nullНетПереопределения быстрых переключателей (null = наследовать глобальные). Допустимые ключи: ruDirect, androidAutoDirect, ruWhitelistDirect, lanDirect, bittorrentDirect, blockQuic, blockAds, gameDownloadsDirect, blockPorn; значения — boolean
dns_overridesobject | nullНетПереопределение клиентского DNS для этого конфига (поля см. в DnsSettingsBody), null = наследовать глобальные

Пример запроса

curl -X PUT "https://api.stealthsurf.net/profile/custom-subscriptions/123/routing/configs/user_config/2?config_index=0" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY" \
  -H "Content-Type: application/json" \
  -d '{
    "routing_rules": [
      { "type": "field", "domain": ["geosite:google"], "outboundTag": "my-tunnel" }
    ],
    "tunnels": [
      { "tag": "my-tunnel", "source_config_type": "user_config", "source_config_id": 2 }
    ],
    "quick_toggle_overrides": null
  }'

Ответ

{
  status: true,
  statusCode: 200,
  data: {
    routing_rules: object[]       // Сохранённые правила
    tunnels: Array<{
      tag: string
      source_config_type: string
      source_config_id: number
      source_config_index: number
      source_config_label: string
    }>
    quick_toggle_overrides: object | null
    effective_quick_toggles: {
      ruDirect: boolean
      androidAutoDirect: boolean
      ruWhitelistDirect: boolean
      lanDirect: boolean
      bittorrentDirect: boolean
      blockQuic: boolean
      blockAds: boolean
      gameDownloadsDirect: boolean
      blockPorn: boolean
    }
    dns_overrides: object | null    // null = наследуются глобальные настройки
    effective_dns: {
      resolve_direct_ipv4: boolean
      dns_preset?: string
      custom_dns_url?: string
    }
  }
}

Ошибки

errorCodemessageКогда
3bad requestНедопустимый config_type
27custom subscription not foundПодписка не найдена
1not foundКонфиг не принадлежит пользователю либо для auto_select указан несуществующий ID балансировщика
77INVALID_ROUTING_RULESНекорректные routing_rules, tunnels или quick_toggle_overrides
84AUTO_SELECT_NO_TUNNELSДля config_type: "auto_select" переданы туннели
82RESERVED_TAG_NAMEТег туннеля совпадает с зарезервированным (direct, block, dns-out, fragment, proxy)
81DUPLICATE_TUNNEL_TAGТеги туннелей повторяются
80TUNNEL_SELF_REFERENCEТуннель ссылается на сам редактируемый конфиг
78TUNNEL_CONFIG_NOT_FOUNDКонфиг-источник туннеля не найден или не принадлежит пользователю
79TUNNEL_INCOMPATIBLE_PROTOCOLПротокол конфига-источника несовместим с XRay
83UNKNOWN_OUTBOUND_TAGВ правиле указан outboundTag, не соответствующий ни одному туннелю
55INVALID_DNS_SERVERВ dns_overrides при dns_preset: "custom" не передан custom_dns_url или указан небезопасный хост

DELETE /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_id

Сбросить настройки маршрутизации для конкретного конфига подписки.

Rate Limit: 3 req / 2 sec

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки
config_typestringДаОдин из: user_config, paid_option_config, paid_option_index, cloud_server_config, auto_select
config_reference_idnumberДаID конфига соответствующего типа (для auto_select — ID балансировщика из custom_auto_selects, 0 для встроенного)

Query Parameters

ParameterTypeRequiredDescription
config_indexnumberНетИндекс конфига (по умолчанию: 0)

Пример запроса

curl -X DELETE "https://api.stealthsurf.net/profile/custom-subscriptions/123/routing/configs/user_config/2?config_index=0" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: true
}

Ошибки

errorCodemessageКогда
3bad requestНедопустимый config_type
27custom subscription not foundПодписка не найдена

GET /profile/custom-subscriptions/:id/routing/available-tunnels

Получить конфиги, доступные для использования в качестве туннелей внутри подписки. Возвращаются только XRay-совместимые конфиги, входящие в состав этой подписки.

Rate Limit: глобальный (60 req/min)

URL Parameters

ParameterTypeRequiredDescription
idnumberДаID подписки

Query Parameters

ParameterTypeRequiredDescription
exclude_config_typestringНетТип конфига для исключения из результата
exclude_config_idnumberНетID конфига для исключения из результата

Пример запроса

curl -X GET "https://api.stealthsurf.net/profile/custom-subscriptions/123/routing/available-tunnels" \
  -H "Authorization: Bearer stlth_XXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYY"

Ответ

{
  status: true,
  statusCode: 200,
  data: Array<{
    config_type: string
    config_id: number
    config_index?: number    // Только для config_type: "paid_option_index"
    tag: string              // config-N / option-N / cloud-N / ext:N:M
    label: string
    protocol: string
  }>
}

Ошибки

errorCodemessageКогда
27custom subscription not foundПодписка не найдена

Помогла ли вам эта статья?

Содержание

ОбзорОбщие схемы разделаGET /profile/custom-subscriptionsПример запросаОтветGET /profile/custom-subscriptions/available-itemsПример запросаОтветGET /profile/custom-subscriptions/:idURL ParametersПример запросаОтветОшибкиPOST /profile/custom-subscriptionsRequest BodyПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/titleURL ParametersRequest BodyПример запросаОтветОшибкиPUT /profile/custom-subscriptions/:id/itemsURL ParametersRequest BodyПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/items/orderURL ParametersRequest BodyПример запросаОтветОшибкиPOST /profile/custom-subscriptions/:id/reset-keyURL ParametersПример запросаОтветОшибкиPOST /profile/custom-subscriptions/:id/share/vk-documentURL ParametersПример запросаОтветОшибкиDELETE /profile/custom-subscriptions/:idURL ParametersПример запросаОтветОшибкиGET /profile/custom-subscriptions/:id/encrypted-subscription-linkURL ParametersПример запросаОтветОшибкиНастройки отображения подпискиGET /profile/custom-subscriptions/:id/display/settingsURL ParametersПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/display/settingsURL ParametersRequest BodyПример запросаОтветОшибкиXRay шаблон подпискиGET /profile/custom-subscriptions/:id/xray-template/settingsURL ParametersПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/xray-template/settingsURL ParametersRequest BodyПример запросаОтветОшибкиGET /profile/custom-subscriptions/:id/xray-template (устарело)URL ParametersПример запросаОтветОшибкиPUT /profile/custom-subscriptions/:id/xray-template (устарело)URL ParametersRequest BodyПример запросаОтветОшибкиDELETE /profile/custom-subscriptions/:id/xray-template (устарело)URL ParametersПример запросаОтветОшибкиУстройства подпискиGET /profile/custom-subscriptions/:id/devicesURL ParametersQuery ParametersПример запросаОтветОшибкиGET /profile/custom-subscriptions/:id/devices/settingsURL ParametersПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/devices/settingsURL ParametersRequest BodyПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/devices/:deviceId/titleURL ParametersRequest BodyПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/devices/:deviceId/blockedURL ParametersRequest BodyПример запросаОтветОшибкиPATCH /profile/custom-subscriptions/:id/devices/:deviceId/approvalURL ParametersПример запросаОтветОшибкиDELETE /profile/custom-subscriptions/:id/devices/:deviceIdURL ParametersПример запросаОтветОшибкиDELETE /profile/custom-subscriptions/:id/devicesURL ParametersПример запросаОтветОшибкиМаршрутизация подпискиGET /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_idURL ParametersQuery ParametersПример запросаОтветОшибкиPUT /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_idURL ParametersQuery ParametersRequest BodyПример запросаОтветОшибкиDELETE /profile/custom-subscriptions/:id/routing/configs/:config_type/:config_reference_idURL ParametersQuery ParametersПример запросаОтветОшибкиGET /profile/custom-subscriptions/:id/routing/available-tunnelsURL ParametersQuery ParametersПример запросаОтветОшибки