HomeDocsQuick start

Quick start

Get VYREX running on Vercel with Discord integration in under 10 minutes.

  1. Fork or clone the repository to your GitHub account.
  2. Import to Vercel — go to vercel.com/new, choose your repo, and deploy.
  3. Add environment variables in Vercel → Project → Settings → Environment Variables. At minimum: DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN, VYREX_OWNER_DISCORD_ID.
  4. Set up Upstash Redis — create a free database at upstash.com and add UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.
  5. Add OAuth redirect — in the Discord Developer Portal, under your app → OAuth2 → Redirects, add https://your-domain.vercel.app/oauth-callback.
  6. Redeploy so new env vars take effect. Then open /dashboard and click Sync from Discord.
Tip: Check /status to verify all services are configured correctly before inviting users.
HomeDocsDeployment

Deployment

VYREX is designed for Vercel but runs anywhere Node.js serverless functions are supported.

Vercel (recommended)

The root vercel.json handles all routing. Static files are served from the root directory; API functions live in api/.

vercel.json — key rewrites
{
  "rewrites": [
    { "source": "/dashboard", "destination": "/dashboard.html" },
    { "source": "/api/discord-token", "destination": "/api/oauth?__op=discord-token" },
    { "source": "/api/bot-config", "destination": "/api/bot-config" }
  ]
}
Important: After adding or changing environment variables on Vercel, you must redeploy for them to take effect. Go to Deployments → ⋯ → Redeploy.

Self-hosted / other providers

Run npm install then serve static files with any web server and set up serverless functions using the provider's Node.js runtime. Ensure all /api/* paths route to the corresponding api/*.js files.

HomeDocsEnvironment variables

Environment variables

All configuration is done through environment variables. Never commit secrets to your repository.

Discord (required)

VariableRequiredDescription
DISCORD_CLIENT_IDRequiredYour Discord application's client / application ID
DISCORD_CLIENT_SECRETRequiredOAuth2 client secret for token exchange
DISCORD_BOT_TOKENRequiredBot token from Discord Developer Portal → Bot → Token
DISCORD_APPLICATION_IDOptionalSame as DISCORD_CLIENT_ID — used as fallback

Access control

VariableRequiredDescription
VYREX_OWNER_DISCORD_IDRequiredFounder Discord user ID — full platform access
VYREX_COOWNER_DISCORD_IDSOptionalComma-separated Owner-tier Discord IDs
VYREX_STAFF_DISCORD_IDSOptionalComma-separated Staff-tier Discord IDs
VYREX_DASH_API_KEYOptionalLong random string for API key auth (no OAuth needed)

Storage

VariableRequiredDescription
UPSTASH_REDIS_REST_URLRecommendedUpstash Redis REST endpoint URL
UPSTASH_REDIS_REST_TOKENRecommendedUpstash Redis REST token
VYREX_ALLOW_MEMORY_FALLBACKOptionalSet to true to allow in-memory fallback when Redis is unavailable
Note: Without Redis, sessions are stored in-memory and lost on function restart. For production, always configure Upstash Redis.
HomeDocsBot setup

Bot setup

Configure your Discord application and bot token for full dashboard integration.

Creating your Discord application

  1. Go to discord.com/developers/applications and click New Application.
  2. Under Bot, click Add Bot. Copy the token and add it as DISCORD_BOT_TOKEN on Vercel.
  3. Under OAuth2 → General, copy the Client ID and Client Secret. Add them as DISCORD_CLIENT_ID and DISCORD_CLIENT_SECRET.
  4. Under OAuth2 → Redirects, add your deployment URL: https://your-domain.vercel.app/oauth-callback.
  5. Enable Presence Intent, Server Members Intent, and Message Content Intent under Bot → Privileged Gateway Intents.

Inviting the bot

Use the Add to Discord button on the homepage, or generate the invite URL manually:

https://discord.com/api/oauth2/authorize
  ?client_id=YOUR_CLIENT_ID
  &permissions=8
  &scope=bot%20applications.commands
HomeDocsBot branding

Bot branding

Customise your bot's avatar, status, activity, and per-server nicknames from the dashboard.

