FOXITY
СерверыБотыПартнеры
FOXITY

Каталог дискорд серверов, дискорд ботов и партнёрских проектов

Designed by Fox DesignerDesigned by Fox Designer

Навигация

СерверыБотыПартнёрыКабинетДокументацияПоддержка

Документы

Файлы CookieУсловия использованияКонфиденциальностьПравила мониторингаСервер поддержкиРазработчики

©2026 Foxity. Все права защищены.

Мы не аффилированы с Discord Inc.

API интеграция

Актуальный Foxity API для автоматического обновления статистики ботов и серверов.

Базовый адрес

Используйте https://foxity.foxbot.su/api.

Статистика бота

POSThttps://foxity.foxbot.su/api/bots/:discord_bot_id/stats/ingest/

Headers

Authorization: BotStats YOUR_STATS_TOKEN
Content-Type: application/json

Body

ПолеТипОбязательноОписание
guilds_countintegerДаКоличество серверов, где находится бот.
users_countintegerДаСуммарное количество участников на серверах бота.
online_members_countintegerНетОнлайн-участники, если библиотека может получить presence данные.
shards_countintegerНетКоличество шардов. По умолчанию: 1.

Примеры библиотек

JS helper
// foxity-stats.js
const API_URL = 'https://foxity.foxbot.su/api';

async function sendFoxityStats({
  botId,
  statsToken,
  guildsCount,
  usersCount,
  onlineMembersCount = 0,
  shardsCount = 1
}) {
  const response = await fetch(`${API_URL}/bots/${botId}/stats/ingest/`, {
    method: 'POST',
    headers: {
      'Authorization': `BotStats ${statsToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      guilds_count: guildsCount,
      users_count: usersCount,
      online_members_count: onlineMembersCount,
      shards_count: shardsCount
    })
  });

  if (!response.ok) {
    throw new Error(`Foxity API error ${response.status}: ${await response.text()}`);
  }

  return response.json();
}

module.exports = { sendFoxityStats };
Node.js (discord.js)
// discord.js v14 + Node.js 18+
const API_URL = 'https://foxity.foxbot.su/api';
const STATS_TOKEN = process.env.FOXITY_STATS_TOKEN;

async function postStats(client) {
  const guildCounts = client.shard
    ? await client.shard.fetchClientValues('guilds.cache.size')
    : [client.guilds.cache.size];

  const memberCounts = client.shard
    ? await client.shard.broadcastEval((c) =>
        c.guilds.cache.reduce((total, guild) => total + (guild.memberCount ?? 0), 0)
      )
    : [client.guilds.cache.reduce((total, guild) => total + (guild.memberCount ?? 0), 0)];

  const payload = {
    guilds_count: guildCounts.reduce((total, value) => total + Number(value || 0), 0),
    users_count: memberCounts.reduce((total, value) => total + Number(value || 0), 0),
    shards_count: client.shard?.count ?? 1
  };

  const response = await fetch(`${API_URL}/bots/${client.user.id}/stats/ingest/`, {
    method: 'POST',
    headers: {
      'Authorization': `BotStats ${STATS_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    throw new Error(`Foxity API error ${response.status}: ${await response.text()}`);
  }
}

client.once('ready', () => {
  void postStats(client);
  setInterval(() => void postStats(client), 30 * 60 * 1000);
});
Python (discord.py)
# discord.py
import aiohttp

API_URL = "https://foxity.foxbot.su/api"
STATS_TOKEN = "YOUR_STATS_TOKEN"

async def post_stats(bot):
    payload = {
        "guilds_count": len(bot.guilds),
        "users_count": sum(guild.member_count or 0 for guild in bot.guilds),
        "shards_count": bot.shard_count or 1,
    }
    headers = {
        "Authorization": f"BotStats {STATS_TOKEN}",
        "Content-Type": "application/json",
    }

    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{API_URL}/bots/{bot.user.id}/stats/ingest/",
            json=payload,
            headers=headers,
        ) as response:
            if response.status >= 400:
                raise RuntimeError(await response.text())
Python (disnake)
# disnake
import aiohttp

API_URL = "https://foxity.foxbot.su/api"
STATS_TOKEN = "YOUR_STATS_TOKEN"

async def post_stats(bot):
    payload = {
        "guilds_count": len(bot.guilds),
        "users_count": sum(guild.member_count or 0 for guild in bot.guilds),
        "shards_count": bot.shard_count or 1,
    }
    headers = {
        "Authorization": f"BotStats {STATS_TOKEN}",
        "X-Bot-Stats-Token": STATS_TOKEN,
        "Content-Type": "application/json",
    }

    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{API_URL}/bots/{bot.user.id}/stats/ingest/",
            json=payload,
            headers=headers,
        ) as response:
            if response.status >= 400:
                raise RuntimeError(await response.text())
cURL: bot stats
curl -X POST https://foxity.foxbot.su/api/bots/YOUR_BOT_ID/stats/ingest/ \
  -H "Authorization: BotStats YOUR_STATS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "guilds_count": 1500,
    "users_count": 120000,
    "online_members_count": 42000,
    "shards_count": 2
  }'

