# End (/api/events/giveaways/end)



## Event Type [#event-type]

```ts
"giveaway.end"
```

## Description [#description]

This event is triggered once a giveaway has ended and the winners have been announced. It is sent after the giveaway is committed as ended, so it is never sent twice for the same giveaway, and never for an end that failed and will be retried.

This is the only event that carries the full participant list.

## Payload Structure [#payload-structure]

<TypeTable
  type="{
  giveawayId: {
    description: 'Unique identifier for the giveaway',
    type: 'string',
  },
  prize: {
    description: 'The prize as it is written on the giveaway message',
    type: 'string',
  },
  channelId: {
    description: 'Discord channel the giveaway was posted in',
    type: 'string',
  },
  messageId: {
    description: 'Discord message ID of the giveaway message',
    type: 'string',
  },
  messageUrl: {
    description: 'Direct link to the giveaway message',
    type: 'string',
  },
  winnersCount: {
    description: 'How many winners the giveaway was configured to draw',
    type: 'number',
  },
  creatorId: {
    description: 'Discord user ID of who created the giveaway',
    type: 'string',
  },
  hostedBy: {
    description: 'Discord user ID of the host',
    type: 'string',
  },
  endedAt: {
    description: 'ISO 8601 timestamp when the giveaway ended',
    type: 'string',
  },
  winners: {
    description: 'Discord user IDs of the winners that were drawn',
    type: 'string[]',
  },
  participants: {
    description: 'Discord user IDs of everyone who entered, winners included',
    type: 'string[]',
  },
  participantsCount: {
    description: 'How many members entered, the length of participants',
    type: 'number',
  },
}"
/>

<Callout type="warn">
  `winners` can be shorter than `winnersCount`, or empty, when fewer members entered than there were prizes to hand out. `participants` is a full list, so a giveaway with thousands of entries produces a large payload. Make sure your endpoint accepts it.
</Callout>

## Example Payload [#example-payload]

```json
{
  "type": "giveaway.end",
  "payload": {
    "giveawayId": "hT7pLm2Qa9",
    "prize": "Nitro Classic",
    "channelId": "1140972530400776294",
    "messageId": "1141002938471829504",
    "messageUrl": "https://discord.com/channels/1140972530400776290/1140972530400776294/1141002938471829504",
    "winnersCount": 2,
    "creatorId": "280158289667555328",
    "hostedBy": "280158289667555328",
    "endedAt": "2024-01-19T15:30:00.000Z",
    "winners": ["713115896805064856", "280158289667555328"],
    "participants": [
      "713115896805064856",
      "280158289667555328",
      "1140972530400776299"
    ],
    "participantsCount": 3
  }
}
```

## Example Usage [#example-usage]

```ts
app.post('/webhook', (req, res) => {
  const { type, payload } = req.body;

  if (type === 'giveaway.end') {
    console.log(`Giveaway ended: ${payload.prize}`);
    console.log(`Winners: ${payload.winners.join(', ')}`);

    // Hand out the prize in your own system
    for (const userId of payload.winners) {
      await grantReward(userId, payload.prize);
    }

    // Keep the entry list for your own records
    await storeParticipants(payload.giveawayId, payload.participants);
  }

  res.status(200).send('OK');
});
```

## Use Cases [#use-cases]

* Hand out a reward automatically to every winner
* Store the full entry list for auditing or for a public results page
* Post the result to another platform
* Measure how many members a giveaway actually reached