How it reaches the bot: the bot polls /api/bot-config every five minutes and applies what is newer than the last thing it applied, so a change made from Discord afterwards (a prefix, a nickname) is not overwritten until you save again here. It needs two values in the bot's .env: DASHBOARD_PUBLIC_URL and VYREX_BOT_SHARED_SECRET, the same secret the panel has. npm run doctor reports whether the sync is on, and >branding-sync applies immediately. Saves are stored in Upstash Redis; without Redis configured they live only in memory and the API answers persisted: false.

Global settings

Navigate to Dashboard → Bot Branding. Changes are saved to /api/bot-config (Redis-backed) and your local cache. The bot picks them up on its next poll, within five minutes, or straight away with >branding-sync.

SettingDescription
Avatar URLPNG/JPG image URL. Your bot must have permissions to change its avatar via the API.
Banner URLProfile banner (requires Discord Nitro on the bot account).
Global NicknameDefault display name across all servers (max 32 chars).
Brand ColourHex colour for generated embeds. Applied to every server that has not set its own colour; one that has keeps it. A value that is not a hex colour is stored as unset rather than replaced with a different one.
Activity TypeWatching, Playing, Listening to, Competing in, Streaming, or Custom.
Activity TextText shown after the activity type in the member list (max 128 chars).
Online StatusOnline (green), Idle (yellow), Do Not Disturb (red), Invisible.

Per-server nicknames

In the Per-server Nicknames card, add rows for each server where you want a custom nickname. These are stored separately at /api/bot-config?guildId=SERVER_ID and can be read individually by your bot worker per guild.

API format: POST /api/bot-config with {"guildId": "123", "nickname": "MyBot"} saves a per-guild config. GET /api/bot-config?guildId=123 retrieves it.
HomeDocsCommands

Commands

VYREX supports both slash commands (/command) and the text prefix (>command). The full, generated list is on the command reference.

Core commands

Every command runs with the text prefix (> by default, changeable per server). The hundred most used are also registered as slash commands and appear in Discord's / picker; everything else is prefix-only. Names and descriptions below are the bot's own.

CommandDescription
/helpInteractive command directory, by category
/setupInteractive server configuration wizard
/prefixShow the current command prefix for this server
>prefix-set <char>Change the server command prefix
/command <list|disable|enable|channel|role>Turn commands off, or limit them to certain channels or roles, in this server
/pingMeasure runtime latency, gateway heartbeat and connection stability
>statusLive platform health, runtime metrics and command pipeline status
>reloadReload commands (owner only)
/ban <user>Permanently remove a member from the server
/kick <user>Forcefully remove a member from the server
/mute <user>Restrict a member from communicating (timeout)
/warn <user>Issue a formal warning to a member
/tempban <user> <30m|6h|3d|1w>Ban for a set time (1 minute to 365 days); the unban is stored, so it still happens after a restart
>tempban-listEvery pending automatic unban in this server, with who set it and when it lifts
/unban <userId>Lift a ban early; also cancels its pending automatic unban
/sticky <set|show|list|remove>Pin a message to the bottom of a channel; it moves down as people chat and survives restarts
/ticketOpen a support ticket
/ticket-transcripts [id]List archived ticket transcripts, or fetch one by its ticket ID
>embedCreate a custom embed message

Vanity roles

Give a role to members who put your link in their custom status. They hold it while the text is there and lose it when they take it out.

CommandWhat it does
>vanity text <text>What to look for in a member's custom status, such as /yourserver
>vanity role @roleThe role they get while it is there
>vanity on / >vanity offTurn it on or off for this server
>vanity statusWhat is set, and how many members hold it
>vanity syncApply it to everyone currently online
Going offline never touches the role. Discord reports no activities for an offline member, so their status cannot be read — which is not the same as having removed the link. Stripping it there would make the role flicker every time someone slept. Idle and do-not-disturb are readable, so those count normally. Run >vanity sync after turning it on: statuses only reach the bot as they change, so a quiet member might not be picked up for days otherwise.
HomeDocsWelcome & goodbye

Welcome & goodbye