Награды за UP

UP-события можно встроить в вашего собственного дискорд бота или backend через обычный HTTP webhook. Это удобно для выдачи валюты, ролей, кейсов, опыта и любых других наград после апа сервера или бота.

В настройках карточки проекта укажите Webhook URL для UP и, при желании, Webhook secret. После каждого UP Foxity отправит POST на ваш URL.

Что приходит в запросе

  • X-Foxity-Event: listing_voted
  • Content-Type: application/json
  • X-Foxity-Webhook-Secret только если вы задали secret в панели
  • В теле запроса: проект, автор апа, количество начисленных UP и итоговые показатели проекта
Payload webhook
{
  "event": "listing_voted",
  "source": "site",
  "project": {
    "type": "server",
    "id": 17,
    "discord_id": "123456789012345678",
    "name": "Foxity Lounge",
    "owner_name": "Лис Дизайнер",
    "owner_discord_id": "805400045159579668",
    "votes_count": 91,
    "score": 91,
    "active_boost_multiplier": 3
  },
  "voter": {
    "user_id": 42,
    "discord_id": "998877665544332211",
    "name": "Maxspeaker",
    "avatar_url": "https://cdn.discordapp.com/avatars/..."
  },
  "vote": {
    "id": 8841,
    "awarded": 3,
    "boost_multiplier": 3,
    "created_at": "2026-05-08T15:04:05+00:00"
  }
}
Node.js пример награды
import express from "express";

const app = express();
app.use(express.json());

app.post("/foxity/up-webhook", async (req, res) => {
  const secret = req.header("X-Foxity-Webhook-Secret");
  if (secret !== process.env.FOXITY_UP_SECRET) {
    return res.sendStatus(403);
  }

  if (req.header("X-Foxity-Event") !== "listing_voted") {
    return res.sendStatus(204);
  }

  const payload = req.body;
  const discordId = payload?.voter?.discord_id;
  const reward = Number(payload?.vote?.awarded || 1) * 100;

  if (!discordId) {
    return res.sendStatus(400);
  }

  await economy.addCoins(discordId, reward);
  await rewardBot.sendMessage(discordId, `Вы получили ${reward} монет за UP проекта!`);

  return res.sendStatus(204);
});

app.listen(3000);
Python пример награды
from fastapi import FastAPI, Header, HTTPException, Request, Response
import os

app = FastAPI()

FOXITY_UP_SECRET = os.getenv("FOXITY_UP_SECRET")


@app.post("/foxity/up-webhook")
async def foxity_up_webhook(
    request: Request,
    x_foxity_event: str | None = Header(default=None),
    x_foxity_webhook_secret: str | None = Header(default=None),
):
    if FOXITY_UP_SECRET and x_foxity_webhook_secret != FOXITY_UP_SECRET:
        raise HTTPException(status_code=403)

    if x_foxity_event != "listing_voted":
        return Response(status_code=204)

    payload = await request.json()
    discord_id = payload.get("voter", {}).get("discord_id")
    reward = int(payload.get("vote", {}).get("awarded", 1)) * 100

    if not discord_id:
        raise HTTPException(status_code=400, detail="Missing voter.discord_id")

    await economy.add_coins(discord_id, reward)
    await reward_bot.send_message(discord_id, f"Вы получили {reward} монет за UP проекта!")

    return Response(status_code=204)

Логика дальше уже ваша: можно начислять игровую валюту, открывать временные роли, выдавать бонусы за бустовый UP-множитель или писать в свою экономику историю наград по voter.discord_id.