Background
logo
Forge Icon
Options
Developer Resources

Developers

Build & Grow

"DiscordForge is the perfect place to grow your bot's user base. We provide powerful tools and a dedicated community to help you succeed."

Adding a Bot

Adding your bot to DiscordForge is simple and takes less than 2 minutes.

  1. Open the Menu and select Add.
  2. Choose Bot from the submission options.
  3. Fill in your Bot's details (Client ID, Prefix, Description, etc.).
  4. Copy the verification code (e.g., df-verify-xyz) and add it to your bot's About Me section in the Discord Developer Portal (not on DiscordForge or top.gg).
  5. Click Submit. Our system will verify the code automatically.
  6. Once a moderator approves it, your bot will be listed!

Announcements

Keep your users updated directly from your bot's profile page.

  • Visibility: Announcements appear at the top of your bot's profile.
  • Markdown: Full Markdown support including links, lists, and code blocks.
  • One at a time: Each new announcement overwrites the previous one.

Widgets

Show off your bot's status on your website or GitHub README.

Go to your bot's profile, click the Actions menu, and select Widget.

JSON / APIGet raw data for custom implementations.
HTML / MarkdownReady-to-use embed codes.

Management

Need to update your bot's description, prefix, or links?

  • Go to your Dashboard
  • Click Edit on your project card
  • Save changes instantly

Growth Tools

Forge Synergy

Link your bot to a Perfect Match partner project to cross-promote audiences.


API Access

We offer a robust REST API for posting stats and fetching bot data. Use our official SDKs for the best experience.

How to get your API Key
  1. Go to Dashboard → My Bots.
  2. Click on your bot's card to open its details.
  3. Navigate to the API Access tab.
  4. Click Generate or Regenerate.
Example Implementation
await fetch('https://discordforge.org/api/v1/bots/stats', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer YOUR_BOT_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ server_count: 1500, shard_count: 5 })
});
POST /api/v1/bots/stats
1 req / 5 min

Update your bot's server, shard, user, and voice connection counts.

{
  "server_count": 1500,
  "shard_count": 5,
  "user_count": 120000,
  "voice_connections": 12
}
GET /api/bots/:id/votes/check
60 req / min

Check whether a user voted in the last 8 hours.

{
  "hasVoted": true,
  "votedAt": "2026-05-03T08:42:11.000Z",
  "nextVoteAt": "2026-05-03T16:42:11.000Z"
}
GET /api/bots/:id
Public

Fetch a bot's public profile. Accepts the bot's DiscordForge ID or Discord client ID. No auth required.

{
  "id": "...",
  "name": "Forge Bot",
  "prefix": "/",
  "shortDescription": "...",
  "avatar": "...",
  "voteCount": 1240,
  "serverCount": 5300,
  "tags": ["moderation", "utility"],
  "owner": { "id": "...", "name": "..." }
}
POST /api/v1/bots/commands
Up to 200 commands

Sync your bot's slash commands. Accepts both custom and Discord API formats.

{
  "commands": [
    {
      "name": "ban",
      "description": "Ban a user",
      "usage": "/ban <user> [reason]",
      "category": "Moderation"
    }
  ]
}
GET/POST /api/v1/bots/heartbeat
Uptime push

Heartbeat / Push-based Uptime. Ping this endpoint every 5 minutes from your bot to record uptime without needing the DiscordForge bot on your server. Once called for the first time, our system switches your bot to push-based monitoring and stops scanning your Discord guilds.

{
  "success": true,
  "message": "Heartbeat recorded successfully",
  "status": "online",
  "uptimeChecks": 5409,
  "uptimeOnline": 5409
}
GET /api/v1/bump/cooldown
60 req / min

Check whether a user can bump a server and when their cooldown expires. Cooldown duration depends on the user's tier (Free: 2h, Premium: 1h, Forge/Pioneer: 30 min).

{
  "canBump": false,
  "cooldownExpiresAt": "2026-05-05T20:30:00.000Z",
  "tierLabel": "FORGE",
  "cooldownMs": 1800000
}
PATCH /api/v1/bots/listing
20 writes / hour

Approved bots can update their own safe listing fields. Send at least one allowed field: prefix, shortDescription, description, tags, supportServer, website, socials, languages, hasPaidFeatures, paidFeaturesAvailable, webInterface, or installableAsUserApp.

{
  "shortDescription": "Moderation tools with clear review queues.",
  "tags": "moderation, utility",
  "website": "https://example.com",
  "webInterface": true
}

Category, invite and OAuth URLs, identity, ownership, team, approval, verification, ranking, assets, boosts, entitlements, and API keys cannot be changed through this API.

POST /api/v1/bots/announcements
10 posts / hour

