Skip to content
CreateDiscordBot
Menu

How to write a Discord bot spec (with a template)

How to write a Discord bot spec a developer can quote from: the 12 sections to include, a copyable template and a filled-in example for a league check-in bot.

By Adam Peleback. Updated . 13 min read.

On this page
  1. Why a spec saves you money
  2. The 12 sections of a Discord bot spec
  3. Discord limits to check before you write
  4. The template
  5. Example spec: a league check-in bot
  6. What to leave out
  7. Send it, or write it with me

A Discord bot spec is a short document that says what the bot must do, for whom, in which server, with which data and outside systems, and how you will check that it works. It has 12 parts: goal, server context, user stories, commands, events, stored data, integrations, permissions, edge cases, an acceptance checklist, ownership, and budget and deadline.

A good spec lets two developers quote the same bot, and lets you and the one you hire agree on when it's finished. Copy the template below, fill in what you know and write "not sure" where you don't. There is a filled-in example for a league check-in bot after it.

Why a spec saves you money

Disputes on bot projects are often about whether something counts as done, not about code quality. One public review of a custom Discord bot gig on Fiverr, for a three-month project, says the developer "tried to move the project to the next milestone" before the current one was complete. A checklist both sides accepted up front settles that kind of argument quickly.

A spec also gets you comparable quotes. "A league bot with check-ins" can mean a small weekend job or a multi-week system with a database and a Google Sheets sync. Quotes written from the same document can be compared. My Discord bot cost guide shows what drives those numbers.

It also surfaces Discord's limits before they cost you a rebuild.

The 12 sections of a Discord bot spec

1. Goal

One or two sentences on the problem and what changes when the bot exists. Add one or two signs that it's working, such as "referees stop pinging captains by hand" or "no ticket waits longer than 12 hours for a first reply". The goal is what you fall back on when a detail is unclear halfway through the build.

2. Server context

How many members, which channels and roles the bot touches, and what other bots already run there. Say whether the bot serves one server or many: a bot in several servers stores its settings per server, and a bot can't grow past 100 servers until Discord verifies it.

Give the numbers that grow, such as teams per season or tickets per week, because they decide how the bot is built. For Rivals League, the provisioning scripts build the server from the roster: 7 divisions, 18 groups and 154 teams, each with its own role and private voice channel. That is 154 roles and 154 channels before a single staff role or division channel, a real share of Discord's caps of 250 roles and 500 channels. More about that project on the work page.

3. User stories for each role

For each group that touches the bot (members, staff such as moderators or referees, and admins), write what they want to do and why: "As a captain, I want to check in my team with one button, so the referee knows we're ready without me pinging anyone." The "so that" part tells the developer what matters when two designs are possible.

4. Commands

A table with the command, its options, who may use it, what happens, and who sees the reply (only the person who ran it, or the whole channel). Discord allows up to 25 options per command and up to 25 fixed choices per option, so a "pick your game" option with 40 games needs autocomplete instead. The slash commands guide shows how commands work from the member's side.

5. Events and automations

Everything the bot does without a command: when someone joins, on a schedule, when a button is pressed, or when something happens outside Discord. Write each one as "when X happens, the bot does Y, in channel Z", and give scheduled times with a time zone.

This section decides which gateway intents the bot needs. Reacting to member joins needs the Server Members intent, and reading what people write needs the Message Content intent. Both are privileged. As of September 2026, once an app reaches 10,000 unique users across its servers, Discord has to approve them in a review that is repeated every year. Button presses and slash commands don't need either, because each interaction already includes the member's roles and permissions.

6. Data the bot stores

List what the bot keeps, why, for how long and who can see it. Discord's Developer Policy says apps may use API data only as needed for the app's stated function, so "we might want it later" is not a reason to store something.

Discord's own audit log keeps entries for 45 days. If you need to prove who checked in, who closed a ticket or who changed a role months ago, the bot has to keep its own log.

7. Integrations and credentials

For each outside system: what data moves in which direction, how the bot connects (API, webhook, a shared sheet), whose account it runs under and who supplies the key. Put the accounts in your organization's name, not the developer's. If members will pay for anything through the bot, say so here: Discord's Developer Policy has monetization rules, and the developer should check how they apply to your setup.

8. Permissions

Which permissions the bot needs, which roles it assigns, who can run staff and admin commands, and which channels it must stay out of. One rule catches many projects: a bot can only assign roles that sit below its own highest role in the server's role list. The permissions calculator turns a list of permissions into the number the invite link needs.

9. Edge cases

What should happen when things go sideways: a member leaves halfway through a flow, two people press the same button at the same moment, the bot restarts, an outside API is slow or down, daylight saving time changes mid-season. You don't need every answer. Listing them matters, because each one is a decision the developer would otherwise make for you.

