api v1

Void API — твои домены, серверы и хостинг по REST.

Регистрация и продление доменов, Cloudflare и DNS, заказ и управление VPS-серверами и веб-хостингом — из своего кода, на том же аккаунте и балансе, что и бот.

https://api.void.cd/v1 Bearer void_… JSON · UTC · USD строками

Хостинг

виртуальный веб-хостинг с панелью

Хостинг-аккаунт — пользователь нашей панели HestiaCP с лимитами тарифа (сайты, диск, базы, почтовые ящики). Создаётся, пока ты ждёшь ответа: POST /hosting отвечает 201 с аккаунтом в статусе ACTIVE либо падает и возвращает деньги. Домен не обязан быть зарегистрирован у нас: направь его A-запись на ip или nameservers — на nameservers. Домен, купленный в Void, автоматически снимается со страницы парковки. Пароль панели отдаёт только GET /hosting/{id}/credentials.

# 1. тарифы и цены
curl -s "$API/hosting/catalogue" -H "Authorization: Bearer $VOID_KEY"

# 2. заказ (списывает срок, возвращает 201 + аккаунт, уже ACTIVE)
curl -s -X POST "$API/hosting" -H "Authorization: Bearer $VOID_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plan":"web-start","domain":"example.org","period":"MONTH"}'

# 3. адрес панели, логин и пароль
curl -s "$API/hosting/$ID/credentials" -H "Authorization: Bearer $VOID_KEY"
// call() — как в быстром старте
const { plans } = await call("GET", "/hosting/catalogue");
const hosting = await call("POST", "/hosting", { plan: plans[0].code, domain: "example.org", period: "MONTH" });

// направь example.org на hosting.ip (A-запись) или на hosting.nameservers
const { panelUrl, login, password } = await call("GET", `/hosting/${hosting.id}/credentials`);
# call() — как в быстром старте
plans = call("GET", "/hosting/catalogue")["plans"]
hosting = call("POST", "/hosting", plan=plans[0]["code"], domain="example.org", period="MONTH")

# направь example.org на hosting["ip"] (A-запись) или на hosting["nameservers"]
creds = call("GET", f"/hosting/{hosting['id']}/credentials")   # panelUrl, login, password
GET/hosting/catalogue

Тарифы в продаже с ценой каждого срока. available: false — продажи хостинга сейчас выключены, заказ ответит PROVIDER_DISABLED. Тарифы идут в порядке показа; id — то, на что ссылается Hosting.planId.

{ "ok": true, "data": { "available": true, "plans": [
    { "id": "8d2f…", "code": "web-start", "nameEn": "Start", "nameRu": "Старт", "sites": 1, "diskMb": 3072, "bandwidthGb": 0, "databases": 1, "mailboxes": 3,
      "prices": { "MONTH": "10.00", "QUARTER": "29.25", "HALF_YEAR": "57.00", "YEAR": "111.00" } }, … ] } }
GET/hosting?offset=0&limit=20

Твои живые аккаунты (PENDING, ACTIVE, SUSPENDED), новые первыми. Не больше 50 на страницу.

{ "ok": true, "data": { "items": [ Hosting, … ], "total": 1, "offset": 0, "limit": 20 } }
POST/hosting201 · списывает баланс

Списывает срок и создаёт аккаунт в панели с доменом в качестве первого сайта. Считается в лимит 20 / мин.

телотип
planобязательноstringcode тарифа из каталога
domainобязательноstringдомен сайта; один домен может жить только на одном хостинг-аккаунте
periodобязательноMONTH QUARTER HALF_YEAR YEARоплачиваемый срок
{ "plan": "web-start", "domain": "example.org", "period": "YEAR" }
402 INSUFFICIENT_FUNDS409 DOMAIN_UNAVAILABLE уже на хостинг-аккаунте400 DOMAIN_INVALID404 PLAN_NOT_FOUND · 400 PLAN_INACTIVE5xx PROVIDER_ERROR деньги возвращены

Повторный заказ для того же домена после успешного первого вернёт 409 DOMAIN_UNAVAILABLE, так что повтор не купит аккаунт дважды.

GET/hosting/{id}

Один аккаунт — см. Hosting.

GET/hosting/{id}/credentials

Адрес панели, логин и пароль — единственное место, где отдаётся пароль.

{ "ok": true, "data": { "panelUrl": "https://…", "login": "wh3f9a1c", "password": "…" } }
PATCH/hosting/{id}

{ "autoRenew": true | false } — в момент истечения продлить на текущий срок с баланса; если денег не хватает, аккаунт приостанавливается. Только для ACTIVE / SUSPENDED. Возвращает аккаунт.

POST/hosting/{id}/renewсписывает баланс

Сразу списывает periodPrice и продлевает expiresAt на один срок от более поздней из дат: текущего истечения или сейчас. Приостановленный аккаунт становится ACTIVE, пользователь панели разблокируется в течение нескольких минут. Каждый успешный вызов добавляет ещё один срок.

402 INSUFFICIENT_FUNDS400 HOSTING_NOT_ACTIVE
GET/hosting/{id}/term

Все сроки продления с ценой по сегодняшним ставкам; current отмечает текущий срок аккаунта. Та же форма, что у серверов.

{ "ok": true, "data": [ { "period": "MONTH", "price": "10.00", "current": true }, { "period": "QUARTER", "price": "29.25", "current": false }, … ] }
PUT/hosting/{id}/term

{ "period": "YEAR" } — меняет срок продления. Сейчас ничего не списывается, expiresAt не меняется; новый срок и его цена действуют со следующего продления, автоматического или ручного.

POST/hosting/{id}/plan/quote

{ "plan": "web-plus" } — цена перехода на тариф побольше. Принимается только более дорогой тариф (меньший может не вместить то, что уже лежит на аккаунте, — это через поддержку). charge списывается сейчас: разница цены срока пропорционально остатку оплаченного срока; periodPrice — каждое продление после смены.

{ "ok": true, "data": { "hostingId": "c41e…", "planCode": "web-plus", "charge": "4.52", "periodPrice": "22.00", "period": "MONTH" } }
POST/hosting/{id}/planсписывает баланс

{ "plan": "web-plus", "maxCharge": "4.52" } — сразу списывает разницу и тут же переключает пакет в панели; возвращает применённую квоту. Если цена теперь выше maxCharge, ничего не списывается, а вызов отвечает 400 UPGRADE_PRICE_CHANGED с details: { "charge" }. Если панель отказала в смене, деньги возвращаются, а прежний тариф восстанавливается.

400 UPGRADE_PRICE_CHANGED400 VALIDATION_ERROR тариф не больше текущего402 INSUFFICIENT_FUNDS5xx PROVIDER_ERROR деньги возвращены