One command configures both messages. >welcome test posts exactly what a new member will see, built by the same code the join event runs.

Subcommands

CommandDescription
>welcomeShow the current configuration
>welcome channel #chWhere welcome messages go
>welcome goodbye-channel #chWhere goodbye messages go (defaults to the welcome channel)
>welcome message <text>Welcome message body, up to 1,500 characters
>welcome title <text>Welcome embed title
>welcome footer <text|off>Footer line under the welcome embed
>welcome banner <https-url|off>Image under the welcome embed (.png, .jpg, .gif or .webp)
>welcome color #hexWelcome embed colour
>welcome goodbye message <text>Goodbye message body
>welcome goodbye title <text>Goodbye embed title
>welcome goodbye color #hexGoodbye embed colour
>welcome goodbye on|offTurn goodbye messages on or off
>welcome enable|disableTurn welcome messages on or off
>welcome testPost a preview to the current channel
>welcome resetClear every message, title, footer, banner and colour

Variables

Any of these work in the message, title and footer, on both the welcome and the goodbye side:

VariableRenders as
{mention}A ping of the member
{user} · {username}Their username
{tag} · {usertag}Their tag
{id} · {userid}Their user ID
{guild}The server name
{count} · {membercount}The member count after the join or leave
{ordinal}The member count as an ordinal: 42nd
{inviter}Welcome only: who invited them, when invite tracking is on
{joineddays} · {isnew}Welcome only: account age in days, and yes when it is under a week old
{daysinserver} · {roles}Goodbye only: how long they stayed and the roles they held
Welcome cards: >welcome-card on attaches a rendered image card to the same message. The banner set here is used when the card is off.
HomeDocsModeration

Moderation

Bans, kicks, mutes, warnings and temporary bans record a moderation case and post to the mod log when one is set (/modlog-set). Member actions respect role hierarchy: the bot never acts on someone above the moderator or above itself. Descriptions are the bot's own. Names shown with / are in the slash picker; the rest run with the prefix.

Members

CommandWhat it does
/ban <user> [reason]Permanently remove a member from the server
>softban <user>Ban then immediately unban a member, removing their recent messages
/tempban <user> <30m|6h|3d|1w> [reason]Temporarily ban a user (auto-unbans after duration, survives restarts)
>tempban-listShow all currently active temporary bans and their remaining durations
/unban <userId>Revoke a ban and restore server access
>banlistList all banned users in this server (paginated)
/kick <user> [reason]Forcefully remove a member from the server
/mute <user> [duration]Restrict a member from communicating
/unmute <user>Restore communication for a member
>vmute / >vunmute <user>Server mute a member in voice channels, and remove it again
>silentban <user>Ban a user without sending them a DM or posting a public success message
/quarantine <user>Strip all of a member's roles and isolate them with a Quarantined role (reversible)
/unquarantine <user>Release a quarantined member and restore their saved roles
/nick <user> <name>Change a user's nickname
>decancer <user>Replace a member's unusual/hoisting nickname with a clean one
Temporary bans are stored, not timed. A restart does not lose them, a 30-day ban is a 30-day ban, and >tempban-list shows every pending unban with who set it. Lifting a ban early with /unban cancels the pending one.

Warnings, cases and records

CommandWhat it does
/warn <user> [reason]Issue a formal warning to a member
/warnings <user>Review warning history for a member
>unwarn <user> [index]Remove one warning from a member by index (or latest)
>clear-warnings <user>Clear all warnings for a member
>escalationView or configure the auto-escalation ladder for warnings
/case <id>View, edit, or delete a moderation case
/history <user>View combined moderation history for a member (warnings + cases + notes)
>mod-note <user> <text>Add a private moderator note to a user record
>notes <user>View private moderator notes for a user
/infractionIssue, review, edit and revoke staff infractions
/promotion / /demotionMove a member up or down the configured rank ladder and record it
/staffStaff records, roster, audit trail and system stats

Channels