10. Acceptance checklist

Statements that are either true or false when you test the bot: "A captain from another team gets a private refusal", not "check-in works well". This is the list you tick off before paying the final invoice, so every must-have feature should appear in it.

11. Hosting and ownership

Who owns the Discord application, the code repository and the hosting account, and who fixes things after launch. My recommendation for any paid build: create the application in a Discord developer team that you own, and add the developer with the Developer role. Discord's docs say that role can reset the bot token and take limited actions such as configuring interaction endpoints, but can't manage the team or take destructive actions. Teams require two-factor authentication, and an app transferred to a team can't be transferred back.

12. Budget and timeline

A budget range, a go-live date and why that date matters (season start, a launch, an event). Say what could ship in a second phase, and list what is out of scope. An explicit out-of-scope list is the cheapest protection against scope arguments.

Discord limits to check before you write

These are the Discord limits that shape a bot's design most directly, from Discord's documentation and support pages as of September 2026.

Limit Value Why it matters in a spec
Roles per server 250 A role per team, per rank or per game adds up fast
Channels per server 500, categories included A text and a voice channel per team halves how many teams fit
Channels per category 50 Big leagues need several categories, or threads instead of channels
Audit log history 45 days Keep your own log if you need older records
Options per slash command 25 Long forms belong in a modal or several steps
Fixed choices per option 25 Longer lists need autocomplete
Slash commands per app 100 global, plus 100 per server Rarely a problem
Time to answer an interaction 3 seconds, or defer and finish within 15 minutes Slow outside APIs need a "thinking" state
Message text 2,000 characters Long standings or rules go in embeds or several messages
Embeds Up to 10 per message, 6,000 characters in total, 25 fields each A 48-team table with one field per team doesn't fit in one embed
Buttons 5 per row, 5 rows per classic message Per-match or per-team buttons may need several messages
Privileged intents Discord review once the app reaches 10,000 users, repeated yearly Member-join and message-reading features depend on it
Servers per app Verification needed to grow past 100 A public bot needs time for verification before launch

The counts matter in practice. For a Swedish online esports league, a bot I co-built with another developer created 138 channels and 123 roles for 131 teams in under half an hour. Counting them in the spec is how you find out whether a design fits in one server. The details are on the work page.

The template

It's plain Markdown: copy it into Notion, GitHub, Google Docs or a text file, delete the hints you don't need and fill in the rest.

discord-bot-spec.md
# Discord bot spec: [bot name]

Version: 1 | Date: YYYY-MM-DD | Contact: [name, Discord username, email]

## 1. Goal
- The problem today:
- What changes when the bot exists:
- How we'll know it works (one or two signs):

