Справочник API Vitamin
Продавайте VPN-аккаунты и виртуальные серверы со своего сайта, бота или скрипта и управляйте ими.
Базовый URLhttps://apiservice.vitamindata.net/api/v1
Ключи создаются в вашей панели. Если раздела нет, попросите поддержку включить доступ к API для вашего аккаунта.
1Создайте API-ключ в панели и отправляйте его как bearer-токен в каждом вызове.
2Вызовите Ping, чтобы проверить ключ, затем получите свои цены через ListPlans и GetVPSStorefront.
3Продавайте с FUNDING_AUTO: когда баланса хватает, платит он; когда нет — клиент получает ссылку на оплату.
Аутентификация
Каждый запрос несёт ваш ключ как bearer-токен. На этом хосте нет cookie и не нужно получать CSRF-токен — ключ и есть все учётные данные.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ключи создаются в вашей панели, в разделе API. Секрет показывается один раз, при создании: мы храним только его хеш. Если он потерян, решение — ротация ключа: она выдаёт новый секрет и оставляет старый рабочим ещё на сутки, чтобы вы развернули изменения без простоя.
Ключ можно ограничить списком исходных адресов, дать ему собственный лимит запросов в минуту и отобрать у него отдельные операции. Это настраивают наши операторы — напишите в поддержку, если нужен ключ, который, скажем, может покупать, но никогда не может удалять услуги.
Тестовые ключи
Ключ, начинающийся с sk_test_, читает реальные данные, но отклоняет всё, что тратит деньги или затрагивает реальную машину, — так вы соберёте и проверите интеграцию раньше, чем она сможет что-то стоить.
Как выглядит отказ
Неизвестный ключ и ключ аккаунта без доступа к API получают один и тот же 401, слово в слово: ответ никогда не подтверждает, существует ли ключ. Исключение — ваш собственный ключ, переживший срок перекрытия при ротации: он говорит api key expired, потому что вы и так знаете, что этот ключ был настоящим, и вам нужно понять, почему он перестал работать. Повторяющиеся отказы с одного адреса ограничиваются — см. ограничение частоты.
Оплата
Всё, что вы покупаете — VPN-аккаунт, продление, сервер, продление сервера, апгрейд — проходит по одному контракту. Вы выбираете, откуда берутся деньги:
funding | Что происходит |
|---|
FUNDING_AUTO | Рекомендуется. Списывает с баланса, если баланса хватает; иначе вызов всё равно успешен и возвращает ссылку на оплату. Один вызов, никакой ошибки, которую нужно разбирать. |
FUNDING_BALANCE | Только баланс. Если баланса не хватает, вызов ЗАВЕРШАЕТСЯ ОШИБКОЙ insufficient_balance (в ошибке всё равно есть ссылка на оплату). |
FUNDING_INVOICE | Всегда возвращает ссылку на оплату, даже если баланса хватило бы. |
С FUNDING_AUTO вы смотрите на одно поле:
{"order": {...}, "paid": true, "status": "completed"}
{"order": {...}, "status": "payment_required",
"invoice": {"invoice_id": "inv_9m2r4t",
"pay_url": "https://pay.example.com/i/inv_9m2r4t",
"price_usd": "11.90", "expires_at": "1785499200"}}
completed означает, что деньги списаны и выдача началась — опрашивайте GetOrder, пока статус не станет delivered. payment_required означает: отправьте клиента на pay_url; выдача начнётся сама, когда счёт будет оплачен.
Цены всегда наши. Можно передать expected_total_usd как страховку: если наш свежий расчёт отличается, продажа отклоняется с price_changed и новой суммой, вместо того чтобы списать сумму, которой клиент не видел.
Безопасные повторы
Отправляйте заголовок Idempotency-Key в каждом вызове, который тратит деньги. Если ответ до вас не дошёл — таймаут, разорванное соединение, перезапущенный воркер — повторите ТОТ ЖЕ запрос с ТЕМ ЖЕ ключом и получите исходный результат, а не второе списание.
Idempotency-Key: 8f14e45f-ea6d-4b3a-9c1b-2f0d5a7e91c3
На каждое действие клиента — новый ключ (UUID идеален). Повторное использование ключа с другим телом отклоняется с idempotency_conflict: такое сочетание означает ошибку в коде, и угадывать, какой запрос вы имели в виду, было бы хуже, чем сказать вам об этом.
Ограничение частоты
Каждый ответ на аутентифицированный запрос говорит, где находится ваш ключ:
RateLimit-Limit: 6000
RateLimit-Remaining: 5987
RateLimit-Policy: 6000;w=60
Лимит — на ключ, в минуту, и он задаётся для вашего аккаунта. Значения по умолчанию хватает магазину; загруженному боту стоит попросить больше, а не подстраиваться под значение по умолчанию. При превышении приходит 429 с Retry-After.
429 приходит и тогда, когда много запросов с одного адреса не проходят аутентификацию. Это защита от подбора, а не ваша квота: она снимается сама (в заголовке сказано когда), и рабочий ключ её никогда не вызывает.
Кроме того, на каждом ответе — даже когда ключа в запросе не было — вы увидите семейство X-Ratelimit-*. Это грубый ограничитель НА АДРЕС перед всем API, а не бюджет вашего ключа: держите темп по RateLimit-Remaining, а заголовки X- считайте чужим делом.
Ошибки
Сбои возвращаются как HTTP-статус и JSON-тело. Верхнеуровневый code — транспортная категория; верхнеуровневый message несёт стабильный машинный код. Полные детали — тот же машинный код, безопасная фраза и полезные дополнительные поля — приходят в details, в поле debug:
{"code": "failed_precondition",
"message": "insufficient_balance",
"details": [{"type": "neopay.seller.publicapi.v1.ErrorInfo",
"value": "CgptZXNzYWdl…",
"debug": {"code": "insufficient_balance",
"message": "insufficient balance",
"payUrl": "https://pay.example.com/i/inv_9m2r4t",
"orderId": "ord_8c3d1e",
"totalUsd": "11.90"}}]}
У канала ошибок две особенности, и обе стоит учесть в коде: value — это protobuf в base64 (игнорируйте его — читайте debug), а дополнительные поля внутри debug записаны в lowerCamelCase — payUrl, orderId, totalUsd, retryAfterSeconds — соглашение Connect, в отличие от snake_case во всех остальных местах. Ветвитесь по верхнеуровневому message или по debug.code; никогда — по тексту фразы.
Отказы до авторизации запроса
Запрос, который так и не доходит до обработчика — ключа нет или он неверен (401), исходный адрес ключу не разрешён (403), превышена частота (429), аутентификация недоступна (503), — отклоняется на входе, и вход отвечает БОЛЕЕ КОРОТКИМ телом: транспортный code и обычная фраза, без details и без машинного кода.
{"code": "unauthenticated", "message": "invalid api key"}
Поэтому в таких случаях ветвитесь по HTTP-СТАТУСУ (и соблюдайте Retry-After при 429); машинные коды ниже относятся к вызовам, которые дошли до обработчика. Грубый ограничитель на адрес появился ещё раньше и отвечает {"error":"rate_limited"}: поле называется error, а не code.
| Код | Что значит | Что делать |
|---|
forbidden_scope | У ключа нет нужной области доступа, либо эта операция у него отобрана. | Попросите поддержку расширить ключ. |
not_found | Такого объекта для этого аккаунта нет. | Проверьте идентификатор. Чужой идентификатор отвечает тем же — так и задумано. |
invalid_request | Поле заполнено неверно. | Исправьте и отправьте снова; повтор без изменений не поможет. |
insufficient_balance | Оплаты только с баланса не хватило. | Используйте payUrl из деталей или перейдите на FUNDING_AUTO. |
price_changed | Ваше значение expected_total_usd больше не совпадает. | Запросите цену заново и подтвердите новую сумму с клиентом. |
idempotency_conflict | Этот ключ уже использовался с другим телом запроса. | Используйте новый ключ на каждое действие. |
sandbox_unavailable | Ключ sk_test_ попытался потратить деньги или затронуть реальную машину. | Так и задумано — для такого вызова используйте боевой ключ. Тестовые ключи читают, но никогда не покупают. |
unpriceable | Запрошенная конфигурация не продаётся: тариф или узел без цены либо корзина, которую не покрывает ни одна модель. | Перечитайте магазин и запросите расчёт цены перед покупкой: ту же корзину расчёт отклонит так же. |
upstream_unavailable | Одна из систем, от которых мы зависим, недоступна. | Повторяйте с нарастающей задержкой; чтения могут быть ненадолго устаревшими. |
order_failed | Выдача после оплаты не удалась. | Не покупайте повторно. Опрашивайте GetOrder; мы восстанавливаем такие заказы автоматически, и поддержка их видит. |
internal | На нашей стороне что-то сломалось, и мы это не классифицировали. | Повторите один раз с задержкой; если повторяется — укажите X-Request-Id в обращении в поддержку. |
Соглашения
- Транспорт. Каждый вызов —
POST {base}/{Method} с JSON-телом — POST /api/v1/CreateVPNOrder. Больше ничего нет: любой другой HTTP-метод отвечает 405, никакого маппинга на REST-глаголы и никаких параметров в пути. - Деньги — это строка.
"19.99", никогда 19.99: JSON-число в большинстве языков становится float и не может точно хранить цент. - 64-битные целые приходят строками. Каждый счётчик байтов и каждая unix-метка времени — 64-битные, и на проводе они в кавычках —
"remaining_bytes": "96636764160". Разбирайте их как целые; в запросах допустима любая из двух форм. - Нули опускаются. Поле со значением
0, false или пустым вообще не появляется в ответе. Считайте отсутствие нулём — и помните: дневной лимит 0 означает, что лимита НЕТ, а не «0 ГБ». - Время — в unix-секундах, кроме окна транзакций: оно принимает и возвращает RFC3339 или
YYYY-MM-DD. - Трафик — в байтах, никогда не в гигабайтах, во всех показателях.
- Идентификаторы непрозрачны.
acc_…, ord_…, vpn_…. Никогда не разбирайте и не генерируйте их и не считайте последовательными. - Постраничность — по непрозрачному курсору: верните
next_cursor из предыдущего ответа. Пустой next_cursor означает, что вы получили всё. - В таблицах полей используются короткие обозначения типов.
money — точная десятичная строка; unix — unix-секунды (64 бита, поэтому строка); bytes — число байтов (64 бита, поэтому строка); int64 — любое другое 64-битное (строка); int — 32-битное, обычное число; cursor — непрозрачный курсор постраничного вывода; enum — ровно одно из перечисленных значений. - Новые поля появляются без предупреждения, а смысл существующих не меняется. Игнорируйте то, чего не знаете.
Начало работы
Первый вызов: он подтверждает, что ключ работает, и говорит, какому аккаунту он принадлежит.
https://apiservice.vitamindata.net/api/v1/PingВозвращает идентификатор вашего аккаунта, тип ключа (боевой или тестовый) и наши часы.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/Ping \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
account_idstring
Аккаунт ключа — доказательство, что ключ распознан.
modeenum
Какого типа ключ вы прислали.
Одно из:livetest
server_timeunix
Наши часы — полезно, чтобы заметить расхождение времени до того, как оно сломает подписи или окна.
Пример ответа{
"account_id": "acc_9f3k2m7q",
"mode": "live",
"server_time": "1785412800"
}
Аккаунт и баланс
https://apiservice.vitamindata.net/api/v1/GetAccountEmail, статус и язык вашего аккаунта, а также подтверждён ли адрес.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetAccount \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
accountobject
Ваш аккаунт.
account.account_idstring
Публичный идентификатор (acc_…).
account.emailstring
Адрес для входа.
account.statusstring
active, если аккаунт не ограничен.
account.localestring
Язык аккаунта — на него локализуются названия карточек и уведомления.
account.email_verifiedbool
Адрес подтверждён.
account.created_atunix
Когда аккаунт был создан.
Пример ответа{
"account": {
"account_id": "acc_9f3k2m7q",
"email": "dev@example.com",
"status": "active",
"locale": "en",
"email_verified": true,
"created_at": "1769000000"
}
}
https://apiservice.vitamindata.net/api/v1/GetBalanceБаланс по вашей книге и сумма, которую покупка действительно может списать.
available_usd — то число, на которое надо смотреть перед покупкой: оно не включает суммы, уже заблокированные незавершённым заказом.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetBalance \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
balance_usdmoney
Полный баланс по книге.
available_usdmoney
Баланс минус блокировки — то, что покупка может потратить прямо сейчас.
as_ofstring
Метка времени этих цифр по книге, RFC3339.
Пример ответа{
"balance_usd": "72.60",
"available_usd": "60.70",
"as_of": "2026-07-29T12:00:00Z"
}
https://apiservice.vitamindata.net/api/v1/ListTransactionsВаша книга, сначала новые.
По умолчанию — последние три месяца. Окно шире 92 дней сужается, и ответ сообщает, какое окно он действительно использовал, — так короткий ответ никогда не бывает двусмысленным.
Запрос
limitintнеобязательно
Размер страницы. По умолчанию 25, максимум 100.
cursorcursorнеобязательно
next_cursor из предыдущего ответа. Для первой страницы опустите.
kindstringнеобязательно
Необязательный фильтр по значениям kind ниже, через запятую.
fromstringнеобязательно
Начало окна, RFC3339 или YYYY-MM-DD.
tostringнеобязательно
Конец окна. to в виде только даты включает весь этот день.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListTransactions \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"limit":25,"cursor":"","kind":"topup_credit,invoice_debit_reserved","from":"2026-05-01","to":"2026-07-30"}'
Ответ200 · application/json
transactionsarray
Строки книги.
transactions[].idstring
Идентификатор строки книги.
transactions[].tsstring
Когда, RFC3339.
transactions[].kindenum
Что двигало деньги. topup_credit — оплаченное пополнение; два вида invoice_debit_* — покупки. Внутренние блокировка и освобождение средств по незавершённому заказу в эту ленту не попадают.
Одно из:topup_creditexternal_creditinvoice_debit_reservedinvoice_debit_externaloverpay_creditmanual_creditmanual_debitspend_debitspend_refundautomated_correction
transactions[].amount_usdmoney
Со знаком — отрицательная при списаниях.
transactions[].balance_after_usdmoney
Текущий баланс после этой строки.
transactions[].ref_invoice_idstring
Счёт за движением — передайте его в GetInvoice, чтобы получить полную картину.
transactions[].descriptionstring
Короткая человекочитаемая подпись. Только для отображения; никогда не ветвитесь по ней.
next_cursorcursor
Верните его как cursor, чтобы получить следующую страницу. Отсутствует/пустой = вы получили всё.
has_morebool
За этой страницей есть ещё строки.
fromstring
ФАКТИЧЕСКИ применённое окно (RFC3339). Уже, чем вы просили, ⇒ вы упёрлись в предел в 92 дня.
tostring
Конец применённого окна.
Пример ответа{
"transactions": [
{"id": "tx_01j9zq", "ts": "2026-07-28T09:14:03Z", "kind": "invoice_debit_reserved",
"amount_usd": "-11.90", "balance_after_usd": "72.60",
"ref_invoice_id": "inv_5k8p2q", "description": "order ord_7b2c9d"},
{"id": "tx_01j8xw", "ts": "2026-07-25T18:40:11Z", "kind": "topup_credit",
"amount_usd": "50.00", "balance_after_usd": "84.50", "ref_invoice_id": "inv_3d1x8n"}
],
"from": "2026-04-30T00:00:00Z",
"to": "2026-07-29T23:59:59Z"
}
POST
CreateTopup
buyIdempotency-Key
https://apiservice.vitamindata.net/api/v1/CreateTopupСоздаёт счёт к оплате, который пополняет ваш баланс.
Отправьте клиента (или себя) на invoice.pay_url. Баланс меняется после оплаты.
Запрос
amount_usdmoneyобязательное
Сколько добавить, десятичной строкой.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/CreateTopup \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"amount_usd":"50.00"}'
Ответ200 · application/json
invoiceobject
Счёт к оплате.
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
Пример ответа{
"invoice": {
"invoice_id": "inv_3d1x8n",
"status": "pending",
"pay_url": "https://pay.example.com/i/inv_3d1x8n",
"pay_telegram_url": "https://t.me/VitaminPayBot?start=3d1x8n",
"price_usd": "50.00",
"expires_at": "1785499200"
}
}
https://apiservice.vitamindata.net/api/v1/GetInvoiceОдин платёж полностью, включая то, что видно в блокчейне.
Ключ связи — ref_invoice_id из строки книги. Читать можно только счета, созданные вашим аккаунтом.
Запрос
invoice_idstringобязательное
Из ref_invoice_id строки книги, из заказа или из пополнения.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetInvoice \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"invoice_id":"inv_5k8p2q"}'
Ответ200 · application/json
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
paymentsarray
Что видно в блокчейне. Пусто для счёта, оплаченного с баланса (блокчейн не участвовал), и для счёта, который ещё никто не оплатил, — пустой список не ошибка.
payments[].chainstring
Сеть, по которой пришёл платёж (tron, bsc, …).
payments[].assetstring
Чем заплатили (USDT, …).
payments[].amountmoney
Сумма в активе, точная.
payments[].tx_hashstring
Транзакция в блокчейне — доказательство оплаты для вашего клиента.
payments[].confirmedbool
Блокчейн его финализировал.
payments[].seen_atunix
Когда мы впервые его увидели.
order_idstring
Что купил счёт. Отсутствует у пополнения — оно ничего не покупает.
Пример ответа{
"invoice": {
"invoice_id": "inv_5k8p2q",
"status": "confirmed",
"pay_url": "https://pay.example.com/i/inv_5k8p2q",
"price_usd": "11.90",
"expires_at": "1785499200"
},
"payments": [
{"chain": "tron", "asset": "USDT", "amount": "11.90",
"tx_hash": "c4a1f09e2b7d", "confirmed": true, "seen_at": "1785412920"}
],
"order_id": "ord_7b2c9d"
}
Цены
Здесь ничего не создаётся — считайте цену сколько угодно раз, пока клиент не принял решение.
https://apiservice.vitamindata.net/api/v1/ListPlansЧто вы можете продавать: границы ползунка и, если ваш магазин их использует, карточки с фиксированной ценой.
Показывайте то, что заполнено. Карточка покупается передачей её bundle_id в корзину; корзина-ползунок использует гб/месяцы/пользователи.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListPlans \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
model_namestring
Модель ценообразования вашего магазина.
model_typestring
Версия её движка.
boundsobject
Правила конфигуратора — каждый расчёт и каждый заказ перепроверяет их на стороне сервера.
bounds.gb_minint
Минимальный трафик, который может запросить корзина.
bounds.gb_maxint
Максимальный.
bounds.gb_stepint
Шаг ползунка.
bounds.users_minint
Минимум одновременных устройств.
bounds.users_maxint
Максимум.
bounds.months_minint
Минимальный срок.
bounds.months_maxint
Максимальный.
bounds.new_accounts_maxint
Максимум аккаунтов, которые может создать один заказ.
bounds.extend_maxint
Максимум аккаунтов, которые может продлить один заказ.
bounds.default_gbint
Разумное значение ползунка по умолчанию.
bounds.default_usersint
Устройств по умолчанию.
bounds.default_monthsint
Срок по умолчанию.
bundlesarray
Карточки с фиксированной ценой, если ваш магазин — каталог карточек.
bundles[].bundle_idstring
Идентификатор, который кладут в cart.bundle_id.
bundles[].namestring
Название карточки, уже локализованное под язык аккаунта.
bundles[].gbint
Включённый трафик.
bundles[].monthsint
Срок действия.
bundles[].online_usersint
Одновременных устройств.
bundles[].price_usdmoney
Цена. Это И ЕСТЬ цена — для карточки расчёт не нужен.
bundles[].highlightbool
Рекомендуемая карточка магазина.
bundles[].daily_cap_gbint
Дневной предел в ГБ. Отсутствует = предела нет.
Пример ответа{
"model_name": "vpn_dynamic",
"model_type": "dynamic_v2",
"bounds": {
"gb_min": 10, "gb_max": 500, "gb_step": 10,
"users_min": 1, "users_max": 10,
"months_min": 1, "months_max": 12,
"new_accounts_max": 5, "extend_max": 10,
"default_gb": 100, "default_users": 3, "default_months": 1
},
"bundles": [
{"bundle_id": "card_100_1m", "name": "100 GB · 1 month", "gb": 100, "months": 1,
"online_users": 3, "price_usd": "11.90", "highlight": true}
]
}
https://apiservice.vitamindata.net/api/v1/QuoteИтоговая цена VPN-корзины, по позициям. Скидки уже применены.
Запрос
cartobjectобязательное
Корзина для расчёта цены.
cart.kindenumобязательное
Купить новые аккаунты или добавить трафик и время существующим.
Одно из:newextend
cart.gbintнеобязательно
Трафик на аккаунт, в ГБ, в границах из ListPlans.
cart.monthsintнеобязательно
Срок действия на аккаунт, в месяцах.
cart.usersintнеобязательно
Одновременных устройств на аккаунт.
cart.new_accountsintнеобязательно
Только для kind:"new": сколько аккаунтов создать. Имена пользователей генерирует сервер.
cart.extend_vpn_idsarrayнеобязательно
Только для kind:"extend": какие аккаунты продлить, по публичным идентификаторам.
cart.bundle_idstringнеобязательно
Покупает карточку с фиксированной ценой из ListPlans.bundles вместо настраиваемой корзины. Если задано, гб/месяцы/пользователи игнорируются — действуют значения и цена самой карточки.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/Quote \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"cart":{"kind":"new","gb":100,"months":1,"users":3,"new_accounts":2}}'
Другие формы этого запросаПродлить аккаунты, которые у вас уже есть{"cart":{"kind":"extend","gb":50,"months":1,"users":3,"extend_vpn_ids":["vpn_6t2k9p","vpn_1a4b7c"]}}
Купить карточку с фиксированной ценой вместо собранной корзины{"cart":{"kind":"new","bundle_id":"card_100_1m","new_accounts":1}}
Ответ200 · application/json
quoteobject
Цена по позициям. Ничего не создаётся и ничего не списывается.
quote.model_namestring
Какая модель ценообразования ответила.
quote.model_typestring
Версия движка модели.
quote.base_usdmoney
Цена до скидок и надбавок.
quote.total_usdmoney
Итоговая цена — сумма, которую спишет продажа с этой корзиной.
quote.linesarray
Постатейная разбивка, со знаками, в точности суммирующаяся в итог.
quote.lines[].codestring
Что это за строка (base, код скидки, надбавка…).
quote.lines[].kindstring
Категория строки, для группировки в вашем интерфейсе.
quote.lines[].amount_usdmoney
Со знаком. Скидки отрицательные; строки в точности суммируются в total_usd.
quote.lines[].pctstring
Процент за строкой, когда он есть.
quote.cappedbool
Итог упёрся в потолок модели.
quote.floor_appliedbool
Итог был поднят до нижней границы модели.
quote.clampedenum
Установлено, если значение корзины было приведено к границам перед расчётом цены.
Одно из:minmax
quote.invalidstring
Непустое значение означает, что корзину нельзя оценить — покажите его и НИКОГДА не списывайте деньги по такому расчёту.
quote.metamap
Дополнительные данные модели, строка→строка (например, remaining_days у апгрейда).
Пример ответа{
"quote": {
"model_name": "vpn_dynamic",
"model_type": "dynamic_v2",
"base_usd": "14.00",
"total_usd": "11.90",
"lines": [
{"code": "base", "kind": "base", "amount_usd": "14.00"},
{"code": "loyalty", "kind": "discount", "amount_usd": "-2.10", "pct": "15"}
]
}
}
Продажа VPN
POST
CreateVPNOrder
buyIdempotency-Key
https://apiservice.vitamindata.net/api/v1/CreateVPNOrderПокупает новые VPN-аккаунты или продлевает существующие ("kind":"extend" с extend_vpn_ids).
О двух формах ответа см. Оплата.
Запрос
cartobjectобязательное
Что купить — та же структура, которую оценивает Quote.
cart.kindenumобязательное
Купить новые аккаунты или добавить трафик и время существующим.
Одно из:newextend
cart.gbintнеобязательно
Трафик на аккаунт, в ГБ, в границах из ListPlans.
cart.monthsintнеобязательно
Срок действия на аккаунт, в месяцах.
cart.usersintнеобязательно
Одновременных устройств на аккаунт.
cart.new_accountsintнеобязательно
Только для kind:"new": сколько аккаунтов создать. Имена пользователей генерирует сервер.
cart.extend_vpn_idsarrayнеобязательно
Только для kind:"extend": какие аккаунты продлить, по публичным идентификаторам.
cart.bundle_idstringнеобязательно
Покупает карточку с фиксированной ценой из ListPlans.bundles вместо настраиваемой корзины. Если задано, гб/месяцы/пользователи игнорируются — действуют значения и цена самой карточки.
fundingenumобязательное
Как платить — см. Оплата. Значения по умолчанию нет: запрос без него отклоняется.
Одно из:FUNDING_AUTOFUNDING_BALANCEFUNDING_INVOICE
expected_total_usdmoneyнеобязательно
Страховка подтверждения. Если задано и наш свежий расчёт отличается, продажа отклоняется с price_changed, вместо того чтобы списать сумму, которой ваш клиент не видел.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/CreateVPNOrder \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"cart":{"kind":"new","gb":100,"months":1,"users":3,"new_accounts":1},"funding":"FUNDING_AUTO","expected_total_usd":"11.90"}'
Другие формы этого запросаПродлить аккаунты, которые у вас уже есть{"cart":{"kind":"extend","gb":50,"months":1,"users":3,"extend_vpn_ids":["vpn_6t2k9p"]},"funding":"FUNDING_AUTO"}
Купить карточку с фиксированной ценой, оплата с баланса{"cart":{"kind":"new","bundle_id":"card_100_1m","new_accounts":1},"funding":"FUNDING_BALANCE"}
Ответ200 · application/json
orderobject
Заказ — опрашивайте GetOrder, пока статус не станет delivered.
order.order_idstring
Публичный идентификатор заказа (ord_…).
order.productenum
Что было куплено.
Одно из:vpnvps
order.kindstring
Форма покупки: new, extend, upgrade…
order.statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
order.fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
order.total_usdmoney
Сумма, которую списывает заказ.
order.invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
order.itemsint
Сколько услуг заказ создаёт или продлевает.
order.created_atunix
Когда заказ был размещён.
order.delivered_atunix
Когда завершилась выдача. До этого отсутствует.
order.breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
invoiceobject
Счёт за заказом: подлежит оплате при payment_required, уже оплачен при completed.
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
paidbool
Деньги получены. Отсутствует (= false) при payment_required.
statusenum
ГЛАВНОЕ поле для ветвления — см. Оплата.
Одно из:completedpayment_required
Пример ответа{
"order": {
"order_id": "ord_8c3d1e", "product": "vpn", "kind": "new",
"status": "invoiced", "funding": "invoice", "total_usd": "11.90",
"invoice_id": "inv_9m2r4t", "items": 1, "created_at": "1785412800"
},
"invoice": {
"invoice_id": "inv_9m2r4t", "status": "pending",
"pay_url": "https://pay.example.com/i/inv_9m2r4t",
"pay_telegram_url": "https://t.me/VitaminPayBot?start=9m2r4t",
"price_usd": "11.90", "expires_at": "1785499200"
},
"status": "payment_required"
}
https://apiservice.vitamindata.net/api/v1/GetOrderОпрашивайте это после покупки: created → invoiced → paid → delivering → delivered.
Запрос
order_idstringобязательное
Из размещённого вами заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetOrder \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"order_id":"ord_7b2c9d"}'
Ответ200 · application/json
orderobject
Заказ, с полной разбивкой.
order.order_idstring
Публичный идентификатор заказа (ord_…).
order.productenum
Что было куплено.
Одно из:vpnvps
order.kindstring
Форма покупки: new, extend, upgrade…
order.statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
order.fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
order.total_usdmoney
Сумма, которую списывает заказ.
order.invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
order.itemsint
Сколько услуг заказ создаёт или продлевает.
order.created_atunix
Когда заказ был размещён.
order.delivered_atunix
Когда завершилась выдача. До этого отсутствует.
order.breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
invoiceobject
Присутствует, только пока заказ ждёт оплаты, — та же структура, что и везде.
Пример ответа{
"order": {
"order_id": "ord_7b2c9d", "product": "vpn", "kind": "new",
"status": "delivered", "funding": "balance", "total_usd": "11.90",
"invoice_id": "inv_5k8p2q", "items": 1,
"created_at": "1785230043", "delivered_at": "1785230103",
"breakdown": {
"model_name": "vpn_dynamic",
"model_type": "dynamic_v2",
"base_usd": "14.00",
"total_usd": "11.90",
"lines": [
{"code": "base", "kind": "base", "amount_usd": "14.00"},
{"code": "loyalty", "kind": "discount", "amount_usd": "-2.10", "pct": "15"}
]
}
}
}
https://apiservice.vitamindata.net/api/v1/ListOrdersИстория ваших заказов, сначала новые.
Запрос
limitintнеобязательно
Размер страницы. По умолчанию 25, максимум 100.
cursorcursorнеобязательно
next_cursor из предыдущего ответа. Для первой страницы опустите.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListOrders \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"limit":25,"cursor":""}'
Ответ200 · application/json
orders[].order_idstring
Публичный идентификатор заказа (ord_…).
orders[].productenum
Что было куплено.
Одно из:vpnvps
orders[].kindstring
Форма покупки: new, extend, upgrade…
orders[].statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
orders[].fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
orders[].total_usdmoney
Сумма, которую списывает заказ.
orders[].invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
orders[].itemsint
Сколько услуг заказ создаёт или продлевает.
orders[].created_atunix
Когда заказ был размещён.
orders[].delivered_atunix
Когда завершилась выдача. До этого отсутствует.
orders[].breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
next_cursorcursor
Верните его как cursor, чтобы получить следующую страницу. Отсутствует/пустой = вы получили всё.
Пример ответа{
"orders": [
{"order_id": "ord_7b2c9d", "product": "vpn", "kind": "new", "status": "delivered",
"funding": "balance", "total_usd": "11.90", "invoice_id": "inv_5k8p2q",
"items": 1, "created_at": "1785230043", "delivered_at": "1785230103"}
]
}
Управление VPN
https://apiservice.vitamindata.net/api/v1/ListVPNВсе ваши VPN-аккаунты, с остатком трафика и датой окончания.
Запрос
limitintнеобязательно
Размер страницы. По умолчанию 50, максимум 200.
cursorcursorнеобязательно
next_cursor из предыдущего ответа. Для первой страницы опустите.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListVPN \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"limit":25,"cursor":""}'
Ответ200 · application/json
vpns[].vpn_idstring
Публичный идентификатор, который принимают все остальные VPN-методы.
vpns[].usernamestring
Логин, который показывают приложения.
vpns[].statusstring
Состояние аккаунта, как его показывает панель — active, если он не приостановлен и не истёк.
vpns[].remaining_bytesbytes
Трафик, оставшийся суммарно по всем его пакетам.
vpns[].total_downloadbytes
Скачано за всё время, по данным живого VPN-плана. В ListVPN всегда 0 — список отдаётся из кэша, в котором нет разбивки по направлениям. Для списка используйте used_bytes, для разбивки — GetVPN/GetVPNUsage.
vpns[].total_uploadbytes
Отдано за всё время. То же замечание, что и для total_download: в ListVPN это 0.
vpns[].used_bytesbytes
Фактически израсходованный трафик за всё время (приём + отдача). Эта величина поддерживается для каждого VPN, поэтому верна на всех эндпоинтах, включая ListVPN.
vpns[].expires_atunix
Когда аккаунт истекает.
vpns[].max_onlineint
Допустимое число одновременных устройств.
vpns[].daily_limit_bytesbytes
Сегодняшний предел. Отсутствует/0 = дневного предела НЕТ.
vpns[].daily_used_bytesbytes
Израсходовано из сегодняшнего предела.
vpns[].daily_reset_unixunix
Когда сбрасывается дневной счётчик.
vpns[].allowed_protocolsint
Битовая маска протоколов для наших приложений. Считайте её непрозрачной.
vpns[].cache_atunix
Насколько свежи цифры: они не новее этой метки времени, если не установлен live.
vpns[].created_atunix
Когда аккаунт был создан.
vpns[].livebool
Цифры только что получены из сети, а не из кэша.
next_cursorcursor
Верните его как cursor, чтобы получить следующую страницу. Отсутствует/пустой = вы получили всё.
Пример ответа{
"vpns": [{
"vpn_id": "vpn_6t2k9p",
"username": "u482913",
"status": "active",
"remaining_bytes": "96636764160",
"total_download": "10737418240",
"used_bytes": "11811160064",
"total_upload": "1073741824",
"expires_at": "1793188800",
"max_online": 3,
"cache_at": "1785412700",
"created_at": "1785000000"
}],
"next_cursor": "vpn_6t2k9p"
}
https://apiservice.vitamindata.net/api/v1/GetVPNОдин аккаунт подробно. live:true означает, что цифры только что получены из сети.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPN \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p"}'
Ответ200 · application/json
vpn.vpn_idstring
Публичный идентификатор, который принимают все остальные VPN-методы.
vpn.usernamestring
Логин, который показывают приложения.
vpn.statusstring
Состояние аккаунта, как его показывает панель — active, если он не приостановлен и не истёк.
vpn.remaining_bytesbytes
Трафик, оставшийся суммарно по всем его пакетам.
vpn.total_downloadbytes
Скачано за всё время, по данным живого VPN-плана. В ListVPN всегда 0 — список отдаётся из кэша, в котором нет разбивки по направлениям. Для списка используйте used_bytes, для разбивки — GetVPN/GetVPNUsage.
vpn.total_uploadbytes
Отдано за всё время. То же замечание, что и для total_download: в ListVPN это 0.
vpn.used_bytesbytes
Фактически израсходованный трафик за всё время (приём + отдача). Эта величина поддерживается для каждого VPN, поэтому верна на всех эндпоинтах, включая ListVPN.
vpn.expires_atunix
Когда аккаунт истекает.
vpn.max_onlineint
Допустимое число одновременных устройств.
vpn.daily_limit_bytesbytes
Сегодняшний предел. Отсутствует/0 = дневного предела НЕТ.
vpn.daily_used_bytesbytes
Израсходовано из сегодняшнего предела.
vpn.daily_reset_unixunix
Когда сбрасывается дневной счётчик.
vpn.allowed_protocolsint
Битовая маска протоколов для наших приложений. Считайте её непрозрачной.
vpn.cache_atunix
Насколько свежи цифры: они не новее этой метки времени, если не установлен live.
vpn.created_atunix
Когда аккаунт был создан.
vpn.livebool
Цифры только что получены из сети, а не из кэша.
livebool
Свежие данные из сети. Отсутствует = ответ отдан из модели чтения и его возраст — cache_at.
Пример ответа{
"vpn": {
"vpn_id": "vpn_6t2k9p",
"username": "u482913",
"status": "active",
"remaining_bytes": "96636764160",
"total_download": "10737418240",
"used_bytes": "11811160064",
"total_upload": "1073741824",
"expires_at": "1793188800",
"max_online": 3,
"cache_at": "1785412700",
"created_at": "1785000000"
},
"live": true
}
https://apiservice.vitamindata.net/api/v1/GetVPNUsageИзрасходованный и оставшийся трафик, плюс сегодняшний предел, если он есть.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPNUsage \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p"}'
Ответ200 · application/json
vpn_idstring
Возвращается эхом.
remaining_bytesbytes
Оставшийся трафик.
total_downloadbytes
Скачано за всё время.
total_uploadbytes
Отдано за всё время.
expires_atunix
Когда аккаунт истекает.
daily_limit_bytesbytes
Сегодняшний предел. Отсутствует = предела нет.
daily_used_bytesbytes
Израсходовано из сегодняшнего предела.
daily_reset_unixunix
Когда сбрасывается дневной счётчик.
cache_atunix
Свежесть цифр, когда они не получены вживую.
livebool
Только что получено из сети.
seriesarray
Зарезервировано под исторический ряд потребления — сегодня пусто.
series[].tunix
Начало интервала.
series[].rxbytes
Скачано за интервал.
series[].txbytes
Отдано за интервал.
Пример ответа{
"vpn_id": "vpn_6t2k9p",
"remaining_bytes": "96636764160",
"total_download": "10737418240",
"total_upload": "1073741824",
"expires_at": "1793188800",
"daily_limit_bytes": "53687091200",
"daily_used_bytes": "1273741824",
"daily_reset_unix": "1785456000",
"cache_at": "1785412700",
"live": true
}
https://apiservice.vitamindata.net/api/v1/ListVPNBundlesКошельки трафика за одним аккаунтом, в порядке их расходования.
Именно так вы отвечаете на вопрос «почему у клиента убавился платный трафик, пока оставался бесплатный?» — следующим расходуется queue_position 1. live:false означает, что мы не смогли их прочитать, а не что их нет.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListVPNBundles \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p"}'
Ответ200 · application/json
bundlesarray
Кошельки, в порядке расходования.
bundles[].bundle_idstring
Идентификатор кошелька.
bundles[].freebool
Выдан в рамках бесплатного уровня, а не куплен.
bundles[].sourceenum
Откуда взялся кошелёк.
Одно из:buyextendmigratedfree_tier
bundles[].granted_bytesbytes
Его полный размер на момент выдачи.
bundles[].remaining_bytesbytes
Сколько в нём осталось.
bundles[].granted_atunix
Когда он был выдан.
bundles[].expires_atunix
Когда он истекает — независимо от того, израсходован или нет.
bundles[].daily_limit_bytesbytes
Его собственный дневной предел. Отсутствует = предела нет.
bundles[].statusenum
Словами, а не числами, — чтобы вам не пришлось запоминать, что 2 значит «исчерпан».
Одно из:activedisabledexhausted
bundles[].queue_positionint
Нумерация с 1 по ПРИГОДНЫМ кошелькам, в порядке расходования — следующим расходуется 1. 0/отсутствует означает, что кошелёк вне очереди (израсходован, истёк или отключён).
bundles[].plan_gbint
Размер, с которым он продавался, в ГБ.
bundles[].plan_daysint
Срок действия, с которым он продавался, в днях.
bundles[].invoice_idstring
Покупка, из которой он появился. Отсутствует у бесплатной выдачи.
livebool
Отсутствует/false = система учёта прав была недоступна, поэтому список ПУСТОЙ, а не неверный. «Мы не смогли их прочитать» и «их нет» — разные утверждения.
Пример ответа{
"bundles": [
{"bundle_id": "bnd_2m8x", "source": "buy",
"granted_bytes": "107374182400", "remaining_bytes": "96636764160",
"granted_at": "1785000000", "expires_at": "1793188800",
"status": "active", "queue_position": 1, "plan_gb": 100, "plan_days": 30,
"invoice_id": "inv_5k8p2q"},
{"bundle_id": "bnd_9k1f", "free": true, "source": "free_tier",
"granted_bytes": "5368709120", "remaining_bytes": "5368709120",
"granted_at": "1784000000", "expires_at": "1793188800",
"status": "active", "queue_position": 2, "plan_gb": 5, "plan_days": 30}
],
"live": true
}
POST
GetSubscriptionLink
read
https://apiservice.vitamindata.net/api/v1/GetSubscriptionLinkСсылка подписки, которую импортирует приложение клиента. Это и есть то, что вы поставляете при продаже VPN.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetSubscriptionLink \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p"}'
Ответ200 · application/json
subscription_urlstring
Передайте это приложению вашего клиента — это и есть вся выдача.
tokenstring
Голый токен — для сборки собственных QR-кодов или ссылок импорта в приложение.
Пример ответа{
"subscription_url": "https://sub.example.com/s/9f3kq8x2",
"token": "9f3kq8x2"
}
POST
SetVPNPassword
credentials
https://apiservice.vitamindata.net/api/v1/SetVPNPasswordМеняет пароль аккаунта.
Требует отдельную область credentials — manage её никогда не подразумевает.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
new_passwordstringобязательное
Пароль, который нужно установить.
credentialstringнеобязательно
Какой логин — для аккаунтов с несколькими. Пусто = основной.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/SetVPNPassword \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p","new_password":"s3cr3t-Enough","credential":""}'
Ответ200 · application/json
usernamestring
Логин, к которому применилось изменение.
Пример ответа{"username": "u482913"}
https://apiservice.vitamindata.net/api/v1/SetVPNStateПриостанавливает или возобновляет аккаунт.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
stateenumобязательное
Что сделать.
Одно из:suspendresume
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/SetVPNState \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p","state":"suspend"}'
Ответ200 · application/json
statusenum
Состояние, в котором оказался аккаунт.
Одно из:suspendedactive
Пример ответа{"status": "suspended"}
https://apiservice.vitamindata.net/api/v1/DeleteVPNУдаляет аккаунт. Отмены и возврата нет.
Запрос
vpn_idstringобязательное
Публичный идентификатор аккаунта (vpn_…), из ListVPN или из выдачи заказа.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/DeleteVPN \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vpn_id":"vpn_6t2k9p"}'
Ответ200 · application/json
statusenum
При успехе всегда deleted.
Одно из:deleted
Пример ответа{"status": "deleted"}
Продажа серверов
Продажа VPS — тот же контракт оплаты, что и продажа VPN, отличается только корзина.
https://apiservice.vitamindata.net/api/v1/GetVPSStorefrontЛокации, тарифы с ценами в каждой из них и загрузочные образы.
Узел с available:false исчерпал ёмкость — показывайте его, но не предлагайте к покупке.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPSStorefront \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
nodesarray
Локации, каждая со своими тарифами и ценами.
nodes[].node_idstring
То, что принимает node_id корзины.
nodes[].labelstring
Отображаемое имя (Frankfurt).
nodes[].regionstring
Грубый код региона для группировки.
nodes[].countrystring
Код страны ISO, для флагов.
nodes[].availablebool
Отсутствует/false = ёмкость исчерпана: показывайте, но не предлагайте к покупке.
nodes[].plansarray
Что здесь продаётся, с ценами.
nodes[].plans[].plan_codestring
То, что принимает plan_code корзины.
nodes[].plans[].namestring
Отображаемое имя.
nodes[].plans[].vcpuint
Ядра.
nodes[].plans[].ram_mbint
Память в МБ.
nodes[].plans[].disk_gbint
Диск в ГБ.
nodes[].plans[].traffic_bytesbytes
Включённый месячный трафик.
nodes[].plans[].price_usd_monthmoney
Месячная цена НА ЭТОМ УЗЛЕ — тот же тариф в другом месте может стоить иначе.
imagesarray
Всё, что можно загрузить или установить.
images[].shastring
ЕДИНСТВЕННЫЙ идентификатор образа — его принимают корзина, переустановка и подключение ISO.
images[].namestring
Человекочитаемое имя (Debian 13).
images[].kindenum
Образ disk разворачивается напрямую; iso — установщик, с которого вы загружаетесь.
Одно из:diskiso
images[].os_familyenum
Для группировки и иконок в вашем интерфейсе.
Одно из:linuxwindowsmikrotik
images[].min_disk_gbint
Переустановка на диск меньшего размера отклоняется — сначала увеличьте диск.
months_minint
Минимальный срок, на который можно купить новую VM.
months_maxint
Максимальный.
Пример ответа{
"nodes": [
{"node_id": "de1", "label": "Frankfurt", "region": "eu", "country": "DE", "available": true,
"plans": [
{"plan_code": "s2", "name": "S2", "vcpu": 2, "ram_mb": 4096, "disk_gb": 40,
"traffic_bytes": "2199023255552", "price_usd_month": "8.00"}
]}
],
"images": [
{"sha": "9a1b8c2d7e6f", "name": "Debian 13", "kind": "disk", "os_family": "linux", "min_disk_gb": 10}
],
"months_min": 1,
"months_max": 12
}
https://apiservice.vitamindata.net/api/v1/ListVPSImagesВсе образы, которые можно загрузить или установить, по sha.
Именно этот sha принимают корзина, переустановка и подключение ISO. Больше образ ничем не задаётся.
Запрос
Параметров нет — отправьте пустой объект, {}.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListVPSImages \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{}'
Ответ200 · application/json
images[].shastring
ЕДИНСТВЕННЫЙ идентификатор образа — его принимают корзина, переустановка и подключение ISO.
images[].namestring
Человекочитаемое имя (Debian 13).
images[].kindenum
Образ disk разворачивается напрямую; iso — установщик, с которого вы загружаетесь.
Одно из:diskiso
images[].os_familyenum
Для группировки и иконок в вашем интерфейсе.
Одно из:linuxwindowsmikrotik
images[].min_disk_gbint
Переустановка на диск меньшего размера отклоняется — сначала увеличьте диск.
Пример ответа{
"images": [
{"sha": "9a1b8c2d7e6f", "name": "Debian 13", "kind": "disk", "os_family": "linux", "min_disk_gb": 10},
{"sha": "3f4e5d6c7b8a", "name": "Windows Server 2025 installer", "kind": "iso",
"os_family": "windows", "min_disk_gb": 40}
]
}
https://apiservice.vitamindata.net/api/v1/QuoteVPSЦена нового сервера, по позициям.
Запрос
cartobjectобязательное
Сервер для расчёта цены.
cart.node_idstringобязательное
Где создать VM, из узлов магазина.
cart.placementstringзарезервировано — не отправляйте
Зарезервировано. В этом API место создания сервера всегда определяет node_id — передавайте его, а узел выбирайте сами из магазина.
Одно из:auto
cart.plan_codestringобязательное
Тариф, из собственного прайс-листа выбранного узла — тарифы и цены различаются между узлами.
cart.image_shastringобязательное
Что загрузить или установить, по sha. Дисковые образы разворачиваются напрямую; установочный ISO приходит уже подключённым, и VM настроена загружаться с него.
cart.namestringобязательное
Имя хоста / метка VM.
cart.monthsintобязательное
Начальный срок, в границах месяцев магазина.
cart.extra_disk_gbintнеобязательно
Дополнительный диск сверх тарифа, в ГБ.
cart.extra_ipsintнеобязательно
Дополнительные публичные IPv4-адреса.
cart.extra_traffic_tbmoneyнеобязательно
Дополнительный месячный трафик в ТБ, десятичной строкой ("0.5").
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/QuoteVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"cart":{"node_id":"de1","plan_code":"s2","image_sha":"9a1b8c2d7e6f","months":2,"name":"web-1","extra_disk_gb":20,"extra_ips":1,"extra_traffic_tb":"0.5"}}'
Ответ200 · application/json
quoteobject
Цена по позициям. Ничего не создаётся и ничего не списывается.
quote.model_namestring
Какая модель ценообразования ответила.
quote.model_typestring
Версия движка модели.
quote.base_usdmoney
Цена до скидок и надбавок.
quote.total_usdmoney
Итоговая цена — сумма, которую спишет продажа с этой корзиной.
quote.linesarray
Постатейная разбивка, со знаками, в точности суммирующаяся в итог.
quote.lines[].codestring
Что это за строка (base, код скидки, надбавка…).
quote.lines[].kindstring
Категория строки, для группировки в вашем интерфейсе.
quote.lines[].amount_usdmoney
Со знаком. Скидки отрицательные; строки в точности суммируются в total_usd.
quote.lines[].pctstring
Процент за строкой, когда он есть.
quote.cappedbool
Итог упёрся в потолок модели.
quote.floor_appliedbool
Итог был поднят до нижней границы модели.
quote.clampedenum
Установлено, если значение корзины было приведено к границам перед расчётом цены.
Одно из:minmax
quote.invalidstring
Непустое значение означает, что корзину нельзя оценить — покажите его и НИКОГДА не списывайте деньги по такому расчёту.
quote.metamap
Дополнительные данные модели, строка→строка (например, remaining_days у апгрейда).
Пример ответа{
"quote": {
"model_name": "vps_plan",
"model_type": "vps_plan_v1",
"base_usd": "16.00",
"total_usd": "16.00",
"lines": [
{"code": "plan_s2", "kind": "base", "amount_usd": "16.00"}
],
"meta": {"months": "2"}
}
}
POST
CreateVPSOrder
buyIdempotency-Key
https://apiservice.vitamindata.net/api/v1/CreateVPSOrderПокупает и разворачивает сервер.
Опрашивайте GetOrder о выдаче, затем GetVPS о самой машине.
Запрос
cartobjectобязательное
Что создать — та же структура, которую оценивает QuoteVPS.
cart.node_idstringобязательное
Где создать VM, из узлов магазина.
cart.placementstringзарезервировано — не отправляйте
Зарезервировано. В этом API место создания сервера всегда определяет node_id — передавайте его, а узел выбирайте сами из магазина.
Одно из:auto
cart.plan_codestringобязательное
Тариф, из собственного прайс-листа выбранного узла — тарифы и цены различаются между узлами.
cart.image_shastringобязательное
Что загрузить или установить, по sha. Дисковые образы разворачиваются напрямую; установочный ISO приходит уже подключённым, и VM настроена загружаться с него.
cart.namestringобязательное
Имя хоста / метка VM.
cart.monthsintобязательное
Начальный срок, в границах месяцев магазина.
cart.extra_disk_gbintнеобязательно
Дополнительный диск сверх тарифа, в ГБ.
cart.extra_ipsintнеобязательно
Дополнительные публичные IPv4-адреса.
cart.extra_traffic_tbmoneyнеобязательно
Дополнительный месячный трафик в ТБ, десятичной строкой ("0.5").
fundingenumобязательное
Как платить — см. Оплата. Значения по умолчанию нет: запрос без него отклоняется.
Одно из:FUNDING_AUTOFUNDING_BALANCEFUNDING_INVOICE
expected_total_usdmoneyнеобязательно
Страховка подтверждения. Если задано и наш свежий расчёт отличается, продажа отклоняется с price_changed, вместо того чтобы списать сумму, которой ваш клиент не видел.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/CreateVPSOrder \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"cart":{"node_id":"de1","plan_code":"s2","image_sha":"9a1b8c2d7e6f","months":2,"name":"web-1","extra_disk_gb":20,"extra_ips":1,"extra_traffic_tb":"0.5"},"funding":"FUNDING_AUTO","expected_total_usd":"36.00"}'
Ответ200 · application/json
orderobject
Заказ — опрашивайте GetOrder, пока статус не станет delivered.
order.order_idstring
Публичный идентификатор заказа (ord_…).
order.productenum
Что было куплено.
Одно из:vpnvps
order.kindstring
Форма покупки: new, extend, upgrade…
order.statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
order.fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
order.total_usdmoney
Сумма, которую списывает заказ.
order.invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
order.itemsint
Сколько услуг заказ создаёт или продлевает.
order.created_atunix
Когда заказ был размещён.
order.delivered_atunix
Когда завершилась выдача. До этого отсутствует.
order.breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
invoiceobject
Счёт за заказом: подлежит оплате при payment_required, уже оплачен при completed.
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
paidbool
Деньги получены. Отсутствует (= false) при payment_required.
statusenum
ГЛАВНОЕ поле для ветвления — см. Оплата.
Одно из:completedpayment_required
Пример ответа{
"order": {
"order_id": "ord_2f8k3j", "product": "vps", "kind": "new",
"status": "invoiced", "funding": "invoice", "total_usd": "16.00",
"invoice_id": "inv_7h4w9s", "items": 1, "created_at": "1785412800"
},
"invoice": {
"invoice_id": "inv_7h4w9s", "status": "pending",
"pay_url": "https://pay.example.com/i/inv_7h4w9s",
"price_usd": "16.00", "expires_at": "1785499200"
},
"status": "payment_required"
}
https://apiservice.vitamindata.net/api/v1/QuoteVPSExtendСколько стоит продление сервера.
Запрос
vps_idstringобязательное
Идентификатор сервера, из ListVPS.
monthsintобязательное
Сколько месяцев добавить. months_min…months_max магазина — это то, что стоит предлагать в вашем интерфейсе, но продление к ним НЕ приводится: передавайте разумное число, потому что рассчитано и списано будет ровно то, что вы передали.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/QuoteVPSExtend \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vps_id":"vm_7q3k1n","months":1}'
Ответ200 · application/json
quoteobject
Цена по позициям. Ничего не создаётся и ничего не списывается.
quote.model_namestring
Какая модель ценообразования ответила.
quote.model_typestring
Версия движка модели.
quote.base_usdmoney
Цена до скидок и надбавок.
quote.total_usdmoney
Итоговая цена — сумма, которую спишет продажа с этой корзиной.
quote.linesarray
Постатейная разбивка, со знаками, в точности суммирующаяся в итог.
quote.lines[].codestring
Что это за строка (base, код скидки, надбавка…).
quote.lines[].kindstring
Категория строки, для группировки в вашем интерфейсе.
quote.lines[].amount_usdmoney
Со знаком. Скидки отрицательные; строки в точности суммируются в total_usd.
quote.lines[].pctstring
Процент за строкой, когда он есть.
quote.cappedbool
Итог упёрся в потолок модели.
quote.floor_appliedbool
Итог был поднят до нижней границы модели.
quote.clampedenum
Установлено, если значение корзины было приведено к границам перед расчётом цены.
Одно из:minmax
quote.invalidstring
Непустое значение означает, что корзину нельзя оценить — покажите его и НИКОГДА не списывайте деньги по такому расчёту.
quote.metamap
Дополнительные данные модели, строка→строка (например, remaining_days у апгрейда).
Пример ответа{
"quote": {
"model_name": "vps_plan",
"model_type": "vps_plan_v1",
"base_usd": "16.00",
"total_usd": "16.00",
"lines": [
{"code": "plan_s2", "kind": "base", "amount_usd": "16.00"}
],
"meta": {"months": "2"}
}
}
POST
ExtendVPS
buyIdempotency-Key
https://apiservice.vitamindata.net/api/v1/ExtendVPSПродлевает сервер.
Продлевать заранее не дороже: новая дата окончания считается от текущей, а не от сегодняшнего дня.
Запрос
vps_idstringобязательное
Идентификатор сервера, из ListVPS.
monthsintобязательное
Сколько месяцев добавить. months_min…months_max магазина — это то, что стоит предлагать в вашем интерфейсе, но продление к ним НЕ приводится: передавайте разумное число, потому что рассчитано и списано будет ровно то, что вы передали.
fundingenumобязательное
Как платить — см. Оплата. Значения по умолчанию нет: запрос без него отклоняется.
Одно из:FUNDING_AUTOFUNDING_BALANCEFUNDING_INVOICE
expected_total_usdmoneyнеобязательно
Страховка подтверждения. Если задано и наш свежий расчёт отличается, продажа отклоняется с price_changed, вместо того чтобы списать сумму, которой ваш клиент не видел.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ExtendVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"vps_id":"vm_7q3k1n","months":1,"funding":"FUNDING_AUTO","expected_total_usd":"8.00"}'
Ответ200 · application/json
orderobject
Заказ — опрашивайте GetOrder, пока статус не станет delivered.
order.order_idstring
Публичный идентификатор заказа (ord_…).
order.productenum
Что было куплено.
Одно из:vpnvps
order.kindstring
Форма покупки: new, extend, upgrade…
order.statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
order.fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
order.total_usdmoney
Сумма, которую списывает заказ.
order.invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
order.itemsint
Сколько услуг заказ создаёт или продлевает.
order.created_atunix
Когда заказ был размещён.
order.delivered_atunix
Когда завершилась выдача. До этого отсутствует.
order.breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
invoiceobject
Счёт за заказом: подлежит оплате при payment_required, уже оплачен при completed.
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
paidbool
Деньги получены. Отсутствует (= false) при payment_required.
statusenum
ГЛАВНОЕ поле для ветвления — см. Оплата.
Одно из:completedpayment_required
Пример ответа{
"order": {
"order_id": "ord_5d1p8m", "product": "vps", "kind": "extend",
"status": "paid", "funding": "balance", "total_usd": "8.00",
"invoice_id": "inv_1c6v3z", "items": 1, "created_at": "1785412800"
},
"invoice": {
"invoice_id": "inv_1c6v3z", "status": "confirmed", "price_usd": "8.00"
},
"paid": true,
"status": "completed"
}
https://apiservice.vitamindata.net/api/v1/QuoteVPSUpgradeСколько стоит конфигурация побольше, пропорционально уже оплаченному времени.
Запрос
vps_idstringобязательное
Идентификатор сервера, из ListVPS.
specobjectобязательное
ЦЕЛЕВАЯ конфигурация. Опущенные/нулевые поля сохраняют текущее значение.
spec.vcpuintнеобязательно
Целевое число ядер. 0 сохраняет текущее значение.
spec.ram_mbintнеобязательно
Целевая память в МБ. 0 сохраняет текущее значение.
spec.disk_gbintнеобязательно
Целевой диск в ГБ. Диск только растёт — меньшее значение отклоняется: уменьшение файловой системы под работающей ОС — это потеря данных.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/QuoteVPSUpgrade \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"vps_id":"vm_7q3k1n","spec":{"vcpu":4,"ram_mb":8192,"disk_gb":80}}'
Ответ200 · application/json
quoteobject
Цена по позициям. Ничего не создаётся и ничего не списывается.
quote.model_namestring
Какая модель ценообразования ответила.
quote.model_typestring
Версия движка модели.
quote.base_usdmoney
Цена до скидок и надбавок.
quote.total_usdmoney
Итоговая цена — сумма, которую спишет продажа с этой корзиной.
quote.linesarray
Постатейная разбивка, со знаками, в точности суммирующаяся в итог.
quote.lines[].codestring
Что это за строка (base, код скидки, надбавка…).
quote.lines[].kindstring
Категория строки, для группировки в вашем интерфейсе.
quote.lines[].amount_usdmoney
Со знаком. Скидки отрицательные; строки в точности суммируются в total_usd.
quote.lines[].pctstring
Процент за строкой, когда он есть.
quote.cappedbool
Итог упёрся в потолок модели.
quote.floor_appliedbool
Итог был поднят до нижней границы модели.
quote.clampedenum
Установлено, если значение корзины было приведено к границам перед расчётом цены.
Одно из:minmax
quote.invalidstring
Непустое значение означает, что корзину нельзя оценить — покажите его и НИКОГДА не списывайте деньги по такому расчёту.
quote.metamap
Дополнительные данные модели, строка→строка (например, remaining_days у апгрейда).
restart_requiredbool
Применение этой конфигурации требует перезапуска питания — клиент должен узнать об этом ДО оплаты.
monthly_before_usdmoney
Регулярная цена сегодня.
monthly_after_usdmoney
Регулярная цена после апгрейда — сколько отныне будут стоить продления.
Пример ответа{
"quote": {
"model_name": "vps_upgrade",
"model_type": "vps_plan_v1",
"base_usd": "4.20",
"total_usd": "4.20",
"lines": [
{"code": "prorate_vcpu", "kind": "vps_upgrade", "amount_usd": "2.40"},
{"code": "prorate_ram", "kind": "vps_upgrade", "amount_usd": "1.80"}
],
"meta": {"remaining_days": "21", "monthly_delta_usd": "6.00", "quote_expires_at": "1785416400"}
},
"restart_required": true,
"monthly_before_usd": "8.00",
"monthly_after_usd": "14.00"
}
POST
UpgradeVPS
buyIdempotency-Key
https://apiservice.vitamindata.net/api/v1/UpgradeVPSОплачивает и применяет конфигурацию побольше. Диск может только расти.
Запрос
vps_idstringобязательное
Идентификатор сервера, из ListVPS.
specobjectобязательное
ЦЕЛЕВАЯ конфигурация — сначала рассчитайте её цену; расчёт заодно скажет о перезагрузке.
spec.vcpuintнеобязательно
Целевое число ядер. 0 сохраняет текущее значение.
spec.ram_mbintнеобязательно
Целевая память в МБ. 0 сохраняет текущее значение.
spec.disk_gbintнеобязательно
Целевой диск в ГБ. Диск только растёт — меньшее значение отклоняется: уменьшение файловой системы под работающей ОС — это потеря данных.
fundingenumобязательное
Как платить — см. Оплата. Значения по умолчанию нет: запрос без него отклоняется.
Одно из:FUNDING_AUTOFUNDING_BALANCEFUNDING_INVOICE
expected_total_usdmoneyнеобязательно
Страховка подтверждения. Если задано и наш свежий расчёт отличается, продажа отклоняется с price_changed, вместо того чтобы списать сумму, которой ваш клиент не видел.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/UpgradeVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"vps_id":"vm_7q3k1n","spec":{"vcpu":4,"ram_mb":8192,"disk_gb":80},"funding":"FUNDING_AUTO","expected_total_usd":"4.20"}'
Ответ200 · application/json
orderobject
Заказ — опрашивайте GetOrder, пока статус не станет delivered.
order.order_idstring
Публичный идентификатор заказа (ord_…).
order.productenum
Что было куплено.
Одно из:vpnvps
order.kindstring
Форма покупки: new, extend, upgrade…
order.statusenum
Жизненный цикл. Цель — delivered; needs_operator означает, что деньги пришли и выдачу завершает человек — не покупайте повторно; expired означает, что счёт истёк неоплаченным.
Одно из:createdinvoicedpaiddeliveringdeliveredneeds_operatorfailedrefund_pendingrefundedexpired
order.fundingenum
Каким способом заказ был фактически оплачен. FUNDING_AUTO разрешается в один из них.
Одно из:invoicebalance
order.total_usdmoney
Сумма, которую списывает заказ.
order.invoice_idstring
Счёт за заказом — он есть у каждого заказа, каким бы способом тот ни был оплачен.
order.itemsint
Сколько услуг заказ создаёт или продлевает.
order.created_atunix
Когда заказ был размещён.
order.delivered_atunix
Когда завершилась выдача. До этого отсутствует.
order.breakdownobject
Расчёт, на который согласился клиент, дословно — та же структура, что возвращает Quote.
invoiceobject
Счёт за заказом: подлежит оплате при payment_required, уже оплачен при completed.
invoice.invoice_idstring
Идентификатор счёта в шлюзе (inv_…).
invoice.statusenum
pending — можно оплачивать. Всё от confirmed до delivered_redirected означает, что деньги пришли необратимо — считайте все эти статусы ОПЛАЧЕННЫМИ. expired означает, что ссылка истекла неоплаченной.
Одно из:pendingconfirmedsweepingsweptdeliveringdelivereddelivered_redirectedexpired
invoice.pay_urlstring
Размещённая у нас страница оплаты. Отправляйте клиента сюда; за ней живут все способы оплаты (монеты, сети, баланс).
invoice.pay_telegram_urlstring
Тот же счёт, оплачиваемый прямо в Telegram: ссылка открывает бот самого платёжного провайдера, который показывает сумму и там же принимает оплату. Предлагайте её рядом с pay_url тем, кто предпочитает не выходить из приложения. Может отсутствовать — она есть только у платёжного провайдера с настроенным ботом, поэтому никогда не делайте её единственной кнопкой оплаты.
invoice.price_usdmoney
Сумма, которую собирает счёт.
invoice.expires_atunix
Когда закрывается окно оплаты.
paidbool
Деньги получены. Отсутствует (= false) при payment_required.
statusenum
ГЛАВНОЕ поле для ветвления — см. Оплата.
Одно из:completedpayment_required
Пример ответа{
"order": {
"order_id": "ord_5d1p8m", "product": "vps", "kind": "extend",
"status": "paid", "funding": "balance", "total_usd": "8.00",
"invoice_id": "inv_1c6v3z", "items": 1, "created_at": "1785412800"
},
"invoice": {
"invoice_id": "inv_1c6v3z", "status": "confirmed", "price_usd": "8.00"
},
"paid": true,
"status": "completed"
}
Управление серверами
Каждый метод здесь принимает сервер по id — в этих вызовах поле буквально называется id, в отличие от vps_id у денежных методов.
https://apiservice.vitamindata.net/api/v1/ListVPSВаши машины, с состоянием питания и адресами.
Запрос
limitintнеобязательно
Размер страницы. По умолчанию 50.
cursorcursorнеобязательно
next_cursor из предыдущего ответа. Для первой страницы опустите.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ListVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"limit":50,"cursor":""}'
Ответ200 · application/json
vps[].idstring
Идентификатор сервера — его принимают id каждого метода управления и vps_id каждого денежного метода.
vps[].namestring
Её имя хоста / метка.
vps[].node_idstring
Где она работает.
vps[].lifecycleenum
0 разворачивается · 1 активна · 2 приостановлена · 3 удаляется · 4 удалена.
Одно из:01234
vps[].provisionedbool
Машина существует на своём хосте.
vps[].power_desiredenum
Каким питание ДОЛЖНО быть: 1 — включено, 0/отсутствует — выключено. Реальное состояние — GetVPSStats.running.
Одно из:01
vps[].mem_mbint
Память в МБ.
vps[].disk_gbint
Диск в ГБ.
vps[].image_shastring
С чего она загрузилась или установилась.
vps[].expires_atunix
Когда сервер истекает — продлите через ExtendVPS до этого момента.
vps[].created_atunix
Когда она была создана.
vps[].ipsarray
Её публичные адреса.
vps[].private_ipstring
Её приватный адрес, если он предусмотрен тарифом.
next_cursorcursor
Верните его как cursor, чтобы получить следующую страницу. Отсутствует/пустой = вы получили всё.
Пример ответа{
"vps": [{
"id": "vm_7q3k1n",
"name": "web-1",
"node_id": "de1",
"lifecycle": 1,
"provisioned": true,
"power_desired": 1,
"vcpu": 2,
"mem_mb": 4096,
"disk_gb": 40,
"image_sha": "9a1b8c2d7e6f",
"expires_at": "1793188800",
"created_at": "1785000000",
"ips": ["203.0.113.10"],
"private_ip": "10.77.0.10"
}]
}
https://apiservice.vitamindata.net/api/v1/GetVPSОдна машина подробно.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n"}'
Ответ200 · application/json
vps.idstring
Идентификатор сервера — его принимают id каждого метода управления и vps_id каждого денежного метода.
vps.namestring
Её имя хоста / метка.
vps.node_idstring
Где она работает.
vps.lifecycleenum
0 разворачивается · 1 активна · 2 приостановлена · 3 удаляется · 4 удалена.
Одно из:01234
vps.provisionedbool
Машина существует на своём хосте.
vps.power_desiredenum
Каким питание ДОЛЖНО быть: 1 — включено, 0/отсутствует — выключено. Реальное состояние — GetVPSStats.running.
Одно из:01
vps.mem_mbint
Память в МБ.
vps.image_shastring
С чего она загрузилась или установилась.
vps.expires_atunix
Когда сервер истекает — продлите через ExtendVPS до этого момента.
vps.created_atunix
Когда она была создана.
vps.ipsarray
Её публичные адреса.
vps.private_ipstring
Её приватный адрес, если он предусмотрен тарифом.
livebool
Только что прочитано из системы.
Пример ответа{
"vps": {
"id": "vm_7q3k1n",
"name": "web-1",
"node_id": "de1",
"lifecycle": 1,
"provisioned": true,
"power_desired": 1,
"vcpu": 2,
"mem_mb": 4096,
"disk_gb": 40,
"image_sha": "9a1b8c2d7e6f",
"expires_at": "1793188800",
"created_at": "1785000000",
"ips": ["203.0.113.10"],
"private_ip": "10.77.0.10"
},
"live": true
}
https://apiservice.vitamindata.net/api/v1/GetVPSStatsCPU, память, диск и сеть в реальном времени.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPSStats \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n"}'
Ответ200 · application/json
cpu_pctint
Загрузка CPU, в процентах.
mem_used_mbint
Занятая память, МБ.
disk_used_mbint
Занятый диск, МБ.
rx_bpsint64
Входящий, бит в секунду.
tx_bpsint64
Исходящий, бит в секунду.
runningbool
Машина прямо сейчас включена.
updated_atunix
Когда были сняты эти показатели.
Пример ответа{
"cpu_pct": 12,
"mem_used_mb": 1536,
"disk_used_mb": 9216,
"rx_bps": "1048576",
"tx_bps": "524288",
"running": true,
"updated_at": "1785412790"
}
https://apiservice.vitamindata.net/api/v1/GetVPSUsageТрафик, израсходованный из квоты машины, по пакетам.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/GetVPSUsage \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n"}'
Ответ200 · application/json
total_downbytes
Скачано за всё время.
total_upbytes
Отдано за всё время.
bundlesarray
Пакеты трафика; current помечает тот, что расходуется сейчас.
bundles[].idint64
Идентификатор пакета трафика в вычислительной системе.
bundles[].modeint
Код режима учёта этой системы. Считайте непрозрачным.
bundles[].bytes_totalbytes
Полная квота пакета.
bundles[].used_dlbytes
Скачано в счёт него.
bundles[].used_upbytes
Отдано в счёт него.
bundles[].stateint
Код состояния этой системы. Считайте непрозрачным.
bundles[].currentbool
Это пакет, который расходуется прямо сейчас.
bundles[].expires_atunix
Когда пакет истекает.
Пример ответа{
"total_down": "53687091200",
"total_up": "10737418240",
"bundles": [
{"id": "41", "mode": 1, "bytes_total": "2199023255552",
"used_dl": "53687091200", "used_up": "10737418240",
"state": 1, "current": true, "expires_at": "1793188800"}
]
}
https://apiservice.vitamindata.net/api/v1/VPSPowerУправление питанием.
shutdown просит операционную систему; force_stop выдёргивает питание. Предпочитайте первое.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
actionenumобязательное
shutdown/reboot — корректные; reset/force_stop — кнопка питания.
Одно из:startshutdownrebootresetforce_stop
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/VPSPower \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n","action":"reboot"}'
Ответ200 · application/json
okbool
Система приняла действие. Следите за фактическим состоянием машины через GetVPSStats.
Пример ответа{"ok": true}
https://apiservice.vitamindata.net/api/v1/ReinstallVPSСтирает диск и устанавливает свежий образ.
Разрушающая операция, НЕ безопасная для повтора — один вызов, одна переустановка. Образ должен уместиться на текущий диск; если нет, сначала увеличьте диск.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
image_shastringобязательное
Образ, по sha из ListVPSImages. Другого способа указать образ нет, а sha не из каталога отклоняется.
reset_rootboolнеобязательно
Заодно сгенерировать новый пароль root.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/ReinstallVPS \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n","image_sha":"9a1b8c2d7e6f","reset_root":true}'
Ответ200 · application/json
okbool
Система приняла действие. Следите за фактическим состоянием машины через GetVPSStats.
Пример ответа{"ok": true}
https://apiservice.vitamindata.net/api/v1/AttachVPSISOПодключает установочный ISO. Чтобы загрузиться с него, задайте порядок загрузки 1.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
image_shastringобязательное
Образ, по sha из ListVPSImages. Другого способа указать образ нет, а sha не из каталога отклоняется.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/AttachVPSISO \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n","image_sha":"3f4e5d6c7b8a"}'
Ответ200 · application/json
okbool
Система приняла действие. Следите за фактическим состоянием машины через GetVPSStats.
Пример ответа{"ok": true}
https://apiservice.vitamindata.net/api/v1/DetachVPSISOОтключает ISO и возвращает загрузку с диска.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/DetachVPSISO \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n"}'
Ответ200 · application/json
okbool
Система приняла действие. Следите за фактическим состоянием машины через GetVPSStats.
Пример ответа{"ok": true}
POST
SetVPSBootOrder
manage
https://apiservice.vitamindata.net/api/v1/SetVPSBootOrderКакое устройство загружается первым.
Запрос
idstringобязательное
Идентификатор сервера, из ListVPS. Обратите внимание: у методов управления поле называется id — только денежные методы пишут его как vps_id.
orderenumобязательное
0 — сначала диск, 1 — сначала CD-ROM.
Одно из:01
Пример запросаcurl https://apiservice.vitamindata.net/api/v1/SetVPSBootOrder \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"vm_7q3k1n","order":1}'
Ответ200 · application/json
okbool
Система приняла действие. Следите за фактическим состоянием машины через GetVPSStats.
Пример ответа{"ok": true}