CommandWhat it does
/purge <amount|all>Delete messages in bulk — any number, or the whole channel
>purge-user <user> [amount]Delete recent messages from a specific member in this channel
/slowmode <seconds>Adjust the message cooldown for the current channel
/lock / /unlockLock a channel (prevent sending messages), and resume normal transmission
>lockdownRestrict all message transmission in a channel
>lock-server / >unlock-serverDeny or reset @everyone send-message permission across all text channels
>raidmode / >unlockallLock or unlock every channel at once (fast raid response)
>nukeClone and replace a channel to purge all history

Server security

CommandWhat it does
>antiraidConfigure and monitor automatic raid protection
>securityauditScore this server's security posture and list what to fix
>securityhardenTurn on every protection that is safe to enable automatically
/command <disable|channel|role|enable|list>Turn commands off, or limit them to certain channels or roles, in this server
Command rules can only narrow access. A /command rule turns an allow into a deny for a server; nothing you set there grants a member a command they could not already run, and the command and help commands themselves cannot be locked out. Naming an alias works — the rule is recorded against the command’s real name, and the reply tells you which one that is.
HomeDocsAutomod

Automod

Eight filters, each its own switch, with thresholds you set per server. Everything is off until you turn it on, and channels or roles you exempt are never scanned. Names and limits below are the bot's own.

Filters

FilterWhat it catches
Bad Words FilterConfigurable word list with leet-speak normalisation (>automod badwords to manage it)
Link ProtectionBlocks http links except allowed domains (>automod whitelist)
Invite BlockerRemoves Discord invite links
Mention ShieldRemoves messages over the mention limit
Caps ControlRemoves shouted messages
Emoji StabilizerRemoves emoji floods over the emoji limit
Zalgo DefenseRemoves text stacked with combining marks
Phishing ShieldRemoves known scam patterns (fake Nitro, gift links, verification bots)

Thresholds and escalation

SettingRange
Violation LimitStrikes before a timeout: 2–20, default 5
Timeout DurationMinutes: 1–1440, default 10
Burst LimitMessages in the spam window before spam triggers: 3–20, default 6
Spam WindowSeconds: 5–120, default 10
Max Mentions2–30, default 6
Max Emojis5–120, default 18

Commands

CommandWhat it does
/automodShow what is on, with the current thresholds
>automod on|offTurn the whole system on or off for this server
>automod panelInteractive menu to toggle each filter and set every threshold
>automod badwords add|remove|list <word>Manage the word list
>automod whitelist add|remove|list <domain>Domains that Link Protection lets through
>automod exempt <#channel|@role>Channels and roles automod never scans
>automod resetBack to defaults
>automod-config punish <none|warn|mute>What happens after the violation limit
>automod-config scanprefix <on|off>Also scan messages that invoke a bot command (off by default)
Commands are not scanned by default. A message that invokes a bot command is skipped unless scanprefix is on, so >say and >8ball do not trip the filters. Ordinary messages are always scanned when a filter is on.
HomeDocsTickets

Tickets

Private channels per request, a panel with a button for members, and an archive that survives the channel. Set a category and a support role with >ticket, then post a panel. Tickets use channel topics and permission overwrites; no dashboard is needed for the core flow.

CommandWhat it does
/ticket <reason>Open a support ticket. The reason must be 8+ characters; the channel is named after the member
>ticket category <id|name>Category the ticket channels are created under
>ticket supportrole @roleThe role that has access to every ticket
>ticket limit <1-20>Open tickets allowed per member
>ticket listEvery open ticket
>ticketpanelPost a persistent panel with an Open Ticket button.
>ticket-panel [config …]Post or configure a support ticket panel (custom title, description, author, footer, button; images via HTTPS args, attachments, or env TICKET_PANEL_*). Manage Server.
>ticket-add @user / >ticket-remove @userAdd a user to the current ticket, or remove one
>ticket-closeClose a ticket — the HTML transcript is posted before the channel is deleted
>ticket-listList open support and application tickets (staff)
>ticket-transcriptExport this ticket channel as an HTML transcript (Discord-style layout, all messages and attachment links). Use inside a support or application ticket.
/ticket-transcripts [id]List archived ticket transcripts, or fetch one by its ticket ID.
>ticket-setupThe setup guide: panel, member commands, staff export and the recommended layout, in one embed

