🧩 Admin
Images
Loading images...
Preview Title ID Description Category Tags Size Popularity Source Status Rating Created Updated Star Actions
Loading rooms...
Room ID Image Dimensions Progress Players
(Active/Total)
Status Creator Completed Guild Channel Deleted Created Last Activity Action
Loading users...
User User ID Discord ID Type Status Pieces Solved Playtime Created Completed Last Active Registered Action
Loading catalog...

Categories

Invalid characters are removed automatically. Renames cascade to linked images.

    Tags

    Names become lowercase slugs automatically, e.g. “Deep Space” → deep-space.

      Loading flags...
      Type Flag ID Entity / Room Reason Details Sender Reporter Reports Status Reported Date Updated Actions
      When Room Sender Message Actions
      No active room chat messages.
      Loading errors...
      Source Message Where Room Country User ID App version Client IP Fingerprint Count Status First seen Last Seen Actions
      Loading conversations...
      Player Latest message Messages Unread (player) Status Created Updated Last Activity Actions
      PuzzleBot instances
      Loading instances…
      Guild Channel Announce Instance ID Status Puzzle Image Grid Players Completed Claimed Room activity Last seen Actions

      Players

      Who can open the app, and which lobby controls they see.

      Access

      Guest play outside Discord, and uploads from the lobby.

      Shown to web visitors while guest access is off.

      Feature flags

      Lobby controls a player can see. Room rules and chat live in their own groups.

      Each player's own "Hide NSFW content" preference applies either way.
      Web rooms stay public unless the host opts out. Discord Activity rooms are always unlisted.
      Passwords are ignored on public rooms. Join checks the password before opening the live room.

      Rooms

      How rooms open, how many people they hold, and what happens during play.

      Room rules

      Who may end a room, and whether a public room is kept open.

      Off by default. Unlisted web rooms stay deletable by their creator either way.
      On by default. Off, the host returns to the title screen with no delete.
      Off by default. When on, a missing public room is opened from the featured catalog at 8×5.

      Room limits

      Minimum 1. Maximum 10000. Default 1000.
      A player who already has this many unfinished rooms cannot create another. Minimum 1. Maximum 100. Default 10.
      Minimum 1. Maximum 500. Default 50.

      During a puzzle

      What happens while people are in a room. Each number is used as entered, within its minimum and maximum.

      Pieces a player can hold in one multi-select pile. Minimum 1. Maximum 100. Default 10.
      Silence from the host before hosting passes to another player, in a room and in an Activity lobby. Minimum 5. Maximum 3600. Default 60.
      Seconds to wait after a dropped socket before announcing leave or handing over hosting. Minimum 0. Maximum 300. Default 3.
      Seconds a drag lock may sit idle before the server releases the piece. Minimum 1. Maximum 600. Default 15.

      Chat and reports

      Room chat, and which reports players are allowed to send.

      Chat

      Players can still open the drawer when sending is off.

      On by default. When off, players can still open chat but cannot send.
      Characters. Longer messages are dropped. Minimum 1. Maximum 4000. Default 500.
      Per player. Exceeding it replies with a slow-down notice rather than disconnecting. Minimum 1. Maximum 100. Default 5.
      Ring buffer replayed to a joining player. Minimum 1. Maximum 1000. Default 100.

      User flags

      Toggle the flags a user can raise in the app.

      Room flags

      Toggle the flags a player can raise about a room.

      Off by default. When on, a right-click on the room code submits a report.

      Images

      What the lobby and admin URL import will accept.

      Image intake

      Applies to lobby URL imports and admin URL uploads. Direct file uploads are bounded by the browser.

      Download is cancelled past this size. Minimum 1. Maximum 100. Default 20.
      Minimum 1. Maximum 10000. Default 1200.
      Minimum 1. Maximum 10000. Default 800.

      AI Vision models

      Workers AI models used for image captioning, tag generation, and NSFW classification.

      Workers AI model id for queries and classification. Default @cf/moondream/moondream3.1-9B-A2B.
      Second model tried when the primary returns no response. Set identical to primary to disable fallback. Default @cf/meta/llama-3.2-11b-vision-instruct.

      Retention

      How long rooms, accounts, and collected errors are kept.

      Retention

      How long each record survives. The daily cron applies these numbers as entered, within each field's minimum and maximum.

      How long a joinable room stays listed in its creator's History. Minimum 1. Maximum 365. Default 14.
      Inactivity after which rejoining resets the board. Also bounds which puzzle PuzzleBot resumes. Minimum 1. Maximum 8760. Default 48.
      Inactivity after which a room stops being joinable. The record itself is kept. Minimum 1. Maximum 365. Default 14.
      Rooms with nobody in them, at most one player in total, and no pieces placed. Includes public rooms. Minimum 30. Maximum 86400. Default 300.
      Days after a room's last move before its record is purged from the database. Minimum 30. Maximum 3650. Default 60.
      Inactivity before a non-Discord account is purged. Minimum 1. Maximum 3650. Default 90.
      Inactivity before a Discord account is purged. Discord players are kept much longer than guests. Minimum 1. Maximum 3650. Default 365.

      Error collection

      When off, submitted errors are acknowledged but not stored, and the Errors page is hidden.
      How long a collected browser error is kept after its last occurrence. Minimum 1. Maximum 3650. Default 30.

      Operations

      Request budgets. The short burst ceilings stay in the deploy config.

      Rate limiting

      Login, registration, URL import, reports, AI. 0 leaves each route on its own budget. Minimum 0. Maximum 100000. Default 0.
      Catalog, stats, room lookups, admin calls. 0 leaves each route on its own budget. Minimum 0. Maximum 100000. Default 0.
      Image file and thumbnail streaming. 0 leaves each route on its own budget. Minimum 0. Maximum 100000. Default 0.

      PuzzleBot

      Hosting in a Discord Activity, and messages players send to PuzzleBot.

      PuzzleBot

      When off, PuzzleBot never claims hosting and the Bot page is hidden.
      Wait after a puzzle is completed before starting another. Minimum 0. Maximum 3600. Default 30.
      Silence from the human host before PuzzleBot may take over. Minimum 1. Maximum 3600. Default 30.
      Time allowed for a host to pick the next puzzle before PuzzleBot starts one automatically. Minimum 10. Maximum 600. Default 60.
      How many channels one server may run PuzzleBot in at once. Minimum 1. Maximum 100. Default 1.
      Consecutive bot puzzles nobody touches. Minimum 1. Maximum 50. Default 2.
      How long one Activity instance holds a server's hosting claim before another may take it. Minimum 10. Maximum 86400. Default 120.
      No floor when this is 0. Minimum 0. Maximum 1000. Default 0.
      No ceiling when this is 0. Minimum 0. Maximum 1000. Default 0.

      Player messages

      When off, players cannot send new PuzzleBot messages and the Messages page is hidden.
      A full thread stops accepting new player messages. Minimum 1. Maximum 5000. Default 200.

      Integrations

      A private management API, and the addresses notified when something happens.

      Private API

      Callers send this value in the X-Api-Key header. Leave it empty and every private API call is rejected. 16–256 characters when set.

      Endpoints

      • GET /api/private/images
      • POST /api/private/images/upload
      • POST /api/private/images/url-import
      • POST /api/private/images/generate
      • POST /api/private/images/analyze
      • PUT /api/private/images/:id
      • DELETE /api/private/images/:id
      • POST /api/private/images/:id/restore
      • GET /api/private/rooms
      • DELETE /api/private/rooms/:id
      • GET /api/private/users
      • DELETE /api/private/users/:id
      • GET /api/private/flags
      • POST /api/private/flags
      • POST /api/private/flags/:id/dismiss
      • POST /api/private/flags/:id/resolve
      • GET /api/private/chat/flagged
      • DELETE /api/private/chat/messages/:id
      • POST /api/private/chat/flagged/:id/dismiss
      • PUT /api/private/catalog/categories/:id
      • PUT /api/private/catalog/tags/:id

      Webhooks

      POST when a room is first created. Leave empty to skip.
      Sample payload
      {
        "event": "room.created",
        "occurredAt": 1710000000000,
        "data": {
          "roomId": "ABCD",
          "creatorId": "guest_1",
          "imageId": "img_ocean",
          "visibility": "public",
          "cols": 20,
          "rows": 10
        }
      }
      POST when every piece is locked. Leave empty to skip.
      Sample payload
      {
        "event": "room.completed",
        "occurredAt": 1710000000000,
        "data": {
          "roomId": "ABCD",
          "imageId": "img_ocean",
          "completedAt": 1710000000000,
          "elapsedMs": 754000,
          "players": [
            { "id": "guest_1", "username": "Ada", "count": 120 }
          ]
        }
      }
      POST when empty or inactive rooms expire. reason is empty or inactive. Leave empty to skip.
      Sample payload
      {
        "event": "room.idle_expired",
        "occurredAt": 1710000000000,
        "data": {
          "reason": "empty",
          "rooms": [{ "roomId": "ABCD" }]
        }
      }
      POST when a room is removed. reason is admin, owner, or moderation. A retention purge sends data.rooms instead of data.roomId. Leave empty to skip.
      Sample payload
      {
        "event": "room.deleted",
        "occurredAt": 1710000000000,
        "data": {
          "reason": "owner",
          "roomId": "ABCD"
        }
      }
      POST when a guest or Discord account is first stored. Leave empty to skip.
      Sample payload
      {
        "event": "user.created",
        "occurredAt": 1710000000000,
        "data": {
          "userId": "guest_1",
          "username": "Ada",
          "isDiscordUser": false
        }
      }
      POST when a guest account is linked to Discord. Leave empty to skip.
      Sample payload
      {
        "event": "user.discord_linked",
        "occurredAt": 1710000000000,
        "data": {
          "userId": "123456789012345678",
          "discordUserId": "123456789012345678",
          "username": "Ada"
        }
      }
      POST when a player imports an image. Leave empty to skip.
      Sample payload
      {
        "event": "user.image_uploaded",
        "occurredAt": 1710000000000,
        "data": {
          "imageId": "usr_ocean",
          "title": "Coral reef",
          "width": 1920,
          "height": 1080
        }
      }
      POST when PuzzleBot starts, finishes, or drops a puzzle. action is started, completed, or deleted. Leave empty to skip.
      Sample payload
      {
        "event": "puzzlebot.activity",
        "occurredAt": 1710000000000,
        "data": {
          "action": "started",
          "roomId": "ABCD",
          "instanceId": "i-1",
          "guildId": "123456789012345678",
          "channelId": "234567890123456789",
          "imageId": "img_ocean"
        }
      }
      POST when a report is first stored. Leave empty to skip.
      Sample payload
      {
        "event": "item.flagged",
        "occurredAt": 1710000000000,
        "data": {
          "flagId": "flag_1",
          "entityType": "image",
          "entityId": "img_ocean",
          "roomId": null,
          "reason": "user_report"
        }
      }
      POST when a client or admin error is captured. Leave empty to skip.
      Sample payload
      {
        "event": "error.captured",
        "occurredAt": 1710000000000,
        "data": {
          "id": "ce_1710000000000_abcde",
          "fingerprint": "a1b2c3d4e5f6",
          "source": "client",
          "kind": "error",
          "message": "Uncaught TypeError: Cannot read properties of undefined",
          "stack": "TypeError: Cannot read properties of undefined\n    at render...",
          "pageUrl": "https://puzzles.samliew.net/room/ABCD",
          "userAgent": "Mozilla/5.0...",
          "appVersion": "1.0.0",
          "userId": "guest_1",
          "roomId": "ABCD",
          "repeat": false
        }
      }