App-owned emojis
Emojis uploaded under your application are usable in any server your
bot posts in, without consuming that server's emoji slot. Discord
parity — same wire format, same <:name:id> syntax
in message content.
Limits
- 2,000 emojis per application (soft cap, enforced on create).
- 256 KB max file size.
- Content types:
image/png,image/jpeg,image/gif,image/webp. - Name: 2–32 characters, charset
[a-zA-Z0-9_]. Unique per app, case-insensitive —BotIconandboticoncollide.
Animated detection
The animated flag is set server-side from the upload's
content type — anything uploaded as image/gif is animated.
The client cannot override this. When you reference an animated emoji
in message content, use the <a:name:id> prefix
(Discord-identical).
REST endpoints
The bot-facing REST surface mirrors Discord's app emoji routes
exactly. Authenticate with Authorization: Bot {token}.
GET /applications/{application.id}/emojis
GET /applications/{application.id}/emojis/{emoji.id}
POST /applications/{application.id}/emojis
PATCH /applications/{application.id}/emojis/{emoji.id}
DELETE /applications/{application.id}/emojis/{emoji.id} POST body is identical to Discord's:
{
"name": "thinking_orange",
"image": "data:image/png;base64,iVBORw0KG..."
} Response shape:
{
"id": "1199283740192847360",
"name": "thinking_orange",
"animated": false,
"user": { "id": "...", "username": "you" },
"managed": false,
"available": true
} Using emojis in messages
Reference app emojis in content the same way as
server emojis:
// Static
"hello <:thinking_orange:1199283740192847360>"
// Animated (note the leading `a:`)
"thanks <a:wave_orange:1199283740192847361>"
For reactions, pass name:id in the URL-encoded emoji
path on PUT /channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me —
same as Discord.
Portal upload flow
The developer portal uploads emojis through the same presigned-URL pipeline as avatars and app icons:
POST /api/uploads/presignwithpurpose=bot_app_emojiandapplication_id.PUTthe file to the returned S3 URL.POST /api/uploads/completewith the returnedfile_id.POST /developer-portal/applications/{id}/emojiswith{name, file_id}.
The server verifies the file's s3_key prefix matches
bot-emojis/{application_id}/ — a leaked
file_id from another app fails the bind.
Storage
Stored at bot-emojis/{application_id}/{file_id}.{ext}
in the public gamevox-files-prod bucket. Soft-deleted
rows leave the S3 object in place; orphaned objects are harvested
by a background sweeper.