REST API v1 · Разработчикам

API BotGG для разработчиков: ваш Discord-сервер в любых проектах

REST API BotGG позволяет вашему сайту, игровому серверу или бэкенду читать и менять данные BotGG на Discord-сервере: выдавать призы через Банк, синхронизировать опыт из игры, награждать за приглашения или выводить топы на сайте. Создайте ключ в консоли — и достаточно одного HTTPS-запроса.

  • Базовый URL: https://console.botgg.app/api/v1
  • JSON по HTTPS, ключи Authorization: Bearer с правами по разделам
  • Машиночитаемое описание всех эндпоинтов в формате OpenAPI 3.1
  • Бесплатный тариф: 2 ключа, 60 запросов в минуту на ключ
Документация для разработчиков
На этой странице

Обзор

То, что участники делают с BotGG в Discord, — балансы, уровни, приглашения и многое другое — доступно и вашему коду. Каждая часть BotGG — это раздел API со своими эндпоинтами и правами; все они перечислены в справочнике.

  • Базовый URL: https://console.botgg.app/api/v1. Только HTTPS.
  • Запросы и ответы — в JSON (Content-Type: application/json).
  • ID — это сноуфлейки Discord (17–20 цифр); они всегда передаются и возвращаются строками.
  • Каждый ключ привязан к одному серверу и работает только на нём — см. авторизацию.
  • Только «сервер — сервер»: запросы из браузера отклоняются, поэтому ключ никогда не окажется во фронтенде.

Быстрый старт

  1. Откройте консоль, выберите сервер и перейдите в раздел API в боковом меню (нужно право «Управлять сервером»).
  2. Создайте ключ: задайте название (например, «Сайт»), выберите права (scopes) и, при желании, срок действия. Сразу скопируйте ключ — он показывается только один раз.
  3. Сохраните его как секрет на своём сервере, например в переменной окружения BOTGG_API_KEY.
  4. Отправьте первый запрос — например, узнайте баланс участника в Банке (право bank:read).
curl
curl -s https://console.botgg.app/api/v1/guilds/123456789012345678/bank/members/876543210987654321 \
  -H "Authorization: Bearer $BOTGG_API_KEY"
Ответ · 200
{
  "userId": "876543210987654321",
  "balance": 1250,
  "currency": { "name": "Coin", "plural": "Coins", "emoji": "🪙" }
}

Для каждого раздела на сервере должен быть включён соответствующий модуль, иначе его эндпоинты отвечают 409 FEATURE_DISABLED (для Банка — BANK_DISABLED). Все коды ошибок — на странице ошибок.

Справочник API по разделам

Для каждого раздела — своя страница справочника, созданная из того же реестра, на котором работает API: параметры, поля запроса и ответа, права, коды ошибок и готовые примеры на curl, JavaScript и Python:

Все эндпоинты

Все пути указаны относительно https://console.botgg.app/api/v1. {guildId} — ID вашего сервера, {userId} — Discord ID участника. Эндпоинтам с пометкой Чувствительное нужно право, которое действует на участников или открывает данные модерации.