Publish a public release update for an approved bot. Content is sanitized Markdown, limited to 4,000 characters.

{
  "title": "v2.4.0: Scheduled reminders",
  "content": "Added recurring reminders and improved /remind.",
  "type": "UPDATE"
}

Migrate to Developer API v1

All v1 routes require Authorization: Bearer YOUR_BOT_API_KEY. The old routes remain compatibility aliases until 14 October 2026, 00:00 UTC, then return 410 Gone with the replacement URL.

Legacy routeUse instead
POST /api/external/bots/commandsPOST /api/v1/bots/commands
GET/POST /api/external/bots/heartbeatGET/POST /api/v1/bots/heartbeat
GET /api/external/bump/cooldownGET /api/v1/bump/cooldown
POST /api/bots/statsPOST /api/v1/bots/stats

Before retirement, legacy responses include Deprecation, Sunset, and Link migration headers. Rotate no key for this migration: your existing bot API key remains valid.


Automatic Bot Status

DiscordForge automatically detects your bot's status if it shares a server with the Forge bot. Forge is a public bot, so you can invite it to any server your bot is already in and uptime checks kick in automatically.

Online
Idle
DND

Why is my bot showing as offline?

It's almost always one of two things:

1

You haven't added Forge to a shared server (most common)

Forge is public and we no longer auto-check every new bot. For uptime to work, the Forge bot needs to be in at least one server your bot is also in.

2

Your bot's presence is set to Offline or Invisible

Some bots set their own presence to invisible in code. When that happens Discord reports them as offline to everyone, including us, even though the process is running fine. Check your bot's presence config and set it to online, idle, or dnd. All three count as online on our end.

Heads up: bots that were on the platform before this change are grandfathered in and still checked the old way. This only affects new submissions.

Still stuck after both? Ping staff with your bot's invite link and we'll take a look.


Vanity URLs

Set a custom vanity URL for your bot or server profile, making it easier to share and remember. Available to FORGE subscribers and PIONEER rank holders.

FORGEPIONEER
https://discordforge.org/bot/your-custom-slug
https://discordforge.org/server/your-custom-slug
  • 3-32 characters, lowercase letters, numbers, and hyphens
  • Must be unique across the platform
  • Configure in Dashboard → Bot or Server Settings

Webhooks

Vote webhooks fire whenever a user upvotes your bot on DiscordForge. Use them to reward voters instantly: grant a Discord role, unlock a premium feature, or DM a custom message. The reward flow is the #1 driver of recurring votes – bots that wire it up see 4x higher repeat votes than bots that don't.

Setup
  1. Go to Dashboard → My Bots → your bot.
  2. Open the Webhooks tab.
  3. Set the Webhook URL to your handler endpoint (HTTPS required).
  4. Create a Secret you control and store it as FORGE_WEBHOOK_SECRET in your bot's env. It is separate from your Bot API key.
  5. Save the webhook settings, then use Test Webhook to verify wiring (sends a payload with isTest: true).

Request

POST YOUR_WEBHOOK_URL

Headers: Authorization: <YOUR_SECRET>Content-Type: application/json

Body:

{
  "id": "123456789012345678",
  "username": "voteruser",
  "weeklyVotes": 42,
  "totalVotes": 150,
  "isTest": false
}
idDiscord user ID of the voter (snowflake string).
usernameDiscord username at the time of the vote.
weeklyVotesvoter's vote count for your bot in the last 7 days.
totalVotesvoter's lifetime vote count for your bot.
isTesttrue only when the dashboard's "Send Test" button fired the request. Skip rewards for test events.

Expected response

Return any 2xx status within 5 seconds. Body content is ignored. A non-2xx response or timeout does not block the vote.

Security

  • Always verify the secret. The Authorization header must equal the secret you copied during setup. Reject anything else with 401.
  • HTTPS only. The dashboard rejects http:// URLs.
  • Rotate the secret if it leaks. Regenerate from the dashboard and update your env. The old secret is invalidated immediately.
  • Treat id as the user identifier. Don't trust username – Discord usernames can change.

Examples

Vote handler
import express from 'express';
import crypto from 'crypto';

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

const FORGE_WEBHOOK_SECRET = process.env.FORGE_WEBHOOK_SECRET;

app.post('/webhooks/forge-vote', (req, res) => {
    // 1. Verify the secret in the Authorization header
    const auth = req.headers.authorization;
    if (auth !== FORGE_WEBHOOK_SECRET) {
        return res.status(401).json({ error: 'Invalid secret' });
    }

    // 2. Parse the payload
    const { id, username, weeklyVotes, totalVotes, isTest } = req.body;

    // Skip test events in production handlers
    if (isTest) {
        console.log('Received test webhook for', username);
        return res.status(200).json({ ok: true });
    }

    // 3. Reward the user (example: grant a Discord role for 12h; role duration is intentionally longer than the 8h vote cooldown)
    grantVoterRole(id);

    // 4. Acknowledge within 5 seconds – non-2xx triggers retries (3 attempts)
    return res.status(200).json({ ok: true });
});

