Skip to main content
The Discord bot lets you ingest images directly from Discord into Pindeck. Imported images land in a moderation queue before any AI processing begins, giving you full control over what enters your library.
The Discord bot is hosted separately from Pindeck. It lives in its own repository and calls Pindeck’s Convex HTTP endpoints over the network. You deploy and run the bot independently — Pindeck does not run it for you.

How it works

1

Trigger an import

React to any Discord message that contains an image with your configured ingest emoji, or run /images import with an optional message link. The bot extracts image URLs, parses post metadata (title, description, source URL, sref style reference), and sends a POST /ingestExternal request to your Convex backend.
2

Image lands as pending

The image is created in Pindeck with status: pending. No AI analysis runs yet. Pindeck posts a Waiting Approval status notification to your Discord webhook channel (if DISCORD_STATUS_WEBHOOK_URL is set).
3

Review the queue

Run /images review in Discord. The bot fetches up to 5 pending items via POST /discordQueue and posts each one as an embed with Approve, Deny, and Generate buttons.
4

Moderate

Click a button or run /images approve, /images reject, or /images generate directly. The bot calls POST /discordModerate with the chosen action.
  • Approve — triggers AI analysis (VLM metadata extraction), then variation generation if a count was requested.
  • Deny — deletes the image record.
  • Generate — skips straight to variation generation using the default count and mode.
5

Status updates

As each stage completes (approved, rejected, generation started, variation queued), Pindeck posts a status message to your Discord webhook channel. When an Approved event appears, the bot automatically posts variation mode buttons for that image.

Ingestion methods

Emoji reaction

React to any message containing an image with one of the emojis configured in DISCORD_INGEST_EMOJIS. The bot immediately imports the image into the moderation queue.
You can configure multiple ingest emojis as a comma-separated list: 📥,<:pindeck:123456789012345678>. Both standard Unicode emojis and custom server emojis are supported.

Slash command

Run /images import in any channel the bot can read. If you omit the message_link option, the bot scans the last 50 messages for the most recent one containing an image. Pass a full Discord message URL to import from a specific message.
/images import
/images import message_link:https://discord.com/channels/123/456/789

Moderation queue

Pending images appear in the Boards/queue view in Pindeck and can also be reviewed from Discord using /images review. Each queue card shows the image preview, title, description, image ID, status, and parsed sref value.
ActionEffect
ApproveSends image to AI analysis; variations generated if count > 0
DenyPermanently deletes the image record
GenerateTriggers variation generation directly, bypassing analysis
You can also approve, reject, or generate by image ID using the direct subcommands:
/images approve image_id:<id>
/images reject image_id:<id>
/images generate image_id:<id> count:4 mode:shot-variation

Variation generation from Discord

The /images generate command and the Generate button both call POST /discordModerate with action: generate. You can specify:
  • count — number of variations (1–12; defaults to DISCORD_GENERATE_DEFAULT_COUNT)
  • mode — variation mode: shot-variation, action-shot, coverage, b-roll, style-variation, subtle-variation
  • detail — optional custom direction passed to the generation prompt

Status webhooks

Set DISCORD_STATUS_WEBHOOK_URL in Convex Project Settings to receive status notifications in a Discord channel. Pindeck posts a message for each of the following events:
EventLabel
queuedWaiting Approval
approvedApproved
rejectedRejected
generation_startedGenerating Variations
generatedVariation Queued
Each queued and generated notification also includes quick-action commands (/images approve image_id:...) for convenience.

RSS and metadata parsing

When a message is ingested, the bot parses the message content and embeds to extract:
  • Title — from embed title, or first non-empty line of message content
  • Description — message content and/or embed description
  • Source URL — embed URL or the first non-image, non-Discord URL in the message
  • sref — style reference number matched against patterns like sref 12345, sref:12345, or #sref12345
Parsed sref values are stored on the image record and added as a sref:<number> tag.

Lineage tracking

Variations triggered from Discord are created with a parentImageId reference pointing to the source image, building a traceable generation chain. The lineage depth is capped at 12 levels to prevent runaway chains.

HTTP endpoints

The bot calls these Convex HTTP endpoints. All requests use Bearer <INGEST_API_KEY> authorization.
EndpointMethodPurpose
/ingestExternalPOSTIngest an image URL into the moderation queue
/discordQueuePOSTFetch pending items for review
/discordModeratePOSTApprove, reject, or generate for an image

Environment variables

These variables are set in the Discord bot’s .env.local file (not in Convex Project Settings).
VariableRequiredDescription
DISCORD_TOKENYesBot token from the Discord Developer Portal
DISCORD_CLIENT_IDRecommendedApplication ID; auto-derived from token if omitted
DISCORD_GUILD_IDRecommendedGuild ID for fast slash command registration
DISCORD_INGEST_EMOJISYesComma-separated emoji triggers for ingest (e.g. 📥)
INGEST_API_KEYYesMust match the INGEST_API_KEY set in Convex Project Settings
PINDECK_INGEST_URLRecommendedFull URL to https://<deployment>.convex.site/ingestExternal
PINDECK_DISCORD_QUEUE_URLOptionalDefaults to /discordQueue on the same Convex site URL
PINDECK_DISCORD_MODERATION_URLOptionalDefaults to /discordModerate on the same Convex site URL
PINDECK_USER_IDYesConvex user ID that imported images are assigned to
NEXTCLOUD_PUBLIC_SHARE_TOKENOptionalFor serving images via NextCloud shared folder
The following variables are set in Convex Project Settings (not the bot’s .env):
VariableDescription
INGEST_API_KEYShared secret that the bot sends as a Bearer token
DISCORD_STATUS_WEBHOOK_URLDiscord webhook URL for status notifications

Bot permissions

When inviting the bot to your server via the Discord Developer Portal OAuth2 URL generator, select these scopes and permissions: Scopes: bot, applications.commands Bot permissions: View Channels, Send Messages, Embed Links, Read Message History, Add Reactions, Use Application Commands

Build docs developers (and LLMs) love