Skip to content

Expressions

An expression is a custom emoji or a sticker. Guild-owned expressions are managed on Guild emojis and Guild stickers. This page covers the routes that read an expression without membership of its guild, the lists of every expression the caller can use, and expression packs.

All routes are relative to https://tebhos.com/api/v1 and require authentication. Routes marked user-only refuse a valid bot token with 403 ACCESS_DENIED; the others also accept bot tokens. Error bodies follow Errors.

Expression IDs are snowflake strings. Every route that takes an emoji_id or sticker_id also accepts the legacy UUID form described in Emoji IDs. An unknown ID returns 404 NOT_FOUND.

Object Route Owning resource
Emoji metadata Get emoji metadata Guild emojis
Sticker metadata Get sticker metadata Guild stickers
Sticker Get sticker Guild stickers
Pack summary Expression packs The pack creator

Emoji metadata object

A custom emoji as seen from outside its guild.

Field Type Description
id snowflake The ID of the emoji
legacy_id ?string The legacy UUID identifier
guild_id snowflake The ID of the guild that owns the emoji
name string The emoji name
animated boolean Whether the image is animated
allow_cloning boolean Always true on this route. Clone guild emoji still refuses a source guild with CLONE_EMOJI_DISABLED
{
  "id": "1501314428688998182",
  "legacy_id": "b4497791-c19c-4b6b-9a2f-df4bc155a9f7",
  "guild_id": "1489002177550843904",
  "name": "party_parrot",
  "animated": true,
  "allow_cloning": true
}

Sticker metadata object

A sticker as seen from outside its guild.

Field Type Description
id snowflake The ID of the sticker
legacy_id ?string The legacy UUID identifier
guild_id snowflake The ID of the guild that owns the sticker
name string The sticker name
animated boolean Whether the stored image is a GIF
allow_cloning boolean false when the owning guild has CLONE_STICKER_DISABLED, otherwise true

Get emoji metadata

GET /emojis/{emoji_id}/metadata

Returns the emoji metadata object of any guild emoji. No membership of the owning guild and no permission is required.

Rate limit: guild:emoji:metadata, 60 per 10 seconds per client.

curl https://tebhos.com/api/v1/emojis/1501314428688998182/metadata \
  -H "Authorization: Bot $TEBHOS_BOT_TOKEN"

Get sticker metadata

GET /stickers/{sticker_id}/metadata

Returns the sticker metadata object of any guild sticker. No membership of the owning guild and no permission is required.

Rate limit: guild:sticker:metadata, 60 per 10 seconds per client.

Get sticker

GET /stickers/{sticker_id}

Returns one sticker for display, for example when a message shows a sticker from a guild the reader is not in. No membership is required. Unlike the other routes, the fields are camelCase:

Field Type Description
id snowflake The ID of the sticker
legacyId ?string The legacy UUID identifier
guildId snowflake The owning guild
name string The sticker name
description ?string The description
imageUrl string The URL of the stored image
tags array[string] Search tags
createdBy snowflake The uploader
createdAt ISO8601 timestamp When the sticker was created

List my guild emojis

GET /users/@me/guild-emojis

Returns every custom emoji of every guild the caller is a member of, as {"items": [...]}. Clients use it to build an emoji picker. Each item has id, legacy_id, guild_id, guild_name, name, image_url and animated. Guilds are grouped in order of guild name.

Sending an emoji from another guild in a guild channel, in a message or as a new reaction, requires both USE_EXTERNAL_EMOJIS in that guild and TEBHOS Pro; otherwise the request fails with 403 FORBIDDEN. Direct messages have no such check.

List my guild stickers

GET /users/@me/guild-stickers

Returns every sticker of every guild the caller is a member of, as {"items": [...]}. Each item has id, legacy_id, guild_id, guild_name, name, description and image_url.

Sending a sticker from another guild in a guild channel requires both USE_EXTERNAL_STICKERS in that guild and TEBHOS Pro; otherwise the request fails with 403 FORBIDDEN. A message can carry at most 3 stickers.

Expression packs

An expression pack is a personal collection of emojis (an emoji pack) or stickers (a sticker pack) owned by one account rather than a guild. Packs are a TEBHOS Pro feature: an account can create and install packs only while it has TEBHOS Pro.

Every pack route is user-only and has no route rate limit.

Pack limits

Limit Without Pro With TEBHOS Pro
Packs created, per type 0 50
Packs installed, per type 0 50
Items per pack - 200
Emoji image - 256 KiB, PNG, JPEG, GIF or WebP
Sticker image - 500 KiB, PNG, JPEG, GIF or WebP