app.listen(3000, () => console.log('Webhook listener on :3000'));

Webhooks v2

Subscribe multiple HTTPS endpoints to signed DiscordForge events. Legacy Webhook remains available and unchanged.

Legacy Webhook

The existing vote-only integration with one URL and secret. Keep it unchanged for compatibility.

Webhooks v2

An opt-in event system with multiple endpoints, per-endpoint subscriptions, signed payloads, test deliveries, and delivery history.

Setup

  1. Open your bot listing and find Webhooks v2.
  2. Add an endpoint name and a public HTTPS URL.
  3. Select one or more events and save the endpoint.
  4. Store the generated endpoint secret securely.
  5. Send a test delivery for a subscribed event before going live.

A bot can have up to three active endpoints. URLs must use HTTPS, contain no credentials, and cannot target localhost or private networks.

Event envelope

Every v2 delivery uses the same envelope. The data object changes with the event type.

JSON
{
  "id": "evt_b19d2b4d5c03427eb3994cd16a7e513b",
  "type": "vote.created",
  "created_at": "2026-08-05T01:49:28.767Z",
  "bot_id": "1503878409934340197",
  "data": {
    "voter_id": "1180554986686525506",
    "streak": 4,
    "total_votes": 100,
    "weekly_votes": 12
  }
}
idStable event identifier. Use it for idempotency.
typeOne of the supported event names.
created_atISO 8601 timestamp in UTC.
bot_idThe bot's public Discord client ID.
dataEvent-specific payload fields.

Request headers

  • Content-Type: application/jsonJSON request body.
  • X-Forge-Signaturesha256=<hex HMAC-SHA256 of the raw request body>.
  • X-Forge-EventThe event type in the envelope.
  • X-Forge-DeliveryThe delivery record identifier.

Verify the signature

  1. Read the raw request body before parsing JSON.
  2. Compute HMAC-SHA256 with the endpoint secret.
  3. Prefix the hexadecimal digest with sha256=.
  4. Compare the result with X-Forge-Signature using a timing-safe comparison.
  5. Parse JSON only after the signature is valid.
Signature verification examples
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const secret = process.env.FORGE_WEBHOOK_SECRET;

app.post('/webhooks/forge', express.raw({ type: 'application/json' }), (req, res) => {
    const rawBody = req.body.toString('utf8');
    const received = req.header('X-Forge-Signature') || '';
    const expected = 'sha256=' + crypto
        .createHmac('sha256', secret)
        .update(rawBody)
        .digest('hex');

    const valid = received.length === expected.length &&
        crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
    if (!valid) return res.status(401).json({ error: 'Invalid signature' });

    const event = JSON.parse(rawBody);
    console.log(event.type, event.id, event.data);
    return res.sendStatus(204);
});

Supported events

EventWhen it firesdata fields
vote.createdFires after a user creates a bot vote.voter_id, streak, total_votes, weekly_votes
review.createdFires when a new bot review is created. Updating an existing review does not emit another event.review_id, reviewer_id, rating, snippet, review_count
milestone.votesFires when a bot reaches a supported vote milestone.threshold, total_votes

Review snippets are limited to 240 characters.

Delivery behavior

  • Source actions do not wait for the receiver network request.
  • Any 2xx response marks the delivery as delivered.
  • The receiver has five seconds to respond.
  • Failed deliveries retry after 1 minute, 5 minutes, and 30 minutes, for four attempts total.
  • Use the event ID or delivery ID to ignore duplicate deliveries.
  • Test deliveries include test: true and source: dashboard and do not change votes or reviews.

Troubleshooting

  • URL rejected: use a public HTTPS endpoint without credentials.
  • Signature mismatch: verify the raw body, endpoint secret, sha256= prefix, and timing-safe comparison.
  • Duplicate event: store handled event or delivery IDs before applying side effects.
  • Repeated 4xx or 5xx responses: inspect delivery history and fix the receiver before retrying.
  • Test event unavailable: subscribe the endpoint to that event first.
Machine-readable API reference

OpenAPI currently documents the public /api/v1 API. This page is the source of truth for outbound Webhooks v2 delivery behavior.

Open public/openapi.json

Vote Notifications

Get real-time Discord notifications whenever someone votes for your bot.

Zero-Code Setup

Vote notifications are sent directly to your Discord server by the Forge bot. No server infrastructure needed. Configure it in Dashboard → Integrations.