Перепродажа VPN-ключей через один HTTP API
Один API для обоих тарифов ключей: свой баланс, своя цена за ГБ и списание сразу после каждой успешной операции. Мы старались сделать контракт простым и предсказуемым — одна и та же логика ошибок и биллинга на всех эндпоинтах, — чтобы интеграция заняла у вас часы, а не дни.
Аутентификация
Каждый запрос должен нести заголовок Authorization с вашим персональным токеном. Посмотреть его можно в Telegram-боте, на панели партнёра, кнопка «Токен» — токен постоянный и меняется только по вашей команде.
Authorization: Bearer ВАШ_ТОКЕН
Токен один на всю организацию. Если нужно выдать сотрудникам ограниченный доступ именно к API (не к боту) — пока такой возможности нет, но напишите нам, если это для вас важно.
Набор доступных вам действий настроен индивидуально под аккаунт. Если какое-то действие ещё не включено, вызов вернёт FORBIDDEN (см. «Коды ошибок» ниже) — просто напишите нам, и мы его добавим.
Формат ответов
Результат операции по существу мы всегда кладём в поле error тела ответа, а не в HTTP-статус. HTTP-код, отличный от 200, сигнализирует только о транспортной или авторизационной проблеме — не о том, что пошло не так с самой операцией.
{
"error": null,
"info": "KEY_EXPANDED",
"charged": 150.0,
"balance": 4200.5
}
{
"error": "INSUFFICIENT_FUNDS",
"info": "Not enough balance...",
"required": 150.0,
"available": 42.5
}
Проверяйте error первым делом, ещё до разбора остального ответа. А вот текст info — это просто человекочитаемое пояснение, он может меняться со временем, так что не стройте на нём логику как на коде ошибки.
Коды ошибок
Ошибки бывают двух независимых уровней: транспортные — это настоящий HTTP-код — и бизнес-ошибки, которые всегда приходят с HTTP 200 и видны в поле error.
HTTP-уровень
| Код | Когда |
|---|---|
| 401 UNAUTHORIZED | Заголовок Authorization отсутствует/не в формате Bearer …, либо токен не найден. |
| 403 PARTNER_DISABLED | Доступ к API приостановлен для вашего аккаунта («Работа API» выключена). |
| 403 RENT_OVERDUE | Просрочена оплата аренды — доступ заблокирован до оплаты. |
| 422 | Тело запроса не прошло валидацию (например, limit <= 0 или пропущено обязательное поле). Стандартный ответ FastAPI, форма отличается от бизнес-ошибок ниже. |
| 500 INTERNAL_ERROR | Внутренняя ошибка на нашей стороне. Детали не раскрываются в ответе — если повторяется, напишите нам. |
Бизнес-уровень (HTTP 200, поле error)
| Код | Когда |
|---|---|
| FORBIDDEN | Действие не разрешено для вашего аккаунта. Список включённых действий настраивается индивидуально — напишите нам, чтобы включить нужное. |
| INSUFFICIENT_FUNDS | Не хватает баланса + кредитного лимита. В ответе есть required и available. |
| GB_LIMIT_EXCEEDED | Запрошенный объём превышает разовый лимит на операцию. В ответе есть requested и max. |
| SERVICE_UNAVAILABLE | Высокоскоростной тариф временно не настроен на нашей стороне. |
| NOTHING_TO_RESET | У ключа нет накопленного трафика — сбрасывать нечего, списания не было. |
| INVALID_LIMIT | В /key/expand новый лимит (limit) меньше или равен текущему лимиту ключа. В ответе есть current_gb и requested_gb. |
| (другое) | Прочие коды — сообщение в info поясняет причину. |
Сквозная ошибка апстрима
Есть и третья форма, отдельная от первых двух: если сам провайдер ключа отклонил операцию (например, ключ не найден), поле error приходит числом, а не строкой, а info всегда null:
{ "error": 500, "info": null }Поэтому проверяйте error просто на null/отсутствие, а не на конкретный тип — строка это или число. Такая форма может встретиться у любого эндпоинта, который обращается к уже существующему ключу: info, expand, edit, renew и так далее.
Тарификация
Цены индивидуальны для вашего аккаунта — актуальные значения price_per_gb, price_fast и price_device всегда можно получить через /balance. Списание происходит только после успешного выполнения операции: если вызов завершается ошибкой, баланс не затрагивается.
| Действие | Классический тариф | Высокоскоростной |
|---|---|---|
| create | limit × months × price_per_gb | price_fast (фикс.) |
| expand | добавляемые ГБ × price_per_gb | — |
| temp_expand | добавляемые ГБ × price_per_gb (без множителя на срок — временно) | — |
| edit | limit × months × price_per_gb | — |
| renew | текущий лимит ключа × price_per_gb (читаем сами) | price_fast (фикс.) |
| reset | уже использованный трафик × price_per_gb (читаем сами) | — |
| device / add | count × price_device | |
| info / activation / deactivate / revoke / delete / get_trial | бесплатно | — |
Перед любым списанием мы проверяем, что баланс вместе с кредитным лимитом покрывает стоимость операции. Если нет — сразу возвращаем INSUFFICIENT_FUNDS, даже не обращаясь к апстриму, так что никаких побочных эффектов не будет.
Свой домен для ссылок
По умолчанию ссылки на подписку клиенты видят на наших доменах. Но если вы хотите, чтобы ссылка выглядела как ваш собственный бренд — например sub.вашдомен.ru для классического тарифа и ssub.вашдомен.ru для высокоскоростного, — это возможно: мы настраиваем проксирование на нужный вам домен, и дальше вы просто собираете ссылки клиентам так же, как обычно, только уже под своим адресом.
Сама интеграция при этом не меняется — key/username из ответов API остаются теми же, меняется только домен, под которым клиент видит ссылку. Настройка занимает немного времени с нашей стороны (нужен ваш домен с уже настроенным DNS на наш сервер) и делается не через API, а вручную. Подробности и запуск — напишите вашему менеджеру в поддержке.
Механика работы ключей
Параметры и формат ответа каждого метода описаны в соответствующем разделе ниже. Здесь — про то, что происходит с ключом фактически: в какой момент считается время, когда обнуляется трафик и что переживает, а что не переживает то или иное действие. Каждый пункт разворачивается по клику.
Создание ключа
Оба тарифа на создании возвращают только идентификатор ключа — готовая ссылка на подписку API не отдаётся ни на одном из тарифов. Ссылка формируется нашей системой релинка: идентификатор подставляется в персональную ссылку на нашем домене (или на вашем собственном — см. «Свой домен для ссылок»). На классическом тарифе ответ дополнительно содержит username и number — про них подробнее в разделе «Перевыпуск» ниже.
Пробный ключ
Пробный ключ действует 5 дней — срок фиксирован. По истечении пробного периода ключ не удаляется автоматически: методом редактирования пробный ключ переводится в обычный оплаченный без пересоздания — тот же ключ продолжает действовать на новых условиях.
Продление
Метод принимает только идентификатор ключа. Точка отсчёта новых 30 дней — текущая дата окончания ключа, а не момент вызова метода: при продлении за неделю до истечения новая дата окончания рассчитывается как «текущая дата окончания + 30 дней», а не «дата вызова + 30 дней». Уже оплаченный период таким образом никогда не укорачивается.
Обнуление счётчика потреблённого трафика — процесс, независимый от продления: оно происходит по собственному циклу, раз в 30 дней от даты создания ключа, а не от даты последнего продления. Поэтому при раннем продлении счётчик трафика не обнуляется сразу в момент оплаты — обнуление наступит в свою обычную дату, и к этому моменту продлённый период уже действует. Для тарифов на несколько месяцев вперёд это означает несколько обнулений в течение оплаченного периода — по одному в месяц, а не одно в конце.
Редактирование
Редактирование пересчитывает лимит трафика и срок действия ключа на новые значения без пересоздания самого ключа: идентификатор, ссылка на подписку и все параметры подключения клиента остаются прежними, списывается только разница между старыми и новыми условиями.
Увеличение лимита трафика
Значение лимита в запросе — это итоговый лимит целиком, а не величина добавки. При текущем лимите 2 ГБ и переданном значении 5 итоговый лимит составит 5 ГБ, а спишется только разница — 3 ГБ. Значение, меньшее или равное текущему лимиту, не принимается (см. INVALID_LIMIT в кодах ошибок).
Временное увеличение
В отличие от обычного увеличения лимита, здесь add_gb — величина добавки сверх текущего лимита, а не новый итоговый лимит, и добавка временная: она снимается сама, без отдельного вызова с вашей стороны — либо по истечении заданного срока (hours/days), либо на ближайшем плановом сбросе трафика ключа, смотря что наступит раньше. Списание считается сразу за весь добавленный объём в момент вызова, независимо от того, сколько времени добавка фактически продержится.
Перевыпуск
Перевыпуск заменяет внутренний идентификатор ключа (id) на новый; номер ключа (number) и остальные параметры — лимит, срок действия, тариф — не изменяются. Действие предназначено для смены учётных данных (например, при компрометации существующей ссылки), а не для сброса ключа целиком. Если id утерян, ключ можно найти по number — обратитесь в поддержку.
Включение и выключение
Раздельные методы временной деактивации ключа и его повторной активации. Срок действия ключа при деактивации не приостанавливается — отсчёт до даты окончания продолжается как обычно; ограничивается только доступ клиента к использованию.
Сброс трафика
Обнуляет накопленную статистику потребления трафика по ключу, не изменяя лимит и срок действия. Списание рассчитывается исходя из объёма уже потреблённого трафика — оплачивается именно та часть, что обнуляется. При отсутствии накопленного расхода операция выполняется бесплатно (NOTHING_TO_RESET).
Удаление
Необратимо удаляет ключ. Восстановление удалённого ключа невозможно — только создание нового.
Ключи · классический тариф
Здесь вы явно задаёте объём трафика в ГБ и срок действия. И здесь, и во всех остальных разделах key — это id, который вы получаете при создании ключа. Важно: передавайте именно короткий id, а не полную ссылку-подписку — её эндпоинты не распознают.
Выпускает новый ключ с указанным объёмом трафика и сроком действия.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| limit | int | обязательно | Объём трафика в ГБ (1 ГБ = 1 073 741 824 байт), > 0. |
| months | int | обязательно | Срок действия в месяцах, > 0. |
Трафик на ключе сбрасывается на полный limit раз в месяц на всё время его действия — ключ на limit=100, months=3 даёт 100 ГБ в первый месяц, ещё 100 ГБ во второй и ещё 100 ГБ в третий (эквивалент созданию ключа на 1 месяц с двумя последующими /key/renew). Поэтому и стоимость считается как limit × months × price_per_gb, а не только за один сброс.
На одну операцию действует индивидуальный лимит ГБ (max_gb_per_purchase). Превысите его — получите GB_LIMIT_EXCEEDED с полями requested/max. Само значение лимита через API не отдаётся, уточняйте его у нас напрямую.
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/create \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"limit": 100, "months": 1}'Пример ответа
{
"error": null,
"info": "KEY_CREATED",
"id": "N9Wg8t58qNo_azod",
"username": "Singularity-6676",
"number": 6676,
"expireAt": 1755590400,
"charged": 150.0,
"balance": 4350.0
}Сохраните id — это и есть key, который понадобится для всех остальных операций с этим ключом.
Заодно советуем сохранить и number: в отличие от id, он не меняется при перевыпуске ключа — /key/revoke выдаёт новый id, а number/username остаются прежними. Если id всё же потеряется, напишите в поддержку с этим номером — мы найдём ключ по нему.
Выдаёт пробный ключ с фиксированными условиями: 2 ГБ без сброса трафика, срок действия — около 5 дней. Тело запроса не нужно.
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/get_trial \
-H "Authorization: Bearer ВАШ_ТОКЕН"Пример ответа
{
"error": null,
"info": "TRIAL_CREATED",
"id": "Tr1al_9kZpQ2vw",
"username": "Singularity-95",
"number": 95,
"expireAt": 1755158400
}Как и у платного ключа, сохраните number — он переживает /key/revoke, в отличие от id.
Отдаёт полную информацию о ключе: статус, трафик, срок действия, ссылку-подписку, подключённые устройства и служебные учётные данные протоколов. Доступен всегда, отдельное разрешение не нужно.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа, полученный при создании. |
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/info \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "N9Wg8t58qNo_azod"}'Пример ответа (полный, с одним подключённым устройством)
{
"error": null,
"uuid": "fb087fad-e972-4910-94d3-09686663d7b0",
"id": 194618,
"shortUuid": "N9Wg8t58qNo_azod",
"username": "Singularity-6676",
"status": "ACTIVE",
"trafficLimitBytes": 107374182400,
"trafficLimitStrategy": "MONTH_ROLLING",
"expireAt": "2026-08-19T00:00:00Z",
"telegramId": null,
"email": null,
"description": null,
"tag": null,
"hwidDeviceLimit": null,
"externalSquadUuid": "5519a60b-9b3f-4027-a313-ee94e2ba1fca",
"trojanPassword": "uzMVSJgfYopp_cEkm3K6KGq2SvXt8eXd",
"vlessUuid": "cf1d8b03-10e6-48b7-959e-06f35fbf6e5e",
"ssPassword": "LWyh7R1kXR7XDfJuWKA84Ryh6vVSgea6",
"lastTriggeredThreshold": 0,
"subRevokedAt": null,
"lastTrafficResetAt": null,
"createdAt": "2026-08-24T08:34:38.870Z",
"updatedAt": "2026-08-24T08:34:38.870Z",
"subscriptionUrl": "https://singularityvpn.fun/N9Wg8t58qNo_azod",
"activeInternalSquads": [
{ "uuid": "3d12d359-05e5-4e9d-b9b0-8a1b643d6244", "name": "Mobile Internet Nodes" },
{ "uuid": "fb518818-bd1b-4ca1-b801-ee8d6f75f284", "name": "Wi-Fi Nodes" }
],
"userTraffic": {
"usedTrafficBytes": 2147483648,
"lifetimeUsedTrafficBytes": 2147483648,
"onlineAt": "2026-08-24T09:10:02.000Z",
"lastConnectedNodeUuid": "3d12d359-05e5-4e9d-b9b0-8a1b643d6244",
"firstConnectedAt": "2026-08-20T10:15:00.000Z"
},
"devices": {
"total": 1,
"devices": [
{
"deviceModel": "iPhone 15 Pro",
"hwid": "a1b2c3d4e5f6",
"platform": "iOS",
"osVersion": "17.5",
"userAgent": "v2rayTun/1.5.2 (iOS)",
"createdAt": "2026-08-20T10:15:00.000Z",
"updatedAt": "2026-08-24T07:42:11.000Z"
}
]
}
}Как ориентироваться в полях
| Поле | Что это |
|---|---|
| status | ACTIVE / DISABLED (после deactivate) / LIMITED / EXPIRED. |
| trafficLimitBytes / trafficLimitStrategy | Лимит трафика в байтах и стратегия его сброса (например, MONTH_ROLLING — сбрасывается раз в месяц, NO_RESET — не сбрасывается сам, только через /key/reset). |
| expireAt | ISO-строка (не unix-время, в отличие от create/renew/get_trial/create_fast — единственное расхождение в формате дат по всему API). |
| subscriptionUrl | Ссылка-подписка для клиентских приложений — то же самое, что нужно раздавать клиенту. |
| trojanPassword / vlessUuid / ssPassword | Сырые учётные данные протоколов подключения (то, из чего собирается сама подписка). Обычному использованию не нужны — раздавайте клиенту subscriptionUrl, а не эти поля напрямую. |
| uuid / id / externalSquadUuid / activeInternalSquads | Внутренние технические идентификаторы. Не используются в других эндпоинтах — для операций с ключом нужен только shortUuid (= ваш key). |
| userTraffic | Использованный трафик (usedTrafficBytes обнуляется по trafficLimitStrategy или вручную через /key/reset, lifetimeUsedTrafficBytes — никогда). |
| devices | total — сколько устройств сейчас подключено к ключу; devices[] — по одной записи на устройство, с моделью/платформой/датами подключения. |
Задаёт новый лимит трафика ключа как абсолютное значение — не добавляет к текущему, а заменяет его. Списываем только за разницу между новым и текущим лимитом, а не за весь объём заново.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
| limit | int | обязательно | Новый лимит трафика в ГБ целиком (абсолютное значение, не сколько добавить), должен быть больше текущего лимита ключа. |
Например: у ключа сейчас 2 ГБ, вы вызываете expand с limit: 5 — итоговый лимит станет 5 ГБ, а не 7. Спишется цена только за добавленные 3 ГБ. А если передать limit меньше или равный текущему лимиту, вернётся INVALID_LIMIT.
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/expand \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "N9Wg8t58qNo_azod", "limit": 50}'Пример ответа
{ "error": null, "info": "KEY_EXPANDED", "charged": 75.0, "balance": 4275.0 }В отличие от expand, задаёт и лимит, и срок как абсолютные значения — перезаписывает их, а не добавляет к текущим. При этом id ключа остаётся прежним.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
| limit | int | обязательно | Новый лимит трафика в ГБ (абсолютное значение), > 0. |
| months | int | обязательно | Новый срок действия в месяцах, > 0. |
Стоимость считается так же, как за новый ключ такого же объёма и срока: limit × months × price_per_gb — просто id остаётся тем же.
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/edit \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "N9Wg8t58qNo_azod", "limit": 200, "months": 3}'Пример ответа
{ "error": null, "info": "KEY_EDITED", "charged": 900.0, "balance": 3375.0 }Продлевает ключ. Объём ГБ передавать не нужно: перед списанием мы сами смотрим текущий лимит ключа через /key/info и считаем стоимость по нему.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/renew \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "N9Wg8t58qNo_azod"}'Пример ответа
{ "error": null, "info": "KEY_RENEWED", "expireAt": 1758268800, "charged": 150.0, "balance": 3225.0 }Снимает ключ с паузы — просто переключает статус, на трафик и срок действия не влияет.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
{ "error": null, "info": "KEY_ALREADY_ACTIVE" }Точный текст info зависит от исходного статуса ключа — например, будет KEY_ACTIVATED, если он реально был на паузе. Ориентируйтесь на error: null как на признак успеха, а не на конкретную строку в info.
Отключает клиенту доступ — тот же переключатель статуса, только в обратную сторону. Срок действия ключа при этом продолжает идти как обычно и не останавливается на время деактивации.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
{ "error": null, "info": "KEY_DEACTIVATED" }Название немного вводит в заблуждение — это не отзыв или удаление ключа, а перевыпуск его учётных данных. Старый id перестаёт работать сразу же, вместо него выдаётся новый.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | Текущий id ключа. |
Обязательно сохраните NEW_KEY из ответа и обновите его у себя — старый id больше не сработает ни в одном запросе.
Пример ответа
{ "error": null, "NEW_KEY": "aB3xQpLk92mZrTs1" }Обнуляет использованный трафик ключа. Перед сбросом мы смотрим, сколько фактически использовано, и списываем за этот объём — иначе он так и остался бы неоплаченным.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
Если у ключа использовано 0 байт, запрос отклоняется с NOTHING_TO_RESET и списания не происходит — поэтому и пометка «Платно*»: платит только тот, кому реально есть что списывать.
Пример ответа (если был трафик для списания)
{ "error": null, "info": "…", "charged": 37.5, "balance": 3187.5 }Пример ответа (трафик не использован)
{ "error": "NOTHING_TO_RESET", "info": "Key has no used traffic to reset" }Удаляет ключ безвозвратно. После этого любой вызов /key/info по этому id будет возвращать ошибку.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
{ "error": null, "info": "KEY_DELETED" }В отличие от expand, добавляет объём временно и сверх текущего лимита — add_gb здесь именно величина добавки, а не новый абсолютный лимит. Прибавка снимается автоматически сама, без обратного вызова с вашей стороны: по истечении заданного срока либо на ближайшем плановом сбросе трафика ключа — что наступит раньше.
Параметры
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | id ключа. |
| add_gb | int | обязательно | Сколько ГБ временно добавить сверх текущего лимита (величина добавки, > 0). |
| hours | int | одно из hours/days | На сколько часов действует добавка, > 0. |
| days | int | одно из hours/days | На сколько дней действует добавка, > 0. Передавайте либо hours, либо days — не оба сразу и не ни одного. |
Например: у ключа лимит 10 ГБ, вы вызываете temp_expand с add_gb: 5, days: 3 — на 3 дня лимит станет 15 ГБ, спишется цена за все добавленные 5 ГБ сразу. По истечении 3 дней (или раньше, если у ключа как раз наступит плановый сброс трафика) лимит сам вернётся к исходным 10 ГБ — вызывать что-либо для отката не нужно.
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/temp_expand \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "N9Wg8t58qNo_azod", "add_gb": 5, "days": 3}'Пример ответа
{ "error": null, "info": "KEY_TEMP_EXPANDED", "added_gb": 5, "original_limit_gb": 10, "current_limit_gb": 15, "duration_hours": 72, "expires_at": 1234567890, "charged": 4.0, "balance": 4271.0 }Ключи · высокоскоростной тариф
Тариф для клиентов, которым важна скорость. Трафик здесь безлимитный, срок фиксированный — 1 месяц, поэтому и цена фиксированная за операцию (price_fast), а не за ГБ.
Выпускает новый ключ высокоскоростного тарифа.
| Поле | Тип | Описание | |
|---|---|---|---|
| period | string | необязательно | Сейчас поддерживается только "1m" — значение по умолчанию. |
Пример ответа
{
"error": null,
"key": "MWI3OGJlZjg0MzhkNDEsMTc4NDQ5NjI5NQPTS8KWejU9",
"username": "1b78bef8438d41",
"expireAt": 1787088294,
"charged": 300.0,
"balance": 2887.5
}Ссылку для клиента соберите сами по шаблону https://i.singularityvpn.ru/{key}, например https://i.singularityvpn.ru/MWI3OGJlZjg0MzhkNDEsMTc4NDQ5NjI5NQPTS8KWejU9. И отдельно сохраните username — он понадобится для продления.
Продлевает высокоскоростной ключ ещё на один период — по той же цене, что и при создании.
| Поле | Тип | Описание | |
|---|---|---|---|
| username | string | обязательно | Значение поля username, полученное при создании ключа. |
| period | string | необязательно | Сейчас только "1m". |
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/key/extend_fast \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"username": "1b78bef8438d41"}'Пример ответа
{ "error": null, "status": "extended", "charged": 300.0, "balance": 2587.5 }Устройства
К каждому ключу по умолчанию привязан лимит в 5 устройств. Через этот эндпойнт можно докупить клиенту дополнительные устройства сверх лимита — прибавка фиксируется для указанного ключа и списывается по вашей цене price_device.
Увеличивает лимит устройств для указанного ключа на count сверх стандартных 5 и списывает price_device × count с вашего баланса.
| Поле | Тип | Описание | |
|---|---|---|---|
| key | string | обязательно | Идентификатор ключа, к которому привязывается докупка. |
| count | integer | необязательно | Сколько устройств докупается за один вызов. По умолчанию — 1. |
Пример запроса
curl -X POST https://api.singularityvpn.ru/api/v1/device/add \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-H "Content-Type: application/json" \
-d '{"key": "ваш-идентификатор-ключа", "count": 1}'Пример ответа
{ "error": null, "charged": 10.0, "balance": 4329.0 }Лимит действует в рамках текущей активной подписки клиента: докупленные устройства привязаны к одному ключу и учитываются, пока эта подписка активна. При завершении или непродлении подписки лимит возвращается к стандартным 5 устройствам — при следующей покупке докупку нужно оформить заново.
Баланс
Тело запроса не нужно — только заголовок авторизации. Удобно вызывать перед крупной операцией, чтобы заранее прикинуть, хватит ли средств.
Пример запроса
curl https://api.singularityvpn.ru/api/v1/balance \
-H "Authorization: Bearer ВАШ_ТОКЕН"Пример ответа
{
"balance": 2587.5,
"credit_limit": 500.0,
"price_per_gb": 1.5,
"price_fast": 300.0,
"price_device": 10.0
}credit_limit показывает, насколько баланс может уйти в минус. Так что реально доступная сумма на операцию — это balance + credit_limit, а не просто balance.
Частые вопросы
"error": null?revoke отличается от delete?revoke не удаляет ключ, а перевыпускает его учётные данные: старый id перестаёт работать, вместо него приходит новый (NEW_KEY), которым нужно заменить сохранённую у клиента ссылку. А delete удаляет ключ безвозвратно.renew не принимает объём ГБ?/key/create_fast отдаёт поле key — ссылка для клиента собирается как https://i.singularityvpn.ru/{key}.key, а username — это отдельное поле в ответе /key/create_fast. Сохраняйте оба поля при создании: key пригодится для ссылки, username — для /key/extend_fast.{"error": "FORBIDDEN"}. Набор доступных действий настроен индивидуально под ваш аккаунт — если нужно больше, напишите нам, и мы включим.limit и в расчёте стоимости./device/add вы увеличиваете лимит устройств для конкретного ключа сверх стандартных 5. Лимит действует, пока активна текущая подписка клиента — если она закончится или не продлится, лимит вернётся к базовым 5 устройствам./key/info (для ключа) или /balance (по изменению баланса), и уже по нему решайте, нужен ли повтор./key/info./key/get_trial (бесплатно) или создать классический ключ с минимальным объёмом на 1 месяц.