Levels

Use Levels when you want to reward participation with XP, rank cards, leaderboards, and roles.

Set up earning

  1. In Levels, turn on XP earning.
  2. Choose the message XP range and cooldown. You can also turn on voice XP and set its rate.
  3. Add no-XP channels or roles where activity should not count, such as staff chat or bots.
  4. Add a multiplier when a channel or role deserves extra XP.
  5. Save, then send a normal message with a test member.

The main XP switch pauses both message and voice awards. A member earns a random amount from your message range after their cooldown. Voice XP is awarded on the schedule shown in the dashboard when the session is eligible.

Ranks and rewards

Members use /rank view for a rank card, /rank settings to personalise their own card, and /levels for the server's all-time leaderboard.

In Role rewards, choose whether members keep every earned reward role or only their highest one. Guardy's role must sit above every reward role. You can also choose a level-up announcement channel and message.

Guardy can manage roles below its own role.
  1. Roles above GuardyGuardy cannot manage these.
  2. Guardy
  3. Roles Guardy can manageSelected roles, rewards, or member choices belong here.
  4. Member roles

Test one level-up with a role that is safe to grant. Do not use the same role for an autorole or reaction-role menu.

Public leaderboard and imports

/privacy leaderboard off makes a member anonymous on the public web leaderboard. It also leaves them out of /levels and /coins leaderboard. Their XP, level and /rank card stay the same. They can switch it back on at any time.

Moving from another leveling bot? Read importing before changing live totals.

Export your level data

Your server's level data is yours. Anyone who manages the server in the dashboard can download it at any time, on every plan, free.

  1. In Levels, open Import, export & reset.
  2. Under Export your level data, choose Download CSV or Download JSON.

The file lists every member who has XP, including members who chose /privacy leaderboard off (that setting only hides them on the public web leaderboard). Treat the file as private server data.

Both files list every member who has a Levels record in this server, highest XP first. The file name includes the server ID and the export date, for example guardy-levels-123456789012345678-2026-10-07.csv.

Members are identified by their Discord user ID. Guardy does not store member names with XP, so neither file includes names. Members whose data was erased at their request are not included. XP earned in the last few moments may not be in the file yet.

Member fields

Both formats use the same member fields. Every number is a whole number.

FieldTypeMeaning
ranknumberPosition by total XP. Members with equal XP share a rank.
user_idtextThe member's Discord user ID. Always text, never a number, because Discord IDs are too long for some programs to store as numbers.
xpnumberTotal XP, including voice XP.
levelnumberLevel as Guardy shows it, worked out from total XP with the curve below.
voice_xpnumberThe part of total XP earned in voice.
message_countnumberMessages Guardy has counted for XP. A member reset does not clear it.
weekly_xpnumberXP earned this week. Weeks start on Monday at 00:00 UTC.
monthly_xpnumberXP earned this calendar month, in UTC.
last_award_attext or emptyWhen the member last earned XP, as an ISO 8601 UTC time such as 2026-10-01T12:30:00Z. Empty if unknown.

CSV

The CSV has one header row and one row per member, with the columns in the order of the table above.

rank,user_id,xp,level,voice_xp,message_count,weekly_xp,monthly_xp,last_award_at
1,1234567890123456789,5000,10,500,300,200,900,2026-10-01T12:30:00Z
2,200000000000000001,900,4,0,41,0,120,2026-09-28T08:02:11Z
2,200000000000000002,900,4,0,44,0,0,

Spreadsheet programs can round long numbers. Import the user_id column as text so the IDs stay exact.

JSON

The JSON file is one object. schema names the format version, so a script can check it before reading the rest. members is always the last key and uses the member fields above.

{
  "schema": "guardy.levels.v1",
  "guild_id": "123456789012345678",
  "exported_at": "2026-10-07T09:15:00Z",
  "level_curve": {
    "name": "mee6",
    "xp_to_next_level": "5 * level^2 + 50 * level + 100",
    "total_xp_for_level": "5 * level * (2 * level^2 + 27 * level + 91) / 6"
  },
  "settings": {
    "leveling_enabled": true,
    "xp_per_message_min": 15,
    "xp_per_message_max": 25,
    "xp_cooldown_seconds": 60,
    "voice_xp_enabled": true,
    "voice_xp_per_tick": 10,
    "voice_tick_seconds": 300,
    "server_multiplier": 1,
    "role_reward_mode": "stack_all",
    "levelup_announce_mode": "channel",
    "levelup_announce_channel_id": null,
    "levelup_announce_template": "GG {user}, you just advanced to level {level}!",
    "levelup_style": "card",
    "levelup_milestone_image": true,
    "leaderboard_visibility": "unlisted"
  },
  "role_rewards": [
    { "level": 5, "role_id": "345678901234567890", "grandfathered": false }
  ],
  "multipliers": [
    { "scope": "channel", "target_id": "456789012345678901", "multiplier": 1.5 }
  ],
  "no_xp_zones": [
    { "scope": "role", "target_id": "567890123456789012" }
  ],
  "rank_card_default": {
    "background_key": "default",
    "color_mode": "solid",
    "color_primary": "#5865F2",
    "color_secondary": null,
    "accent_color": "#FFFFFF"
  },
  "members": [
    {
      "rank": 1,
      "user_id": "1234567890123456789",
      "xp": 5000,
      "level": 10,
      "voice_xp": 500,
      "message_count": 300,
      "weekly_xp": 200,
      "monthly_xp": 900,
      "last_award_at": "2026-10-01T12:30:00Z"
    }
  ]
}

All Discord IDs (guild_id, user_id, role_id, target_id, levelup_announce_channel_id) are text. exported_at is an ISO 8601 UTC time. settings holds the values on the Levels page: XP amounts are per message or per voice tick, cooldowns and ticks are in seconds, and server_multiplier and multiplier are decimals. In multipliers and no_xp_zones, scope is channel or role and target_id is that channel or role. grandfathered marks a role reward kept from an import above your plan's limit.

The level curve is the same one MEE6 uses. A member's level is the highest level whose total_xp_for_level is at or below their XP.

Bring an export back into Guardy

The CSV goes straight back into Guardy. Open the import wizard, choose the CSV export source, and upload the file. Guardy reads the user_id and xp columns and works out each level again from XP. One import file holds up to 80,000 members. The JSON file is for your own records and other tools; the import wizard does not read it.

Was this page helpful?