Applications and staff trials

An applicant opens a ticket, fills it in, and a reviewer decides. Accepting can grant the role outright, or put them on a probation period first.

CommandWhat it does
>apply-panelPost one application panel where members pick a role from a menu
>apply-ticket <role>Open an application ticket for a specific role
>apply-accept [role]Accept the application and grant the role
>apply-accept trial [days]Accept on probation instead — grants the trial role and starts the clock
>apply-denyDeny the application and close the ticket
>trial role @roleThe role a trial grants
>trial days <1-90>How long a trial runs by default
>trial start @user [days]Grant the trial role and start the clock
>trial confirm @user [@role]They passed — grant the real role and take the trial one off
>trial end @user [reason]They did not — take the trial role back
>trial listWho is on trial, and when each is reviewed
Nothing is promoted automatically. A trial is stored with its end date rather than held in a timer, so a restart never loses one. When the time is up VYREX raises it once in your application review channel and a person decides. Set the trial role before accepting anyone onto a trial — without one, the command refuses rather than inventing a role.
Closing a ticket deletes its channel a few seconds later, so the transcript written on close is the only copy. /ticket-transcripts reads that archive; the support role and anyone with Manage Channels can open it, and it only ever returns this server's tickets.
HomeDocsEconomy & levels

Economy & levels

Gold, XP and reputation per member, with a shop and leaderboards. Members earn XP by chatting and by voice time; the commands below are the ones in the slash picker.

CommandWhat it does
/balance [user]View your or another user's balance.
/dailyClaim your daily gold and XP reward
/workWork for gold and experience
/shopBrowse the VYREX shop and purchase items.
/pay <user> <amount>Transfer gold to another user.
/richestView the richest players
/slots <amount>Bet gold on the slot machine for a chance to win big!
/betflip <amount> <heads|tails>Flip a coin and bet gold on the outcome.
/rank [user]View your level and progress, or another member's.
/leaderboardView the global XP rankings.
/profile [user]Display a comprehensive player identity card.
/rep <user>Endorse a user with reputation points.
>track <amount|all>Stake gold and lock a moving marker on a multiplier zone
The odds on >track are published, not implied. Every strip is the same ten zones shuffled: one 3x, one 2x, two 1.5x and six that pay nothing, so it returns 80% of what goes into it over time. The zone you get is the one the marker was standing on when you pressed — nothing is rolled afterwards. A round nobody locks refunds the stake.
Level roles: >addlevelrole <level> @role grants a role when a member reaches a level. The full economy — jobs, gacha, pets, casino games, crafting — is in the command reference.
HomeDocsVoice assistant

Voice assistant

VYREX can sit in a voice channel, hear a wake word, answer out loud, and optionally run moderation commands it was asked for by voice. Because it listens to people, the rules about who is told and who can refuse come first.

What happens to the audio. Speech is decoded in memory, sent to the configured speech-to-text provider, and discarded. Nothing in the voice path writes audio to disk. Transcripts are only posted to a channel if a server turns vc transcript on.

Who is told, and how to refuse

  • Joining announces itself. >vc join replies in the channel with what the bot is listening for and how to opt out.
  • So does arriving later. Anyone who walks into the voice channel while a session is live is named once, in the same channel, with the same instruction. A group arriving is announced together rather than one line each.
  • Opting out is global and permanent. >vc optout means the bot never transcribes that person, in any server, until they run >vc optin. The check runs before the audio stream is subscribed to, not after.
  • Opting out is not announced. Someone who has already opted out is not named on arrival, because they are not being transcribed and the choice is theirs to share.

Commands

