REST API v1 · Developers · API reference

Giveaways API reference

All 6 Giveaways endpoints of the BotGG REST API v1: scopes, parameters, fields, errors and ready-to-run curl, JavaScript and Python examples.

Developer docs
On this page

Endpoints

Paths are relative to https://console.botgg.app/api/v1. Send your API key as Authorization: Bearer botgg_…; IDs are strings.

Giveaways endpoints
EndpointScopeDescription
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

Besides its own errors below, every endpoint can return these common ones:

List giveaways

GET/guilds/{guildId}/giveaways

Scope: giveaways:read

status: active, scheduled, ended, cancelled or open (= scheduled + active). Running ones by end time, others newest first.

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
statusquerystringNoOne of scheduled, active, ended, cancelled, open
pagequeryintegerNo1–10,000 · Default 1
limitqueryintegerNo1–100 · Default 25

Response

Response fields · 200
FieldTypeRequiredDescription
itemsarray of objectYes
items[].idintegerYes
items[].statusstringYesOne of scheduled, active, ended, cancelled
items[].prizestringYes
items[].descriptionstring | nullYes
items[].channelIdstringYes
items[].messageUrlstring | nullYesnull until the bot posted it
items[].winnersCountintegerYes
items[].startsAtstringYes
items[].endsAtstringYes
items[].endedAtstring | nullYes
items[].entrantsintegerYes
items[].entriesintegerYesTickets incl. bonus entries
items[].winnerIdsarray of stringYes
items[].hostIdstringYes
items[].requirementsobjectYes
items[].pingRoleIdstring | nullYes
items[].dmWinnersbooleanYes
items[].createdAtstringYes
totalintegerYes
pageintegerYes
nextPageinteger | nullYes
Response · 200
{
  "items": [
    {
      "id": 98765,
      "status": "scheduled",
      "prize": "Nitro",
      "description": "example",
      "channelId": "234567890123456789",
      "messageUrl": "https://example.com",
      "winnersCount": 10,
      "startsAt": "2026-10-07T12:00:00.000Z",
      "endsAt": "2026-10-07T12:00:00.000Z",
      "endedAt": "2026-10-07T12:00:00.000Z",
      "entrants": 42,
      "entries": 10,
      "winnerIds": [
        "234567890123456789"
      ],
      "hostId": "234567890123456789",
      "requirements": {},
      "pingRoleId": "234567890123456789",
      "dmWinners": true,
      "createdAt": "2026-10-07T12:00:00.000Z"
    }
  ],
  "total": 10,
  "page": 10,
  "nextPage": 10
}

Examples

curl
curl -s "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways?page=1&limit=25" \
  -H "Authorization: Bearer $BOTGG_API_KEY"
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways?page=1&limit=25', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os
import requests

