Skip to main content

Tickets

People ask for help, staff pick it up, and a transcript is kept.

Module: tickets — off until a bot owner runs /moduleadmin enable module: Tickets. See Modules.

Setting up a full ticket system, start to finish

This is everything, in order. Skipping a step just means the next one tells you what's missing.

1. Turn the module on

Bot owner only:

/moduleadmin enable module: Tickets guild_id: <your server ID>

2. Pick the category tickets open into

Ticket channels are created inside a Discord category. Make one (e.g. Tickets), then point the bot at it:

/config set key: ticket_category value: #your-category

Without this, opening a ticket fails with "Ticket category not configured."

3. Set the log channel

Every open, close, claim, and transcript gets posted here:

/ticketadmin logs channel: #ticket-logs

4. Decide your ticket types

Out of the box, before you configure anything, four built-in types exist: Support, Appeal, Application, Miscellaneous. If that's enough, skip to step 6. Otherwise, create your own — the moment you create even one custom type, the built-ins stop being offered and only your types are used.

/ticketadmin type create

Opens a form: type key (lowercase, no spaces — e.g. report), display label, short description (shown in the dropdown), an emoji, and an intro message shown when the ticket opens.

Manage types with:

CommandWhat it does
/ticketadmin type createNew type (opens a form)
/ticketadmin type edit <type_key>Edit an existing type (same form, pre-filled)
/ticketadmin type delete <type_key>Delete a type
/ticketadmin type toggle <type_key> <enabled>Hide a type from panels without deleting it
/ticketadmin type reorder <type_key> <position>Change dropdown order (1 = first)
/ticketadmin type listSee every configured type
/ticketadmin type setcategory <type_key> <category>Send this one type's tickets to a different category than the server default
/ticketadmin type clearcategory <type_key>Undo that override

5. Add a form, if you want one (optional)

Up to 5 fields per type. When a type has fields, opening that ticket pops a form instead of creating the channel immediately, and the answers get posted into the ticket.

/ticketadmin form add type_key: report

Opens a form for the form field itself: label, placeholder text, style (short or paragraph), whether it's required, and max length (up to 1000).

CommandWhat it does
/ticketadmin form add <type_key>Add a field (max 5)
/ticketadmin form list <type_key>See the fields, in order
/ticketadmin form remove <type_key> <field_number>Remove by number, from form list

Without this, tickets fall back to your server's global staff_role / admin_role (set with /config set). To be specific per type:

/ticketadmin staffrole set type_key: report role: @Moderators level: handler

Three levels:

LevelCan do
ViewerRead only. No sending, no reactions.
HandlerRead and send.
SeniorRead, send, and manage (this is what the claimer gets automatically).
CommandWhat it does
/ticketadmin staffrole set <type_key> <role> <level>Assign a role
/ticketadmin staffrole remove <type_key> <role>Unassign
/ticketadmin staffrole list <type_key>See assignments for one type

7. Post the panel

The panel is the dropdown people actually click to open a ticket.

/ticket panel post

Opens a form: title, description (markdown works — bold, bullets), which ticket types to include (comma-separated keys, blank = all enabled), accent colour (hex, blank = blue), and an optional image URL. Posts immediately in whatever channel you ran the command in.

Use save instead of post if this is a panel you'll want to bring back later:

/ticket panel save name: general

Same form, but it also remembers the panel under that name. If the panel message ever gets deleted — someone fat-fingers it, the channel gets purged — you don't rebuild it from scratch:

/ticket panel load name: general
CommandWhat it does
/ticket panel postPost a panel, don't save it
/ticket panel save <name>Post a panel and remember it
/ticket panel load <name>Repost a saved panel
/ticket panel listSee saved presets
/ticket panel delete <name>Forget a saved preset

That's a full system: module on, category set, log channel set, types defined, forms attached where you want them, roles assigned, panel live.

Optional: unclaim appeals

If a claimer goes quiet and someone else wants to take the ticket over, other staff can vote to force an unclaim. This needs its own channel:

/config set key: ticket_vote_channel value: #staff-votes

Optionally set who's allowed to vote (falls back to your admin role if unset):

/config set key: ticket_inner_circle_role value: @Inner Circle

The button that starts a vote (⚠️ Appeal) only appears on claimed tickets, to anyone with staff perms other than the current claimer.

Using it, day to day

Opening a ticket

Members click the dropdown on the panel. If the type has a form, it pops up first; otherwise the ticket opens immediately.

Staff can open one on someone's behalf:

/ticket open member: @someone ticket_type: report

Claiming

The 🤝 Claim button on the ticket's control message. Whoever claims gets full control (send, manage messages, manage the channel). Claiming is what tells everyone else it's being handled — there's no other signal.

Only one claimer at a time. 🔓 Unclaim on the control message gives it up (only the claimer can do this themself; anyone else has to go through the appeal vote above).

Working the ticket

CommandWhoWhat it does
/ticket add <member>StaffBring someone in (handler perms)
/ticket remove <member>StaffTake someone out
/ticket coclaim <member> <add|remove>Claimer onlyA second handler, max 2
/ticket note <content> [attachment]StaffA note saved in the transcript and posted to the private staff thread
/ticket rename <name>Claimer (or staff, if unclaimed)Rename the channel
/ticket perms <target> <level>Claimer (or admin)Set a specific user or role to viewer / handler / co-claimer / none
/ticket transcriptAnyone in the ticketGenerate the HTML transcript right now, without closing
/ticket list [status]StaffEvery ticket in the server — open, closed, or all

Every ticket also gets a private staff thread, invisible to the ticket opener, for coordinating without cluttering the ticket itself. Staff in the handling role(s) are added automatically. /ticket note posts there too.

Closing

🔒 Close on the control message. This:

  • Revokes the opener's access to the channel (they can no longer see it)
  • Posts a transcript to the log channel automatically
  • DMs the opener a star rating request (1–5 stars, plus an optional comment, or they can skip it)
  • Leaves 🔓 Reopen, 📄 Transcript, and 🗑️ Delete buttons behind

If the opener never responds to the rating DM within 48 hours, that's logged too, as "no feedback" rather than silently dropped.

It's not working

When you are stuck

"Ticket category not configured."

Run /config set key: ticket_category value: #your-category. See step 2 above.

The panel button does nothing

The panel is older than the last time ticket types changed — its dropdown still references types that no longer exist. Repost it with /ticket panel load if it was saved, or /ticket panel post for a fresh one.

"You can't claim this."

You're not in the handler/senior role for that ticket type (/ticketadmin staffrole list), and you don't hold the server's global staff or admin role either.

The ticket channel didn't open

Usually the bot can't create channels in the configured category — check its permissions there. Second most common: you already have an open ticket of that same type; the bot won't open a second one.

The transcript is empty

Transcripts capture messages the bot could see in that channel. If it was added to the channel late (e.g. via /ticket add), it only has messages from that point on.

"No vote channel configured."

The unclaim appeal needs ticket_vote_channel set — see the optional section above. Without it, there is no way to force an unclaim; the claimer has to do it themselves.