CommandWhat it does
>vc join [#channel]Join and start listening. Needs Connect and Speak in that channel.
>vc leaveDisconnect and stop listening.
>vc ask <question>Ask by typing; the answer is spoken out loud.
>vc statusLive diagnostics and latency for the current session.
>vc testEnd-to-end self-test of the voice pipeline.
>vc optoutNever transcribe me, in any server.
>vc optinUndo that.
>speak <text>Say something out loud in the current voice channel.
>transcribeReply to an audio file to transcribe it.

Settings (Manage Server)

CommandWhat it setsDefault
>vc mode wake|always|pushWhen the bot respondswake
>vc wake <phrase>The wake phrasehey vyrex
>vc voice <name>The speaking voiceprovider default
>vc persona <style>The personality of repliesprofessional
>vc transcript on|off [#channel]Post what was said to a channeloff unless set
>vc actions on|offLet voice run moderation commandson
Speech-to-text needs a key. Set GROQ_API_KEY (free tier) or DEEPGRAM_API_KEY and restart. Without one the bot can still speak, but it cannot listen. Timing is tunable: VYREX_VOICE_SILENCE_MS (default 800) is the pause that ends an utterance, VYREX_VOICE_MAX_UTTERANCE_MS (default 30000) caps a single one, and VYREX_VOICE_IDLE_TIMEOUT_MS (default 600000) leaves an idle channel.
HomeDocsAuthentication

Authentication

VYREX signs in with PKCE-based Discord OAuth only. Sessions are server-backed via Upstash Redis.

Discord OAuth (PKCE)

  1. User clicks Continue with Discord. The browser generates a 48-byte random code verifier.
  2. The SHA-256 hash of the verifier (code challenge) is sent to Discord's authorize URL.
  3. Discord redirects to /oauth-callback with an auth code.
  4. The callback calls POST /api/discord-token, sending the code + verifier. The server exchanges these for an access token without the client_secret ever touching the browser.
  5. The access token is used to call GET /users/@me on Discord's API to get the user's ID and email.

Sessions and accounts

Accounts are stored in Upstash Redis under vyrex:acc:<id>. Sessions are 32-byte random tokens stored under vyrex:sess:<token> with a 30-day TTL. Password sign-in is disabled by default; see Auth endpoints.

Tier system

All role checks happen server-side in api/_lib/serverAccountTier.js:

TierAccess levelSet via
FounderFull platform access including Founder panelVYREX_OWNER_DISCORD_ID
OwnerTeam management, system ops, subscriptionsVYREX_COOWNER_DISCORD_IDS
StaffAnalytics, logs, admin accounts viewVYREX_STAFF_DISCORD_IDS
MemberDashboard, commands, modules, automationsEveryone else
HomeDocsEmbed builder

Embed builder

Build rich Discord embeds visually and export the JSON to use in any bot.

Using the embed builder

Navigate to Dashboard → Embed Builder. The live preview updates as you type. When done, click Copy JSON to get the payload.

JSON output format

{
  "embeds": [{
    "color": 5046271,
    "author": { "name": "VYREX", "url": "https://vyrex.lastlydevelopments.com" },
    "title": "Embed Title",
    "description": "Your **markdown** text here.",
    "fields": [
      { "name": "Field 1", "value": "Value 1", "inline": true },
      { "name": "Field 2", "value": "Value 2", "inline": true }
    ],
    "footer": { "text": "VYREX Bot" },
    "timestamp": "2025-01-01T00:00:00.000Z"
  }]
}

Quick presets

8 built-in presets: Welcome, Announcement, Warning, Success, Error, Info, Rules, Event. Click any to load it into the builder.

Tip: Save your custom embeds as named presets using Save preset — they're stored in your browser and persist across sessions.
HomeDocsTeam & roles

Team & roles

Manage your platform team using Discord ID allowlists on Vercel environment variables.

Adding team members

  1. Get the team member's Discord user ID (right-click their name in Discord → Copy User ID, with Developer Mode on).
  2. Add the ID to VYREX_COOWNER_DISCORD_IDS (Owner) or VYREX_STAFF_DISCORD_IDS (Staff) on Vercel — comma-separated for multiple IDs.
  3. Redeploy the project. The team member can now sign in with Discord and access their tier-appropriate sections.
Note: The Founder panel is exclusively for the single Discord ID set in VYREX_OWNER_DISCORD_ID. It cannot be shared or transferred.
HomeDocsAPI overview

API overview

All VYREX API routes are serverless Node.js functions deployed alongside the static site.

Base URL

https://your-domain.vercel.app/api/

Authentication

API routes accept two auth methods:

  • API key: x-vyrex-api-key: YOUR_DASH_API_KEY header — full access
  • Discord OAuth: Authorization: Bearer DISCORD_ACCESS_TOKEN — access scoped by Discord ID tier

Available routes

RouteMethodDescription
/api/healthGETService health check — no auth required
/api/discord-tokenPOSTExchange Discord auth code for access token
/api/auth-accountsGET/POST/PUTUser account management and sessions
/api/bot-snapshotGETFetch bot's guilds from Discord API
/api/bot-configGET/POSTBot branding and per-server configuration
/api/command-catalogGETSearch the generated command reference
/api/workspace-storeGET/POSTPersist dashboard workspace state to Redis
/api/guild-planGET/POSTManage per-guild billing plan
/api/connection-statusGETConfiguration and storage health summary
/api/connection-selftestGETFull self-test with latency measurements
HomeDocsAuth endpoints

Auth endpoints

The /api/auth-accounts endpoint handles sessions and admin operations. Sign-in itself goes through Discord OAuth — see Authentication.

POST /api/auth-accounts — Register / Login

Both actions are disabled. VYREX signs in with Discord only, so these return:

403 { "error": "password_auth_disabled" }

Set VYREX_ALLOW_PASSWORD_AUTH=1 on the deployment to re-enable email/password sign-in. It is off by default and should stay off unless you have a specific reason.

POST /api/auth-accounts — Logout

{ "action": "logout" }

Returns: { "ok": true }

GET /api/auth-accounts?me=1

Requires Authorization: Bearer SESSION_TOKEN. Returns the current account and computed tier.

HomeDocsBot config API

Bot config API

Store and retrieve bot customisation settings per-guild or globally.

GET /api/bot-config

Returns global config. Append ?guildId=SERVER_ID for per-guild config.

POST /api/bot-config — Global

{
  "activityType": "watching",
  "activityText": "your server",
  "onlineStatus": "online",
  "brandColor": "#7c3aed",
  "globalNick": "VYREX",
  "avatarUrl": "https://cdn.example.com/avatar.png"
}

Requires Founder or Owner auth (API key or elevated Discord ID).

POST /api/bot-config — Per-guild

{ "guildId": "1234567890", "nickname": "MyBot", "prefix": "!", "embedColor": "#34d399" }

Requires any valid auth (Discord OAuth or API key).

FAQ

Common questions about VYREX setup and configuration.

Why does /api/bot-snapshot show 0 servers?

The bot snapshot requires DISCORD_BOT_TOKEN set on Vercel and a valid Discord or API key auth header. Sign in with Discord in the dashboard and click Sync from Discord.

My session expires — how do I extend it?

Sessions last 30 days (Redis TTL). The dashboard auto-refreshes the server session if you're active. Re-signing in creates a fresh session.

Can I run multiple bots from one dashboard?

Currently one bot token per deployment. To manage multiple bots, deploy separate instances of VYREX with different environment variables.

How do I enable Stripe billing?

Add STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_PRO, and STRIPE_PRICE_PREMIUM to Vercel. The /api/stripe-session handler is ready.

HomeDocsTroubleshooting

Troubleshooting

Common issues and how to fix them.

"Failed to fetch" on Discord sign-in

The /api/discord-token route is not reachable. Check: (1) the site is deployed on Vercel (not opened as a file), (2) DISCORD_CLIENT_SECRET is set, (3) the redirect URI in Discord Portal matches exactly.

Sessions not persisting across devices

Configure Upstash Redis. Without it, sessions are in-memory and lost on function cold starts.

Bot branding not applying to Discord

The dashboard saves config to /api/bot-config. The bot reads it every five minutes when DASHBOARD_PUBLIC_URL and VYREX_BOT_SHARED_SECRET are set in its .env; npm run doctor in the bot repo tells you whether that sync is on.

Owner/Staff access not working

Make sure you signed in with Discord OAuth. The tier check compares your Discord user ID against the env var allowlists. After adding IDs, redeploy Vercel.

Still stuck? Visit Support — the status page shows which keys are set on this deployment.