Reaching a limit returns 400 BAD_REQUEST.

Pack summary object

Field Type Description
id snowflake The ID of the pack
name string The pack name, 1-64 characters
description ?string The description, up to 256 characters
type string emoji or sticker
creator_id snowflake The account that created the pack
created_at ISO8601 timestamp When the pack was created
updated_at ISO8601 timestamp When the pack was last changed
installed_at? ISO8601 timestamp When the caller installed it. Only in the installed lists
{
  "id": "1502001122334455667",
  "name": "Workshop reactions",
  "description": null,
  "type": "emoji",
  "creator_id": "1489002177550843905",
  "created_at": "2026-09-14T09:12:44+00:00",
  "updated_at": "2026-09-14T09:12:44+00:00"
}

List my packs

GET /packs

Returns the caller's created and installed packs, grouped by type:

{
  "emoji": {"installed_limit": 50, "created_limit": 50, "installed": [], "created": []},
  "sticker": {"installed_limit": 50, "created_limit": 50, "installed": [], "created": []}
}

Each list holds pack summary objects. The limits are 0 for an account without TEBHOS Pro.

Create pack

POST /packs/{pack_type}

Creates an empty pack and returns its pack summary object. {pack_type} is emoji or sticker; any other value returns 400 BAD_REQUEST.

Field Type Description
name string The pack name, 1-64 characters after trimming
description? ?string Up to 256 characters. Empty means none

Modify pack

PATCH /packs/{pack_id}

Renames a pack and returns its pack summary object. Only the creator can change a pack (403 FORBIDDEN otherwise).

Field Type Description
name? string The new name, 1-64 characters

Delete pack

DELETE /packs/{pack_id}

Deletes a pack. Only the creator can delete it. Returns 204.

Pack items

The creator manages a pack's items with these routes. The pack must be of the matching type, otherwise the request fails with 400 BAD_REQUEST; a pack owned by someone else returns 403 FORBIDDEN.

Route Description
GET /packs/emojis/{pack_id} List the emojis: id, name, animated, nsfw (always false) and user
POST /packs/emojis/{pack_id} Add an emoji. Body: name (1-32 characters) and image
POST /packs/emojis/{pack_id}/bulk Add 1-50 emojis. Body: {"emojis": [...]}. Returns {"success", "failed"}
PATCH /packs/emojis/{pack_id}/{emoji_id} Rename an emoji. Body: name (required)
DELETE /packs/emojis/{pack_id}/{emoji_id} Remove an emoji. Returns 204
GET /packs/stickers/{pack_id} List the stickers: id, name, description, tags, animated, nsfw and user
POST /packs/stickers/{pack_id} Add a sticker. Body: name (1-32 characters), description? (up to 256), tags? (up to 20) and image
POST /packs/stickers/{pack_id}/bulk Add stickers. Body: {"stickers": [...]}. Returns {"success", "failed"}
PATCH /packs/stickers/{pack_id}/{sticker_id} Update a sticker. Body: name (required), description? and tags?. tags replaces the list; omitting it clears the tags
DELETE /packs/stickers/{pack_id}/{sticker_id} Remove a sticker. Returns 204

For pack items, image must be a data: URL (for example data:image/png;base64,...); raw base64 is refused. The declared media type decides the format, and a GIF, an animated PNG or an animated WebP is marked animated. The item routes return the created or updated item without user.

The delete routes accept the query parameter purge=true, which also deletes the stored image file.

Pack invites

GET /packs/{pack_id}/invites lists the pack's invite codes and POST /packs/{pack_id}/invites creates one. Only the creator can use them.

Field Type Description
max_uses? integer 0-100, where 0 means unlimited (default 0)
max_age? integer Lifetime in seconds, 0-604800, where 0 means no expiry (default 0)
unique? boolean When false (the default), an existing invite by the caller with the same settings is returned instead of a new one

A pack can have at most 1000 invites. Each pack invite object has code, type (2 for an emoji pack, 3 for a sticker pack), pack (the pack summary plus creator), inviter, expires_at, temporary, created_at, uses and max_uses.

Pack invite codes cannot be accepted yet

Accept invite and Get invite handle guild invites only. To add someone else's pack, install it by its ID.

Install pack

POST /packs/{pack_id}/install

Adds a pack to the caller's installed packs and returns 204. Any existing pack can be installed. Installing needs TEBHOS Pro and counts toward the installed limit for the pack's type.

DELETE /packs/{pack_id}/install removes an installed pack and returns 204.