Applications, ban appeals and tickets for your Discord server.
Appealy is an open-source Discord bot for staff applications, ban
appeals and tickets, with a web dashboard. Members fill in a form from a panel button or
/apply. Staff review each submission in a queue and pick an outcome. The
role grant, the DM and the unban all happen on that one click.
Appy’s ban message says “this decision is final and cannot be appealed.”
The mark above is an open door, because that is the opposite of that sentence in one shape.
Five things most Discord bots in this category do not do.
These lead because they are the honest differences, not because they test well. Every one
of them is checkable against the repository.
Fully open source
The gateway bot, the API, the dashboard, the Terraform, and the pricing calculator that
decides what you are charged. AGPL-3.0. You can read the code that enforces your caps.
Self-host it for free
No licence key and no feature gate. .env.example ships
DEPLOYMENT_MODE=self: billing is off, the payment credentials are never
read, and caps come from your own CAP_* values on your own hardware.
Every feature at every tier
Paid plans raise nine throughput caps. That is the entire difference. Dropdown panels,
custom outcomes, manager delegation, ban appeals, transcripts — all of it is on the
free tier too.
Complete export, no lock-in
/export writes one JSON file containing every form, question, panel,
submission, ticket, giveaway, config and delegation for your server. Import it into a
self-hosted instance and leave.
No unlimited tier, anywhere
Every cap has a hard ceiling, including the ones you set yourself. An unbounded cap
removes the ability to reason about worst-case cost and makes abuse free to attempt, so
it does not exist here by design.
No telemetry
Asserted as TELEMETRY_ENABLED = false in
shared/config/deployment.ts rather than promised in prose, so it would show
up in a diff if it ever changed.
The whole surface
It is not only an application bot.
Seventeen slash commands, and a dashboard for configuring what they do. Every one of the
subsystems below is available on the free tier.
Applications and forms
Panels with up to 5 form buttons, or a dropdown of up to 25
/apply runs the same code path as a panel button, so gating cannot drift between them
Text and select questions; selects use a two-step flow because a Discord modal holds text inputs only
Applications longer than five questions page across several modals, because five components is Discord’s limit and losing question six is not an acceptable way to respect it
Optional regex validation per question, alongside min and max length
Role gating, cooldowns, and per-user submission limits
DM applications, for people who cannot see the channel yet
Staff review
A review message with the answers, the applicant, and the roles you asked to be pinged
Custom outcomes — “accept as Trainee”, “accept as Moderator” — each with its own roles, message and log channel
A minimum staff level per outcome, and no reviewer may grant a role at or above their own highest
Deny reasons, with a deny-path role grant and removal kept separate from the accept path
Auto-deny when the applicant leaves the server before review, so the queue does not fill with people who are gone
Manager delegation: review and manage access without handing out Administrator
Ban appeals
DM a form the moment someone is banned
Accepting the appeal can unban them automatically
Appeal forms are forced to DM delivery, because a banned member cannot reach a panel or /apply
The settings page names the three ways to switch this on and still have it do nothing
Tickets
Private channel, private thread or public thread — chosen per ticket type, not once for the server
Claim and close buttons, and an optional transcript posted to a channel on close
Optional 1–5 star rating DMed to the opener after the ticket closes
Configurable behaviour when the opener leaves: nothing, close, or notify
Giveaways
Button entry, not reactions
Role gating in the same shape as form gating, plus optional bonus entries per role
Scheduled auto-end
Reroll that excludes anyone who already won
Polls
/poll creates and publishes immediately, using Discord’s own poll by default — real vote buttons, a live countdown and Show results, not an embed imitating one
It asks when to close and you answer in the channel: 1h 20m, 10 hours 50 minutes, july 10 3pm
Name your timezone however you say it — 3pm EST, 3pm UTC+5:30, 3pm india, 3pm tokyo, 3pm Asia/Kolkata — and daylight saving is applied for the date the poll actually closes, not today’s
A spelling that means two places is refused rather than guessed: IST is India, Ireland and Israel, and a poll closing four hours early is worse than a question. Without a timezone the time is read as UTC, and either way it is echoed back in your own before anything is posted
A Discord poll runs in whole hours, so engine: Legacy embed keeps the older embed for an exact close time — and for results you can query in SQL, which Discord’s polls do not expose
The dashboard schedules publish and close for later
Up to 9 options, optional multiselect
Verification and welcome
One-button verification, or a retype-the-code challenge
An optional unverified role applied on join and stripped on verify, with an optional auto-kick timer for members who never finish
Welcomer: join message, join DM, auto-role, and a leave message
Role menus for self-assignable roles
Anti-raid
Join-velocity detection over a threshold and window you set
Alert staff, or restrict joins for as long as the lockdown is active
Never retroactive and never a mass-ban. A false positive on a public invite going viral does more damage than under-reacting to a real raid
Staff utilities
Quick responses: saved replies, organised into categories
Sticky messages: keep one message at the bottom of a busy channel
/reset-cooldown, /forms, /botstats
Data portability
/export — the complete JSON dump, owner-only on purpose so a delegated admin cannot trigger it
/import-appealy — stand the same configuration up in another server; every channel and role reference is re-keyed and anything that cannot be resolved comes back in a report
/import-appy — bring submission history across from Appy
/export_applications — CSV of matching submissions, as a Discord attachment
One rule worth stating on its own. A form that loses its role gating on
import is imported switched off. A staff application whose gate referenced roles that mean
nothing in the new server would otherwise arrive not as broken but as open, and an
open staff application is a worse outcome than a missing one.
Getting running
Three steps.
Add the bot
One invite, nine permissions, every one of them load-bearing: roles for outcome grants,
channels for tickets, ban and kick for appeal unbans and verification timeouts. An
invite missing one produces a feature that silently does nothing.
Build a form, publish a panel
From the dashboard, or from /panel create in the server. Set the questions,
the gating, the roles to grant on each outcome, and the channel staff review in.
Review
Submissions arrive in your review channel and in the dashboard queue. Pick an outcome.
Roles, DMs, log entries and unbans follow from it.
Pricing
You pay for throughput, or for hosting. Never for features.
Two independent, additive axes. A server can sit on free throughput with a dedicated
instance, or on a paid throughput tier on the shared bot, in any combination. There is no
bundle discount and none is planned.
Free
$0
forever, not a trial
100 submissions/day
50 tickets/day
500 giveaway entries/day
5 forms, 5 panels
30 days of history
Tier 1
$60 /year
$5.00/month equivalent, billed once
500 submissions/day
250 tickets/day
2,500 giveaway entries/day
50 forms, 50 panels
365 days of history
Tier 2
$180 /year
$15.00/month equivalent, billed once
2,000 submissions/day
1,000 tickets/day
10,000 giveaway entries/day
100 forms, 100 panels
730 days of history
Custom
per unit
priced live, before checkout
Set each of the nine caps yourself
The dashboard re-prices it as you change each number
Never a “contact us” step
Every field still has a ceiling
Billing is annual only. There is no monthly option, anywhere, by design.
Card processing runs roughly 2.9% + $0.30 per transaction, and that flat 30 cents is
brutal at these amounts: a $5/month tier billed monthly loses about 9% of a year’s
revenue to fees, and the same tier billed as one $60 charge loses about 3%. Monthly
figures on this site are computed from the annual price for comparison. They are never a
billing cadence you can select.
A self-hosted instance is this same bot with the same features. Billing is off, the
payment credentials are never read, and the caps come from your CAP_*
values. Raise them — it is your hardware.
It boots without a merchant account
That used to be the blocker: the payment credentials were unconditionally required, so a
clone of an open-source project crashed on startup asking for a merchant account. It
does not any more.
Anywhere Docker runs
A VPS, a Raspberry Pi, or a laptop. ./setup.sh checks your tools, generates
the secrets you should not be typing by hand, walks you through the Discord portal and
starts the containers. It is safe to re-run.
Answered plainly, including where the answer is a limitation. A FAQ that only lists
things the product is good at is an advertisement wearing a question mark.
What happens when I hit a cap?
The action is refused and the person doing it is told which cap and when it resets.
Nothing is deleted and nothing is silently dropped — a submission that would
exceed the daily cap is never accepted and then discarded, because an applicant who
believes they applied and did not is worse off than one who was told no.
What permissions does the bot need?
Manage Roles for the roles it grants, Manage Channels for tickets, Ban Members only if
you use ban appeals, plus the usual read and send. Discord’s own role hierarchy
still applies: the bot cannot grant a role positioned above its own, and the dashboard
marks those roles in every picker rather than failing at the moment it matters.
Do I lose my data if I stop paying?
No. Dropping to the free tier lowers your caps; it does not delete forms, submissions
or tickets. History retention is the one cap that removes anything, it only ever
removes reviewed submissions past your window, and pending ones are never purged
— that is live work sitting in somebody’s queue.
Can I move to another server, or off the platform?
Both. /export writes one JSON file with everything, and the importer
rebuilds it elsewhere — remapping channels and roles, and reporting anything it
could not. Where a setting cannot be carried safely it fails in the cautious direction
and says so, rather than importing something that looks configured and is not.
Is my application data used to train anything?
No. There is no telemetry and no analytics pipeline; the assertion lives in
shared/config/deployment.ts as a constant rather than in prose here, so a
change to it would appear in a diff. If you would rather not take that on trust, the
self-hosted mode never talks to us at all.
What is not built yet?
Worth saying out loud: there is no mobile app, no localisation beyond English, and no
SLA on the hosted service. Self-hosting has no support contract either — it has
the source, the setup guide and the issue tracker.
Support
Where to get help, and what to expect.
This is a small project rather than a company with a support desk, and it is better to
say so than to imply a response time nobody is on call to meet.
Ask in Discord
The community server is the quickest route for most
questions, and the right one when you are not sure whether what you are seeing is a
bug or a setting. Other people running the same bot are in there too.
Something is broken
Open an issue on
the issue tracker.
Include what you did, what happened, and the server id if it is specific to one
— those three things are the difference between a fix and a conversation.
Is it me, or is it down?
The status page is served independently of the app, so it still
answers when the app does not. Check there first: an outage and a misconfiguration
look identical from inside a Discord server.
Setting it up yourself
SETUP.md
covers the hosted path and
SELF_HOSTING.md
the standalone one, including the environment variables that decide which mode you are
in. Most setup questions are answered in one of those two files.
A security problem
Please do not open a public issue for anything exploitable. Use GitHub’s
private
vulnerability reporting instead, which reaches the maintainer without publishing
the details first.
Billing and payment
Payments are processed by Tebex as merchant of record, so refunds and payment-method
problems go through their support with your order reference. What a plan actually
grants is a different question — that one belongs on the issue tracker, or is
readable directly in pricing.ts.
You were banned from the platform
That has its own route, and it does not run through the issue tracker. Sign in and the
ban screen carries the reason and the form — these are read by a person, they
pause rather than close when attempts run out, and they are never described as final.
There is no paid support tier and no plan for one. Paying for a higher throughput cap does
not buy a faster answer, which would be a strange thing to sell given the whole service is
a set of numbers you can read in the repository.
Add it to a server.
The free tier is a set of caps, not a countdown. Nothing expires, and nothing asks for a
card before it works.