> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/discordplace/discord.place/llms.txt
> Use this file to discover all available pages before exploring further.

# Vote Webhooks

> Receive real-time notifications when users vote for your bot or server.

Instead of polling the [Check Vote Status](/api-reference/bots/check-vote) endpoint, you can configure a webhook URL. discord.place will send an HTTP `POST` to your endpoint within seconds of a vote being cast.

## Setting Up Your Webhook

<Steps>
  <Step title="Open your bot's manage page">
    Go to [discord.place](https://discord.place), navigate to your bot's listing, and click **Manage**.
  </Step>

  <Step title="Open Webhook Settings">
    Select the **Webhook Settings** tab from the manage page navigation.
  </Step>

  <Step title="Enter your webhook URL">
    Provide the publicly accessible URL of your HTTP endpoint. discord.place will `POST` to this URL on every vote.
  </Step>

  <Step title="Set a webhook token (optional)">
    Enter a secret token. This value will be sent in the `Authorization` header of every webhook request, allowing your server to verify the request came from discord.place.

    <Note>Webhook tokens are not supported for Discord Webhook URLs (`discord.com/api/webhooks/...`). For Discord Webhooks you can instead set a **language** field to localize the notification message.</Note>
  </Step>

  <Step title="Save and test">
    Save the settings, then use the **Send Test** button to fire a test payload to your endpoint and confirm it is reachable.
  </Step>
</Steps>

## Webhook Payload

discord.place sends a JSON body with the `Content-Type: application/json` header on every vote.

### Bot Vote

<ParamField body="bot" type="string">
  The snowflake ID of the bot that was voted for. Present on bot vote webhooks.
</ParamField>

<ParamField body="user" type="string" required>
  The snowflake ID of the user who cast the vote.
</ParamField>

<ParamField body="test" type="boolean" required>
  `true` when the payload is a test event triggered from the manage page; `false` for real votes.
</ParamField>

```json theme={null}
{
  "bot": "123456789012345678",
  "user": "987654321098765432",
  "test": false
}
```

### Server Vote

<ParamField body="guild" type="string">
  The snowflake ID of the server that was voted for. Present on server vote webhooks.
</ParamField>

<ParamField body="user" type="string" required>
  The snowflake ID of the user who cast the vote.
</ParamField>

<ParamField body="test" type="boolean" required>
  `true` for test events, `false` for real votes.
</ParamField>

```json theme={null}
{
  "guild": "123456789012345678",
  "user": "987654321098765432",
  "test": false
}
```

### Test Webhook

Test payloads only include `user` and `test: true` — no `bot` or `guild` field is present:

```json theme={null}
{
  "user": "987654321098765432",
  "test": true
}
```

## Verifying Requests

If you configured a webhook token, compare the value of the incoming `Authorization` header against your stored secret before processing the payload:

```javascript theme={null}
if (req.headers['authorization'] !== process.env.WEBHOOK_TOKEN) {
  return res.status(401).send('Unauthorized');
}
```

## Retry Policy

If your endpoint returns a response with a status code **outside the 200–299 range**, discord.place will retry the request up to **3 times** with a **5-second delay** between each attempt. After all retries are exhausted, delivery stops and the event is not queued again.

<Warning>
  Always respond with a `2xx` status code (e.g., `200` or `204`) as quickly as possible. Do any heavy processing asynchronously after sending the response. If your endpoint consistently fails, webhook delivery will be suspended.
</Warning>

## Express.js Handler Example

```javascript theme={null}
import express from 'express';

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

app.post('/webhook/vote', (req, res) => {
  // Verify the request came from discord.place
  const token = req.headers['authorization'];
  if (token !== process.env.WEBHOOK_TOKEN) {
    return res.status(401).send('Unauthorized');
  }

  const { bot, guild, user, test } = req.body;

  // Acknowledge immediately to avoid retries
  res.sendStatus(200);

  // Handle test pings
  if (test) {
    console.log('Test webhook received from discord.place');
    return;
  }

  if (bot) {
    // Handle bot vote — e.g., grant a vote reward role
    console.log(`User ${user} voted for bot ${bot}`);
  } else if (guild) {
    // Handle server vote
    console.log(`User ${user} voted for server ${guild}`);
  }
});

app.listen(3000);
```
