Skip to main content

Getting Started

Discord Ticket Bot

A modern, self-hosted Discord ticket bot built on Discord.js v14: SQLite out of the box (no external database required), with optional MySQL/MariaDB and PostgreSQL support. No telemetry, full feature set out of the box.

It is a plain Discord bot: no game server, no FiveM, no ESX or QBCore, no framework. All it needs is Node.js and a bot token.

License: AGPL-3.0 · Node.js 24+ · Discord.js v14 · Docs: docu.msk-scripts.de

Prefer the overview first? The self-hosted Discord ticket bot page on msk-scripts.de walks through the features, the transcript tiers and the verification flow. Auf Deutsch: Discord Ticket Bot zum Selbsthosten.

Still deciding between the options? The comparison of self-hosted Discord ticket bots puts this bot next to Discord Tickets, Sayrix Ticket-Bot and the hosted Ticket Tool, including the cases where another project is the better fit. Auf Deutsch: Ticket Bots im Vergleich.


✨ Features​

FeatureDescription
🎫 Ticket TypesUp to 25 types, each with its own emoji, color, category, staff roles, start priority and questions
📋 QuestionnairesUp to 5 questions in a modal when a ticket is opened. The answers appear in the ticket and in the transcript
🎛️ PanelButton or select menu, optional logo and banner. The /setup panel refreshes itself on every start
🙋 Claim SystemClaim and unclaim per button or command, embed and channel topic update automatically
🔴 PrioritiesLow, Medium, High, Urgent. Predefined per ticket type or set with /priority
🛡️ Type-specific StaffA ticket type with its own staffRoles is handled by those roles only, for channel access and for every staff action
🚧 Open RestrictionsBlocked roles, per-type cantAccess, a blacklist and a per-user open limit that cannot be raced
📝 Staff NotesPrivate notes per ticket with /note
🔀 Move TicketMove a ticket to another type and category, with the matching permissions
🔒 Ticket LockThe creator and added users can no longer write
♻️ Reopen TicketsReopen a closed ticket per button or /reopen, restores access and category
⏰ Auto-CloseCloses inactive tickets after a warning, can be paused per ticket with /autoclose
⏰ Staff ReminderPings the ticket's staff roles when nobody answered within X hours
⭐ Rating System1 to 5 stars with an optional comment, posted with the ticket category and the user's avatar. Staff can reply via the Comment Feedback context menu
📄 HTML TranscriptSelf-contained HTML in a modern or classic design. Avatars, custom emojis and, without an API key, the images are embedded, so the file works offline
🔗 Transcript LinksWith an MSK API key, transcripts are uploaded and shared as a link, optionally under your own domain
💬 Canned ResponsesSnippets with placeholders and autocomplete, defined in snippets.jsonc
📢 BroadcastOne message to every open ticket
🔔 User NotificationsOptional "Notify me" button, the creator gets a DM when staff replies
📊 StatisticsServer-wide and per-user stats with /stats
🎮 Dynamic Bot StatusShows the number of open tickets in the bot status
🌍 Multilingual7 languages included (English, German, French, Spanish, Portuguese, Polish, Hungarian), easily extensible
🗄️ Flexible DatabaseSQLite out of the box, optional MySQL/MariaDB or PostgreSQL via DATABASE_URL, with a migration script
🔄 Update NoticeChecks GitHub releases on start and posts new versions to the log channel
🖥️ Web DashboardOptional browser dashboard: tickets, statistics, config editor, bot control, permissions and an end-user portal. See Web Dashboard
🐳 DockerOfficial images for linux/amd64 and linux/arm64. See Docker

🔗 MSK Transcript Service​

Without an API key nothing leaves your server: the transcript is attached as a self-contained HTML file to the log channel and, if you want, to the close DM. With an API key the bot uploads it to www.msk-scripts.de instead and shares a public link that opens in any browser.

Four tiers are available: Basic (free), Premium (€4.99/mo), Hosted (€9.99/mo) and Business (€19.99/mo), each paid tier also billed yearly with two months free. Paid tiers add larger transcripts and file attachments, longer storage, custom domains and the right to remove the MSK notice. From Hosted on, the bot itself can be hosted on our servers. All paid tiers start with a 14-day free trial that takes no credit card.

To get started, grab your API key at www.msk-scripts.de/ticketbot/verify (sign in with Discord, pick your server) and add it to your .env:

MSK_API_KEY='your_api_key_here'
MSK_API_URL="https://www.msk-scripts.de"

📖 Full walkthrough (tier comparison, API key, custom domain): Service Setup


🖥️ Hosted Bot Management (Hosted & Business)​

Do not want to run a server at all? On Hosted and Business the bot can be hosted by MSK Scripts, and you set it up yourself in the dashboard at msk-scripts.de/ticketbot/dashboard. Enter your bot token, client ID and client secret, press one button, and we install it, start it and check that it came up.

Dashboard, Hosted Bot Management

Your bot then gets its own address, tickets-<id>.msk-scripts.de or a domain of your own, with its own Discord login. That is what lets your whole support team into the bot's dashboard, not just you.

📖 Details: Service Setup → Hosted Bot Management


🖥️ Self-Hosted Web Dashboard​