Все эндпоинты REST API v1
ЭндпоинтПравоОписание
GET/guilds/{guildId}guild:readGet the server
GET/guilds/{guildId}/rolesguild:readList roles
GET/guilds/{guildId}/channelsguild:readList channels
GET/guilds/{guildId}/members/{userId}guild:readGet a member
GET/guilds/{guildId}/bank/members/{userId}bank:readGet a member’s balance
GET/guilds/{guildId}/bank/members/{userId}/transactionsbank:readList a member’s transactions
POST/guilds/{guildId}/bank/members/{userId}/transactionsbank:writeAdd to or remove from a member’s balance
GET/guilds/{guildId}/bank/leaderboardbank:readTop balances
GET/guilds/{guildId}/levels/members/{userId}levels:readGet a member’s level
GET/guilds/{guildId}/levels/leaderboardlevels:readXP leaderboard
POST/guilds/{guildId}/levels/members/{userId}/xp-changeslevels:writeAdd, remove or set a member’s XP
GET/guilds/{guildId}/levels/xp-changes/{changeId}levels:writeGet the status of an XP change
GET/guilds/{guildId}/invites/members/{userId}invites:readGet a member’s invites
GET/guilds/{guildId}/invites/leaderboardinvites:readInvites leaderboard
POST/guilds/{guildId}/invites/members/{userId}/bonusinvites:writeAdd or remove bonus invites
GET/guilds/{guildId}/ticketstickets:readList tickets
GET/guilds/{guildId}/tickets/{ticketNo}tickets:readGet a ticket
GET/guilds/{guildId}/tickets/{ticketNo}/transcripttickets:readGet a closed ticket’s transcript
POST/guilds/{guildId}/tickets/{ticketNo}/closetickets:writeClose a ticket
GET/guilds/{guildId}/applications/formsapplications:readList application forms
GET/guilds/{guildId}/applications/submissionsapplications:readList applications
GET/guilds/{guildId}/applications/submissions/{number}applications:readGet an application
POST/guilds/{guildId}/applications/submissions/{number}/decisionapplications:writeAccept or deny an application
GET/guilds/{guildId}/appealsappeals:readList ban appeals
GET/guilds/{guildId}/appeals/{number}appeals:readGet a ban appeal
POST/guilds/{guildId}/appeals/{number}/approveappeals:write ЧувствительноеApprove a ban appeal (unban)
POST/guilds/{guildId}/appeals/{number}/rejectappeals:write ЧувствительноеReject a ban appeal
GET/guilds/{guildId}/moderation/casesmoderation:read ЧувствительноеList moderation cases
GET/guilds/{guildId}/moderation/cases/{number}moderation:read ЧувствительноеGet a moderation case
POST/guilds/{guildId}/moderation/users/{userId}/warnmoderation:write ЧувствительноеWarn a member
POST/guilds/{guildId}/moderation/users/{userId}/timeoutmoderation:write ЧувствительноеTime out a member
POST/guilds/{guildId}/moderation/users/{userId}/untimeoutmoderation:write ЧувствительноеRemove a member’s timeout
POST/guilds/{guildId}/moderation/users/{userId}/kickmoderation:write ЧувствительноеKick a member
POST/guilds/{guildId}/moderation/users/{userId}/banmoderation:write ЧувствительноеBan a user
POST/guilds/{guildId}/moderation/users/{userId}/unbanmoderation:write ЧувствительноеUnban a user
GET/guilds/{guildId}/moderation/actions/{actionId}moderation:write ЧувствительноеGet the result of a moderation action
GET/guilds/{guildId}/shop/storesshop:readList stores
GET/guilds/{guildId}/shop/itemsshop:readList items
GET/guilds/{guildId}/shop/items/{itemId}shop:readGet an item
PATCH/guilds/{guildId}/shop/items/{itemId}shop:write ЧувствительноеRestock or turn an item on/off
GET/guilds/{guildId}/shop/members/{userId}/inventoryshop:readA member’s inventory
GET/guilds/{guildId}/shop/purchasesshop:readList purchases
GET/guilds/{guildId}/shop/purchases/{purchaseId}shop:readGet a purchase
POST/guilds/{guildId}/shop/members/{userId}/purchasesshop:write ЧувствительноеBuy an item for a member
POST/guilds/{guildId}/shop/members/{userId}/grantsshop:write ЧувствительноеGive an item to a member for free
POST/guilds/{guildId}/shop/purchases/{purchaseId}/refundshop:write ЧувствительноеRefund a purchase
GET/guilds/{guildId}/giveawaysgiveaways:readList giveaways
POST/guilds/{guildId}/giveawaysgiveaways:writeStart a giveaway
GET/guilds/{guildId}/giveaways/{giveawayId}giveaways:readGet a giveaway
GET/guilds/{guildId}/giveaways/{giveawayId}/entriesgiveaways:readList a giveaway’s entrants
POST/guilds/{guildId}/giveaways/{giveawayId}/endgiveaways:writeEnd a giveaway now
POST/guilds/{guildId}/giveaways/{giveawayId}/rerollgiveaways:writeReroll winners
GET/guilds/{guildId}/flowsflows:readList flows
GET/guilds/{guildId}/flows/runs/{executionId}flows:readGet a flow run
POST/guilds/{guildId}/flows/{workflowId}/runsflows:run ЧувствительноеRun a flow

То же описание доступно как документ OpenAPI 3.1 — импортируйте его в Postman, Insomnia или генератор клиентов. Актуальная версия (без ключа) — по адресу https://console.botgg.app/api/v1/openapi.json.