res = requests.get(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
    },
    params={
        "page": 1,
        "limit": 25,
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

Start a giveaway

POST/guilds/{guildId}/giveaways

Scope: giveaways:writeIdempotency-Key

Saved as scheduled; the bot posts it in the channel within ~10 s (or at startsAt). Same rules as the console editor. Look and DM setting default to the server’s Giveaways settings.

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
Idempotency-KeyheaderstringNoOptional. Send a unique value (a UUID) and reuse it when you retry: the change happens only once. How it works

Request body

Request body
FieldTypeRequiredDescription
channelIdstringYesDiscord ID (string)
prizestringYes1–200 characters
descriptionstring | nullNoup to 1,000 characters
winnersintegerNoDefault 1
1–50
startsAtstring | nullNoISO 8601; omitted / null = start now
ISO 8601 date-time (UTC)
endsAtstringNoISO 8601; or send durationSeconds
ISO 8601 date-time (UTC)
durationSecondsintegerNoFrom the start; or send endsAt
60–5,184,000
requirementsobjectNoRequired / blocked roles, account and member age, level, entry cost, bonus roles
requirements.roleIdsarray of stringNoup to 20 items · Default []
requirements.roleModestringNoOne of any, all · Default "any"
requirements.blockedRoleIdsarray of stringNoup to 20 items · Default []
requirements.minAccountAgeDaysintegerNo0–3,650 · Default 0
requirements.minMemberDaysintegerNo0–3,650 · Default 0
requirements.minLevelintegerNo0–1,000 · Default 0
requirements.entryCostintegerNo0–1,000,000,000 · Default 0
requirements.bonusRolesarray of objectNoup to 10 items · Default []
requirements.bonusRoles[].roleIdstringYesDiscord ID (string)
requirements.bonusRoles[].entriesintegerYes2–10
embedobjectNoDefault: the server’s Giveaways look
embed.colorstringNoDefault "#D94CFF"
embed.endedColorstringNoDefault "#4E5058"
embed.emojistringNo1–64 characters · Default "🎉"
embed.imageUrlstring | nullNoup to 500 characters · Default null
embed.thumbnailUrlstring | nullNoup to 500 characters · Default null
pingRoleIdstring | nullNoDiscord ID (string)
dmWinnersbooleanNoDefault: the server setting
hostIdstring | nullNoShown as the host; default: the API key’s creator
Discord ID (string)

Response

Response fields · 201
FieldTypeRequiredDescription
idintegerYes
statusstringYesOne of scheduled, active, ended, cancelled
prizestringYes
descriptionstring | nullYes
channelIdstringYes
messageUrlstring | nullYesnull until the bot posted it
winnersCountintegerYes
startsAtstringYes
endsAtstringYes
endedAtstring | nullYes
entrantsintegerYes
entriesintegerYesTickets incl. bonus entries
winnerIdsarray of stringYes
hostIdstringYes
requirementsobjectYes
pingRoleIdstring | nullYes
dmWinnersbooleanYes
createdAtstringYes
Response · 201
{
  "id": 98765,
  "status": "scheduled",
  "prize": "Nitro",
  "description": "example",
  "channelId": "234567890123456789",
  "messageUrl": "https://example.com",
  "winnersCount": 10,
  "startsAt": "2026-10-07T12:00:00.000Z",
  "endsAt": "2026-10-07T12:00:00.000Z",
  "endedAt": "2026-10-07T12:00:00.000Z",
  "entrants": 42,
  "entries": 10,
  "winnerIds": [
    "234567890123456789"
  ],
  "hostId": "234567890123456789",
  "requirements": {},
  "pingRoleId": "234567890123456789",
  "dmWinners": true,
  "createdAt": "2026-10-07T12:00:00.000Z"
}

Examples

curl
curl -s -X POST "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways" \
  -H "Authorization: Bearer $BOTGG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"channelId":"234567890123456789","prize":"Nitro","description":"example","winners":1,"startsAt":"2026-10-07T12:00:00.000Z","endsAt":"2026-10-07T12:00:00.000Z","durationSeconds":3600,"requirements":{"roleIds":[],"roleMode":"any","blockedRoleIds":[],"minAccountAgeDays":0,"minMemberDays":0,"minLevel":0,"entryCost":0,"bonusRoles":[]},"embed":{"color":"#D94CFF","endedColor":"#4E5058","emoji":"🎉","imageUrl":"https://example.com","thumbnailUrl":"https://example.com"},"pingRoleId":"234567890123456789","dmWinners":true,"hostId":"234567890123456789"}'
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(), // reuse it when you retry this request
  },
  body: JSON.stringify({
    channelId: '234567890123456789',
    prize: 'Nitro',
    description: 'example',
    winners: 1,
    startsAt: '2026-10-07T12:00:00.000Z',
    endsAt: '2026-10-07T12:00:00.000Z',
    durationSeconds: 3600,
    requirements: {
      roleIds: [],
      roleMode: 'any',
      blockedRoleIds: [],
      minAccountAgeDays: 0,
      minMemberDays: 0,
      minLevel: 0,
      entryCost: 0,
      bonusRoles: [],
    },
    embed: {
      color: '#D94CFF',
      endedColor: '#4E5058',
      emoji: '🎉',
      imageUrl: 'https://example.com',
      thumbnailUrl: 'https://example.com',
    },
    pingRoleId: '234567890123456789',
    dmWinners: true,
    hostId: '234567890123456789',
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os, uuid
import requests

res = requests.post(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),  # reuse it when you retry this request
    },
    json={
        "channelId": "234567890123456789",
        "prize": "Nitro",
        "description": "example",
        "winners": 1,
        "startsAt": "2026-10-07T12:00:00.000Z",
        "endsAt": "2026-10-07T12:00:00.000Z",
        "durationSeconds": 3600,
        "requirements": {
            "roleIds": [],
            "roleMode": "any",
            "blockedRoleIds": [],
            "minAccountAgeDays": 0,
            "minMemberDays": 0,
            "minLevel": 0,
            "entryCost": 0,
            "bonusRoles": [],
        },
        "embed": {
            "color": "#D94CFF",
            "endedColor": "#4E5058",
            "emoji": "🎉",
            "imageUrl": "https://example.com",
            "thumbnailUrl": "https://example.com",
        },
        "pingRoleId": "234567890123456789",
        "dmWinners": True,
        "hostId": "234567890123456789",
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

Get a giveaway

GET/guilds/{guildId}/giveaways/{giveawayId}

Scope: giveaways:read

With entry counts, winners per draw and the latest queued actions (to follow an end / reroll).

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
giveawayIdpathstringYes

Response

Response fields · 200
FieldTypeRequiredDescription
idintegerYes
statusstringYesOne of scheduled, active, ended, cancelled
prizestringYes
descriptionstring | nullYes
channelIdstringYes
messageUrlstring | nullYesnull until the bot posted it
winnersCountintegerYes
startsAtstringYes
endsAtstringYes
endedAtstring | nullYes
entrantsintegerYes
entriesintegerYesTickets incl. bonus entries
winnerIdsarray of stringYes
hostIdstringYes
requirementsobjectYes
pingRoleIdstring | nullYes
dmWinnersbooleanYes
createdAtstringYes
winnersarray of objectYes
winners[].userIdstringYes
winners[].drawintegerYes0 = the end draw, 1.. = rerolls
winners[].drawnAtstringYes
actionsarray of objectYesThe latest queued actions (end / reroll / …), newest first
actions[].idintegerYes
actions[].actionstringYes
actions[].statusstringYesOne of pending, processing, done, failed
actions[].errorstring | nullYes
actions[].createdAtstringYes
actions[].processedAtstring | nullYes
Response · 200
{
  "id": 98765,
  "status": "scheduled",
  "prize": "Nitro",
  "description": "example",
  "channelId": "234567890123456789",
  "messageUrl": "https://example.com",
  "winnersCount": 10,
  "startsAt": "2026-10-07T12:00:00.000Z",
  "endsAt": "2026-10-07T12:00:00.000Z",
  "endedAt": "2026-10-07T12:00:00.000Z",
  "entrants": 42,
  "entries": 10,
  "winnerIds": [
    "234567890123456789"
  ],
  "hostId": "234567890123456789",
  "requirements": {},
  "pingRoleId": "234567890123456789",
  "dmWinners": true,
  "createdAt": "2026-10-07T12:00:00.000Z",
  "winners": [
    {
      "userId": "876543210987654321",
      "draw": 10,
      "drawnAt": "2026-10-07T12:00:00.000Z"
    }
  ],
  "actions": [
    {
      "id": 98765,
      "action": "example",
      "status": "pending",
      "error": "example",
      "createdAt": "2026-10-07T12:00:00.000Z",
      "processedAt": "2026-10-07T12:00:00.000Z"
    }
  ]
}

Examples

curl
curl -s "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789" \
  -H "Authorization: Bearer $BOTGG_API_KEY"
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os
import requests

res = requests.get(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

List a giveaway’s entrants

GET/guilds/{guildId}/giveaways/{giveawayId}/entries

Scope: giveaways:read

Ordered by user id. Pass after=<nextCursor> for the next page. weight = tickets (bonus roles), paid = entry cost paid.

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
giveawayIdpathstringYes
limitqueryintegerNo1–100 · Default 50
afterquerystringNoDiscord ID (string)

Response

Response fields · 200
FieldTypeRequiredDescription
itemsarray of objectYes
items[].userIdstringYes
items[].weightintegerYes
items[].paidintegerYes
items[].enteredAtstringYes
nextCursorstring | nullYes
Response · 200
{
  "items": [
    {
      "userId": "876543210987654321",
      "weight": 10,
      "paid": 10,
      "enteredAt": "2026-10-07T12:00:00.000Z"
    }
  ],
  "nextCursor": "98700"
}

Examples

curl
curl -s "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/entries?limit=50" \
  -H "Authorization: Bearer $BOTGG_API_KEY"
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/entries?limit=50', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os
import requests

res = requests.get(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/entries",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
    },
    params={
        "limit": 50,
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

End a giveaway now

POST/guilds/{guildId}/giveaways/{giveawayId}/end

Scope: giveaways:writeIdempotency-Key

Queued for the bot, which draws the winners and announces them within ~5 s (202). Follow it with GET …/giveaways/{giveawayId}.

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
giveawayIdpathstringYes
Idempotency-KeyheaderstringNoOptional. Send a unique value (a UUID) and reuse it when you retry: the change happens only once. How it works

Response

Response fields · 202
FieldTypeRequiredDescription
giveawayIdintegerYes
actionobjectYes
action.idintegerYes
action.actionstringYes
action.statusstringYesOne of pending, processing, done, failed
action.errorstring | nullYes
action.createdAtstringYes
action.processedAtstring | nullYes
Response · 202
{
  "giveawayId": 98765,
  "action": {
    "id": 98765,
    "action": "example",
    "status": "pending",
    "error": "example",
    "createdAt": "2026-10-07T12:00:00.000Z",
    "processedAt": "2026-10-07T12:00:00.000Z"
  }
}

Examples

curl
curl -s -X POST "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/end" \
  -H "Authorization: Bearer $BOTGG_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/end', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
    'Idempotency-Key': crypto.randomUUID(), // reuse it when you retry this request
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os, uuid
import requests

res = requests.post(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/end",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),  # reuse it when you retry this request
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

Reroll winners

POST/guilds/{guildId}/giveaways/{giveawayId}/reroll

Scope: giveaways:writeIdempotency-Key

For an ended giveaway: the bot draws count new winners (never someone who already won) within ~5 s (202).

Needs this feature enabled on the server: Giveaways

Parameters
NameInTypeRequiredDescription
guildIdpathstringYesYour server’s ID · Discord ID (string)
giveawayIdpathstringYes
Idempotency-KeyheaderstringNoOptional. Send a unique value (a UUID) and reuse it when you retry: the change happens only once. How it works

Request body

Request body
FieldTypeRequiredDescription
countintegerNoDefault 1
1–20

Response

Response fields · 202
FieldTypeRequiredDescription
giveawayIdintegerYes
actionobjectYes
action.idintegerYes
action.actionstringYes
action.statusstringYesOne of pending, processing, done, failed
action.errorstring | nullYes
action.createdAtstringYes
action.processedAtstring | nullYes
Response · 202
{
  "giveawayId": 98765,
  "action": {
    "id": 98765,
    "action": "example",
    "status": "pending",
    "error": "example",
    "createdAt": "2026-10-07T12:00:00.000Z",
    "processedAt": "2026-10-07T12:00:00.000Z"
  }
}

Examples

curl
curl -s -X POST "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/reroll" \
  -H "Authorization: Bearer $BOTGG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"count":12}'
JavaScript (fetch)
// Node.js 18+ (built-in fetch) — on your server, never in a browser
const res = await fetch('https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/reroll', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BOTGG_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(), // reuse it when you retry this request
  },
  body: JSON.stringify({
    count: 12,
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}: ${data.message}`);
console.log(data);
Python (requests)
import os, uuid
import requests

res = requests.post(
    "https://console.botgg.app/api/v1/guilds/123456789012345678/giveaways/234567890123456789/reroll",
    headers={
        "Authorization": f"Bearer {os.environ['BOTGG_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),  # reuse it when you retry this request
    },
    json={
        "count": 12,
    },
    timeout=10,
)
data = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {data['error']}: {data['message']}")
print(data)

Errors

Ready to level up your server?

Add BotGG for free, then switch features on in the web console.