## 2. Server context
- Servers the bot runs in: [one / several / public bot]
- Members: [about how many] | Active on a busy day: [about how many]
- Channels the bot uses: [#channel: what for]
- Roles involved: [role: who has it, about how many people]
- Other bots in the server and what they do:
- Numbers that grow (teams per season, tickets per week):

## 3. User stories
Members:
- As a [member type], I want to [action], so that [reason].
Staff:
- As a [moderator / referee / support agent], I want to [action], so that [reason].
Admins:
- As an admin, I want to [action], so that [reason].

## 4. Commands
| Command and options | Who can use it | What happens | Reply visible to |
|---|---|---|---|
| /command option | everyone / role | | only the user / the channel |

## 5. Events and automations
- When [something happens], the bot [does what] in [where].
- Every [day and time, with time zone], the bot [does what].
- When [outside system] sends [event], the bot [does what].

## 6. Data the bot stores
| What | Why it's needed | How long it's kept | Who can see it |
|---|---|---|---|
| | | | |
- Does the bot need to read what members write? [no / yes, because]
- Does it need to know when members join, leave or change roles? [no / yes, because]

## 7. Integrations and credentials
| System | Data in or out | How it connects | Account owner | Who supplies the key |
|---|---|---|---|---|
| | | API / webhook / sheet | | |
- Do members pay for anything through the bot? [no / yes: what and how]

## 8. Permissions
- Permissions the bot needs:
- Roles the bot assigns (its own role must sit above them):
- Who can run staff and admin commands:
- Channels the bot must not touch:

## 9. Edge cases
- A member leaves halfway through a flow:
- Two people press the same button at once:
- The bot restarts (must old buttons keep working?):
- An outside system is slow or down:
- Time zones and daylight saving:
- Limits we may hit as we grow (roles, channels, message length):

## 10. Acceptance checklist
- [ ] [A statement that is true or false when tested]
- [ ] [One line per must-have feature]
- [ ] Setup docs let another developer run the bot from scratch

## 11. Hosting and ownership
- Discord application owned by: [our developer team / our account]
- Code repository owned by:
- Hosting: [who runs it, where, who pays]
- After launch: [who fixes bugs, who updates the bot when Discord changes]

## 12. Budget and timeline
- Budget range:
- Must be live by, and why:
- Phase 1 must include:
- Out of scope for this project:

Example spec: a league check-in bot

This example is made up. The Northwind League, its numbers and its dates are invented to show the level of detail a developer needs; it is not a client project.

Goal

Match nights are Tuesdays and Thursdays at 8:00 PM US Eastern. Referees ping captains by hand to find out who's ready, and matches start late. The bot gives every match a check-in window, reminds captains who haven't checked in, and gives referees one summary at start time. Signs it works: no check-in DMs from referees, and a timestamped record behind every forfeit.

Server context

  • One server, about 1,400 members.
  • 48 teams in 4 divisions of 12, so 24 matches on a full match night. Next season may have 64 teams.
  • Channels: #check-in (the bot posts here), #referee-desk (staff only, the bot posts summaries), #announcements (the bot never posts here).
  • Roles: Admin (3 people), Referee (8), Captain (one or two per team), and 48 team roles that admins create each season. 64 team roles next season still fits under the 250-role cap.

User stories

  • As a captain, I want to check in my team with one button during the 30 minutes before our match, so the referee knows we're ready.
  • As a captain, I want a reminder 10 minutes before start if we haven't checked in, so we don't forfeit by accident.
  • As a referee, I want one list of tonight's matches with their check-in state, so I can start matches on time.
  • As a referee, I want to check a team in by hand with a reason, for when a captain's Discord is down.
  • As an admin, I want to load a night's matches from our schedule sheet and see a preview first, so a sheet mistake doesn't go out.

Commands

Captains check in with a button, not a command.

Command and options Who can use it What happens Reply visible to
/matches Everyone Lists tonight's matches, start times (as Discord timestamps) and check-in state Only the user
/checkin-override match team reason Referee, Admin Marks the team as checked in and records who did it and why Only the user; a line goes to #referee-desk
/schedule-import date Admin Reads that date's matches from the sheet and shows a preview with Confirm and Cancel buttons Only the user
/schedule-cancel match Admin Takes a postponed match out of check-in and marks its message "Postponed" Only the user
/checkin-settings window reminder Admin Sets the window (15 to 60 minutes) and the reminder (5 to 30 minutes before start) Only the user

Events and automations

  • Window opens (default: 30 minutes before start): one message per match in #check-in with both team names, the start time and a Check in button for each team.
  • Button press: only a member with the Captain role and that team's role can check the team in. Anyone else gets a private refusal. The message updates to show who checked in and when.
  • Reminder (default: 10 minutes before start): the bot mentions the captains of teams that haven't checked in, in #check-in.
  • Start time: buttons lock, and #referee-desk gets a summary with checked-in teams (and times) and missing teams. The bot never decides a forfeit; referees do.

Data the bot stores

What Why it's needed How long it's kept Who can see it
Matches: ID, teams, division, start time in UTC To run the windows The season plus 90 days Everyone, through /matches
Check-ins: team, Discord user ID, time, override by, reason The record for forfeit disputes The season plus 90 days, then exported to CSV for admins and deleted Referees and admins
Settings: window, reminder, channel and role IDs Configuration While the bot runs Admins

The bot doesn't read message content and doesn't need member join or leave events; the roles it checks arrive with each button press.

Integrations and credentials

System Data in or out How it connects Account owner Who supplies the key
Google Sheets, "Season schedule" tab In: date, time (US Eastern), division, home team, away team, match ID A Google service account with read-only access to that one sheet The league's Google account A league admin shares the sheet with the service account

Members don't pay for anything through the bot. start.gg results are out of scope for this project.

Permissions

  • The bot needs View Channels, Send Messages, Embed Links and Read Message History in #check-in and #referee-desk, and nothing elsewhere.
  • It assigns no roles.
  • Referee and admin commands check roles in code, and server admins also hide them from other members in the server's command permission settings.

Edge cases

  • A captain from the other team, or a player who isn't a captain, presses a button: private refusal, nothing changes.
  • Both captains of a team press at the same moment: one check-in is recorded, no duplicate messages.
  • The bot restarts during a window: buttons keep working and no check-ins are lost, because the state lives in the database.
  • A match is rescheduled after import: the admin cancels it and imports the new date; the old message says "Postponed".
  • The sheet can't be reached: the import fails with a clear message and nothing changes.
  • US clocks go forward on March 14, 2027, mid-season. Sheet times are US Eastern, and the bot converts each match to UTC using that match's own date.

Acceptance checklist

  • /schedule-import for a test date shows a preview that matches the sheet row by row, and Cancel posts nothing.
  • Check-in messages appear 30 minutes before each start time, within one minute.
  • A captain of the right team can check in; anyone else gets a private refusal.
  • The reminder mentions only captains of teams that haven't checked in.
  • At start time the buttons lock and #referee-desk gets the summary.
  • An override records who made it and why.
  • Restarting the bot during a window loses no check-ins, and the buttons still work.
  • The Tuesday, March 16, 2027 match (first match night after the clock change) opens at 7:30 PM Eastern.
  • With the setup docs, another developer can run the bot on a fresh test server.

Hosting and ownership

  • The Discord application lives in the league's developer team, with the developer as a member with the Developer role. The code lives in the league's GitHub organization.
  • The developer hosts the bot for the first season; the league reviews that before the next one.
  • After launch: 30 days of bug fixes, then a monthly maintenance plan or hourly work.

Budget and timeline

  • Budget: $1,500 to $2,000.
  • Live by Tuesday, January 12, 2027, the first match night of the season. A dry run with referees on a test server the week before.
  • Phase 1: everything above. Phase 2, not in this project: start.gg results and standings.

For scale: with my prices as of September 2026, a bot like this (a database, a handful of commands and one Google Sheets integration) usually lands in the Community tier, from $1,490. The pricing page lists what each tier includes. If your league wants something like it, the esports and league bots page shows what else these bots usually do.

What to leave out

  • The technology, unless you have a reason. "Must run on our existing server" is a requirement; "use Python" usually isn't.
  • Features nobody asked for yet. Put them in the phase 2 list, where they don't raise the price of phase 1.
  • Anything that breaks Discord's rules. I decline selfbots, fake members and bots that copy messages out of servers you don't own, and so should any developer you hire. The Discord Developer Policy also rules out contacting members without their permission, so "DM everyone who joins with our offer" is out too.

Send it, or write it with me

If you've filled in the template, send it with a short brief and I'll reply with questions or a fixed quote.

If you'd rather not write it alone, that is what the Bot Blueprint is for: a 45-minute call about your server and workflows, then a written spec with an acceptance checklist we both sign off on, and a fixed price and delivery date for the build. It costs $249 and is credited in full if you order the build within 30 days. You can book a Blueprint. If you're still choosing who to hire, how to hire a Discord bot developer covers the questions to ask.

Questions

How long should a Discord bot spec be?

Long enough that two developers would build the same thing from it. For a one-system bot that is often one or two pages; a bot with a database, an integration and several roles usually needs three or four. Length matters less than the acceptance checklist, which is the part people skip.

Do I need to know how to code to write a spec?

No. A spec describes what members and staff do and what the bot does in response. The technical choices, such as the library, database and hosting setup, are the developer's job, unless you have a reason to require something specific.

What is the difference between a brief and a spec?

A brief is a paragraph or two about what you want, enough for a developer to say whether it's a fit and give a rough range. A spec is detailed enough to fix a price and a delivery date. The quote form takes a brief; the template on this page is a spec.

What happens if we need something that isn't in the spec?

It becomes a change request: written down, priced and agreed before anyone builds it. Small adjustments can fit in a revision round. With me, larger changes are billed at $90 an hour in prepaid 5-hour blocks, and the pricing page lists what each package includes.

Should the developer or I write the spec?

Either works, as long as both of you agree to it in writing before the build starts. Writing a first draft yourself saves time and money. A developer then fills the gaps you can't know about, such as permissions, intents and Discord's limits.

Sources

Prices and features were checked on September 27, 2026.

  1. Discord Support, Account caps, server caps and more (roles, channels, audit log)
  2. Discord Developer Docs, Permissions (role hierarchy)
  3. Discord Developer Docs, Gateway (privileged intents)
  4. Discord Developer Docs, Getting started with privileged intent review (10,000-user threshold, yearly review)
  5. Discord Developer Support, How do I get my app verified? (required past 100 servers)
  6. Discord Developer Docs, You might not need a privileged intent
  7. Discord Developer Docs, Application commands (options, choices, command limits)
  8. Discord Developer Docs, Receiving and responding to interactions (3 seconds, 15 minutes)
  9. Discord Developer Docs, Message resource (message and embed limits)
  10. Discord Developer Docs, Component reference (buttons per row, components per message)
  11. Discord Developer Docs, Teams (2FA, member roles, transfers)
  12. Discord Developer Policy (effective July 8, 2024)
  13. Fiverr, reviews on a custom Discord bot gig (3-month project review)

Tell me what your server needs

Send a short brief. You get a reply within one business day with questions or a price range, and a fixed quote before any work starts.