Как работает API

Полные примеры

Полный пример изменения баланса: один ключ идемпотентности на операцию, ожидание при 429/503 и обработка INSUFFICIENT_FUNDS. Запускайте его на сервере, а не в браузере.

Node.js · bank.mjs
// Node.js 22+ (built-in fetch). Run it on your server — never in a browser or game client.
const API = 'https://console.botgg.app/api/v1';
const KEY = process.env.BOTGG_API_KEY; // a key with the bank:write scope, kept in a secret
const GUILD_ID = '123456789012345678';

export async function changeBalance(userId, type, amount, reason) {
  // One Idempotency-Key per logical change: every retry below reuses it, so the change happens once.
  const idempotencyKey = crypto.randomUUID();

  for (let attempt = 1; attempt <= 3; attempt++) {
    const res = await fetch(`${API}/guilds/${GUILD_ID}/bank/members/${userId}/transactions`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': idempotencyKey,
      },
      body: JSON.stringify({ type, amount, reason }),
    });
    const data = await res.json();

    if (res.ok) return data; // 201 — or the original response, replayed

    if (res.status === 429 || res.status === 503) {
      const seconds = Number(res.headers.get('Retry-After')) || attempt * 2;
      await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
      continue;
    }
    if (data.error === 'INSUFFICIENT_FUNDS') {
      throw new Error(`Not enough balance: the member has ${data.balance}`);
    }
    throw new Error(`${res.status} ${data.error}: ${data.message}`);
  }
  throw new Error('BotGG API is busy, try again later');
}

const tx = await changeBalance('876543210987654321', 'add', 100, 'Tournament prize');
console.log(`New balance: ${tx.balance}`);
Python · bank.py
# Python 3 + requests. Run it on your server — never ship the key to clients.
import os, time, uuid
import requests

API = "https://console.botgg.app/api/v1"
KEY = os.environ["BOTGG_API_KEY"]  # a key with the bank:write scope
GUILD_ID = "123456789012345678"

def change_balance(user_id, type_, amount, reason=None):
    idempotency_key = str(uuid.uuid4())  # one per logical change, reused on every retry
    for attempt in range(1, 4):
        res = requests.post(
            f"{API}/guilds/{GUILD_ID}/bank/members/{user_id}/transactions",
            headers={"Authorization": f"Bearer {KEY}", "Idempotency-Key": idempotency_key},
            json={"type": type_, "amount": amount, "reason": reason},
            timeout=10,
        )
        data = res.json()
        if res.ok:
            return data  # 201 — or the original response, replayed
        if res.status_code in (429, 503):
            time.sleep(int(res.headers.get("Retry-After", attempt * 2)))
            continue
        raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
    raise RuntimeError("BotGG API is busy, try again later")

print(change_balance("876543210987654321", "add", 100, "Tournament prize")["balance"])

Частые вопросы

API BotGG бесплатный?

Да. Каждый сервер бесплатно получает 2 API-ключа и 60 запросов в минуту на ключ. На Pro — до 10 ключей и 600 запросов в минуту.

Можно ли вызывать API из JavaScript в браузере?

Нет. API принимает только запросы «сервер — сервер»: всё, что приходит с заголовком Origin, отклоняется. Обращайтесь к API со своего бэкенда и передавайте результат на страницу — так ключ останется в секрете.

Как начислять участникам валюту из игры или с сайта?

Создайте ключ с правом bank:write и отправьте POST /guilds/{guildId}/bank/members/{userId}/transactions с телом {"type":"add","amount":100}. Добавьте заголовок Idempotency-Key, чтобы повторы никогда не начисляли дважды.

Есть ли спецификация OpenAPI?

Да. API публикует документ OpenAPI 3.1, созданный из реестра эндпоинтов: актуальная версия — https://console.botgg.app/api/v1/openapi.json, а скачать его можно на любой странице документации. Импортируйте его в Postman, Insomnia или генератор кода.

Что делать, если API-ключ утёк?

Сразу отзовите его в консоли — он мгновенно перестанет работать — и создайте новый. Каждая операция Банка, сделанная ключом, есть в журнале Банка с его названием, так что вы увидите, что он успел сделать.

Готовы прокачать свой сервер?

Добавьте BotGG бесплатно и включайте нужные функции в веб-консоли.