Running the bot yourself? The optional web dashboard lets you manage tickets, statistics, the configuration and the bot process from your browser, with a permission model for your team. It is disabled by default and safe out of the box.

See the dedicated Web Dashboard page for setup, security and the full permission model.


📁 Project Structure​

discord_ticketbot/
├── index.js # the plain bot (npm start)
├── dashboard.js # supervisor + web dashboard, forks index.js (npm run dashboard)
├── config/ # *.example.jsonc templates; your configs are gitignored
├── locales/ # bot strings: main.json (source), en, de, fr, es, pt, pl, hu
├── assets/ # panel logo and banner
├── data/ # runtime data, SQLite database
├── docs/ # setup, configuration and dashboard guides
├── scripts/ # migrate-db.js, dashboard-setup.js
├── tests/ # node:test suites (npm test)
├── web/ # dashboard UI (React + Vite), web/dist is committed
└── src/
├── client.js # boot flow and staff checks
├── config.js # JSONC parser + validation
├── commands/ # slash commands and the "Comment Feedback" context menu
├── components/ # buttons/, menus/, modals/ (custom ids start with tb_)
├── events/ # ready, interactionCreate, messageCreate, channelDelete
├── handlers/ # loaders for commands, components, events
├── database/ # async DB layer for SQLite, MySQL/MariaDB, PostgreSQL
├── dashboard/ # web server, supervisor, auth, permissions
└── utils/ # ticket lifecycle, transcript, embeds, MSK API client, …

The full layout is in docs/development-en.md on GitHub.


⚙️ Slash Commands​

CommandWhoDescription
/setupAdministratorSend the ticket panel
/close [reason]closeOption.whoCanCloseTicketClose the current ticket
/reopenreopenOption.whoCanReopenReopen a closed ticket, restores access and category
/claim · /unclaimStaffClaim or release the ticket, topic and embed update
/moveStaffMove the ticket to another type
/add <user> · /remove <user>StaffAdd or remove a user
/rename <name>StaffRename the ticket channel
/priority <level>StaffSet low, medium, high or urgent
/note add <text> · /note listStaffPrivate staff notes
/lock lock [reason] · /lock unlockStaffLock or unlock the ticket
/autoclose pause · /autoclose resumeStaffPause or resume auto-close and the staff reminder for this ticket
/transcriptStaffGenerate the HTML transcript now
/snippet send <name> · /snippet listStaffSend or list canned responses
/broadcast <message> [type] [embed]StaffMessage every open ticket
/blacklist add/remove/listManage ServerManage the blacklist
/stats [user]StaffServer-wide or per-user statistics

Staff means the staff roles of the ticket's type, or the global rolesWhoHaveAccessToTheTickets for types without their own. Administrators always count as staff. /setup and /blacklist ship with a default permission that the server admin can widen under Server Settings → Integrations.

Context Menu​

EntryTargetWhoDescription
Comment FeedbackA posted rating (right click → Apps)ratingSystem.commentRoles, otherwise staffAdds a team comment to the rating embed. A second comment by the same person replaces the first

🔘 Ticket Buttons​

ButtonVisible whenDescription
🔒 Close TicketcloseOption.closeButtonClose the ticket, optionally with a reason
🙋 Claim / 🙌 UnclaimclaimOption.claimButtonToggles between the two
🔀 MoveMore than one ticket typeChoose a new type, staff only
🔕 Notify meuserNotifications.enabledThe creator opts in to DM notifications
🗑️ Delete TicketAfter closingDeletes the channel after confirmation
♻️ ReopenAfter closing, reopenOption.buttonReopens the ticket
⭐ 1 to 5Rating request after closingOnly the ticket creator can rate

🗄️ Database Schema​

The database is created automatically. By default this is a local SQLite file (data/tickets.db); set DATABASE_URL to use MySQL/MariaDB or PostgreSQL instead (see Database). The same schema applies to every backend, and missing columns are added automatically on start.

TableContents
ticketsOne row per ticket: status, type, priority, claim, lock, notifications, reminder, auto-close pause, transcript
blacklistBlocked users per server, with reason and timestamp
staff_notesPrivate staff notes per ticket
ratingsOne rating per ticket (1 to 5 ⭐) with optional comment
panel_messagesLocation of the /setup panel message, for the refresh on start
dashboard_accessDashboard permissions per role or user
dashboard_auditAppend-only log of every dashboard change

🌍 Adding a New Language​

Seven languages ship with the bot: English, German, French, Spanish, Portuguese, Polish and Hungarian (locales/en.json, de.json, fr.json, es.json, pt.json, pl.json, hu.json). To use one, set its code in config/config.jsonc ("lang": "fr").

To add another language:

  1. Copy locales/en.json, e.g. as locales/it.json
  2. Translate all strings (including the transcript block)
  3. Set "lang": "it" in config/config.jsonc (and optionally "transcriptLang": "it")

📝 License​

AGPL-3.0-only. Anyone who distributes or hosts a modified version must publish its source under the same license.

One additional term under Section 7(b): the notice identifying the software as MSK Ticket Bot has to stay visible to the people using the bot. Servers with an active Premium or Premium+ subscription are exempt. The exact wording is in the NOTICE file.