FiveM Refund Case Lifecycle Using Discord Thread States and Auto-Close Rules
Turn refund requests into a predictable, auditable workflow using Discord thread states, permissions, and auto-close rules.
Refund requests are operational work. If you treat them like ad-hoc DMs, you get inconsistent decisions, missing evidence, and staff burnout. A better approach is to model each refund as a case with clear states, stored in Discord threads (or ticket threads), and governed by auto-close rules. This post outlines a lifecycle you can implement today: how to structure threads, which roles can do what, what evidence to require, and how to close cases automatically without losing accountability.
“Consistency beats speed: a refund process that staff can follow every time protects players, moderators, and the server.”
Model the refund lifecycle as thread states
Start by defining a small set of states that cover 95% of cases. In Discord, you can represent states using forum post tags (best option), thread name prefixes (fallback), or a bot-managed state field stored in a database. If you use a Forum channel like #refund-cases, tags are ideal because they are visible, filterable, and hard to ignore. Keep the state machine simple and enforce transitions with permissions and bot checks.
- NEW (intake created, waiting for required info)
- EVIDENCE (player provided proof; staff validating)
- ON HOLD (waiting for third party: payment processor, dev, or logs)
- APPROVED (refund authorized; pending execution)
- DENIED (decision made; include reason and policy reference)
- CLOSED (thread locked/archived after summary and logging)
Define what “done” means for each state. For example, NEW should always contain the player’s identifiers (license, Discord ID), purchase reference, and a short description. EVIDENCE should always include screenshots or clip links plus server logs references (transaction logs, inventory logs, or admin action logs). APPROVED should include who approved, what will be refunded (amount/item), and who executes it (Finance role, Store Manager, or automated payout).
Set up Discord structure: channels, roles, and permissions
A clean Discord layout prevents cases from leaking into public chat and limits who can change outcomes. Use a dedicated Forum channel (recommended) or a private category with a ticket bot that creates private threads. Either way, make sure the case content is visible to the right staff and hidden from everyone else by default.
- Channel: #refund-cases (Forum) with tags for each state and common reasons (Chargeback, Duplicate Purchase, Non-delivery, Exploit/Abuse)
- Role: Refund Support (can reply, request evidence, apply NEW/EVIDENCE/ON HOLD tags)
- Role: Refund Manager (can move to APPROVED/DENIED, lock threads, post final summaries)
- Role: Finance/Store Manager (can execute refunds in Tebex/Stripe/PayPal or in-game compensation, but cannot change the decision tag)
- Role: Audit/Leadership (read-only access for oversight)
- Bot account (Manage Threads, Manage Messages if needed, Read Message History, Send Messages, View Audit Log if your bot uses it)
Permissions should prevent accidental approvals. In Discord terms, avoid giving broad permissions like Administrator to refund staff. Instead, grant only what the workflow needs: View Channel, Send Messages, Create Public Threads (if applicable), Manage Threads (for managers), and Apply Tags (for forums). If you use private threads, ensure the ticket bot invites the requester and the Refund Support role, and that @everyone cannot view the parent channel.
Practical tip: use a “decision separation” rule
Separate “decision” from “execution.” Let Refund Managers set APPROVED/DENIED, and let Finance execute the refund. This reduces fraud risk and makes internal reviews easier because two roles touch the case at different points.
Intake: standardize evidence and identifiers
Most refund disputes fail because staff cannot tie a Discord user to a FiveM identity and a purchase record. Fix that with an intake template posted by a bot when the thread is created. Require consistent identifiers so you can query server logs and store records without guessing.
- Player opens a refund thread via a /refund command or a “Create Post” form in the Forum.
- Bot posts an intake form and sets state to NEW.
- Player provides: Discord ID, FiveM license identifier (license:xxxxxxxx), in-game name, purchase ID (e.g., Tebex transaction ID), date/time, and reason.
- Bot validates required fields (basic regex checks for license: and transaction formats) and moves the thread to EVIDENCE when complete.
- Refund Support requests missing proof (screenshots, clip links, or a short reproduction description) and references the relevant policy section.
Example: a player claims they bought a vehicle but it never appeared. Your intake should force a timestamp and transaction ID so staff can check Tebex delivery logs and your FiveM server logs (e.g., a resource log line confirming vehicle spawn/grant). If you run a framework like ESX/QBCore, ensure you log item/vehicle grants to a dedicated channel (e.g., #server-logs) via a logging resource or webhook, so staff can link evidence directly in the thread.
Investigation: connect Discord threads to FiveM logs and store records
Once a case is in EVIDENCE, staff should follow the same investigation path every time. The goal is to confirm three things: the purchase is real, delivery happened or failed, and the request complies with policy (time window, usage, chargeback status, abuse flags). Use bots and logging to reduce manual work and keep an audit trail.
- Store logs: confirm transaction status, product SKU, and delivery attempts (Tebex/Stripe/PayPal).
- Server logs: check player identifiers, connection times, and any grant events (inventory/vehicle/money).
- Anti-abuse signals: prior refunds, chargeback history, ban status, and alt accounts (match by license/discord/steam identifiers).
- Staff actions: confirm no admin removed the item/vehicle due to rule violations (look at admin command logs).
- Reproduction: if it’s a technical failure, confirm resource errors around the timestamp (txAdmin console logs or resource error logs).
Discord example: create a private staff-only thread inside the case (or a linked internal thread) for sensitive notes like payment processor details. Keep the main case thread focused on what the player needs to provide and what decision was made. If you use a bot like LD Refund System for intake and state transitions, configure it to post a “case snapshot” message whenever the state changes: who changed it, when, and why.
Practical tip: pin a “policy + evidence checklist” message
Pin one message that links your refund policy and lists required evidence for common scenarios (non-delivery, duplicate purchase, accidental purchase, chargeback). Staff can then respond with a single reference instead of rewriting requirements each time.
Decision and execution: approvals, denials, and player communication
Decision quality improves when you force staff to document the reason in the thread. Require a short decision format: outcome, policy reference, evidence summary, and next steps. Keep it readable and specific. Avoid vague denials like “not eligible.” Instead, state the exact rule and the log evidence you relied on.
Example approval message: “APPROVED — Non-delivery confirmed. Tebex Txn #T12345 shows paid at 18:42 UTC; server grant log has no vehicle grant event for license:abcd. Finance will re-deliver the product within 24 hours. If the vehicle appears later, report it to avoid duplication.” Example denial message: “DENIED — Chargeback filed on Txn #T12345. Policy section 4.2: chargebacks void eligibility and may result in account sanctions. If you believe this is incorrect, provide processor documentation within 7 days.”
Execution should be traceable. If Finance re-delivers an in-game item, require a log reference (command log entry, inventory log line, or webhook confirmation). If Finance processes a payment refund, require the refund transaction reference. Post that reference in the thread or in a staff-only note, depending on sensitivity. If you use LD Refund System or a similar tool, configure it to write a structured log to a #refund-audit channel with case ID, outcome, approver, executor, and timestamps.
Auto-close rules: inactivity timers, reminders, and safe closure
Auto-close rules reduce backlog, but only if you apply them by state. A single “close after X days” rule is too blunt: NEW cases need quick reminders, ON HOLD needs longer windows, and APPROVED needs follow-up until execution is confirmed. Implement timers with your ticket bot, a custom Discord bot, or automation platforms that can read thread tags and timestamps.
- NEW: reminder after 24 hours if required fields are missing; auto-close after 72 hours with a message explaining how to reopen.
- EVIDENCE: reminder after 48 hours if staff requested proof; auto-close after 7 days of no response.
- ON HOLD: reminder every 7 days; auto-close after 30 days unless a manager extends it (tag: ON HOLD-EXT).
- APPROVED: reminder to Finance after 24 hours if no execution note is posted; auto-close 72 hours after execution confirmation.
- DENIED: auto-close after 72 hours; allow one appeal window (e.g., “appeal within 7 days with new evidence”).
When a thread auto-closes, post a final summary first. Include: case ID, outcome, key evidence links, and how to reopen (new thread or a /reopen command). Then lock the thread (or archive it) and ensure it remains searchable for staff. If you operate under txAdmin, consider exporting a weekly refund report (counts by state, average time to close, approval rate) so leadership can spot policy gaps or technical delivery issues.
A safe closure rule: never auto-close if the last message was from staff requesting action from another staff role (e.g., Finance). Instead, the bot should detect the tag APPROVED and require an execution confirmation keyword or button press (e.g., “Executed”) before starting the closure timer. This prevents approved cases from quietly expiring.
Auditability and continuous improvement
Refund workflows fail when you cannot explain decisions later. Build auditability into the lifecycle: every state transition should record who did it, when, and why. Centralize logs in a read-only channel like #refund-audit, and restrict deletion permissions so evidence does not disappear. If you allow staff to delete messages, you lose trust and create disputes you cannot resolve.
Run a monthly review using a small sample of closed cases. Check for: missing identifiers, inconsistent policy references, delayed execution, and repeat technical failures (e.g., delivery webhooks failing after a resource restart). Update your intake template and auto-close timers based on what you learn. Over time, you should see fewer back-and-forth messages, faster resolutions, and fewer escalations—because the process is predictable and evidence-driven.
Need a smarter refund flow?
LD Refund System automates Discord approvals, in-game claims, and audit logging so your staff stay focused on players.