Reaction suggestions
Suggest the emoji people react with, from the text of a message.
On this page
Reaction suggestions read a message and return the emoji people would react with. Show them in a hover bar or a quick-reaction row, so the right reaction is one click away. They are part of every plan.
How it works
You send the message text to POST /v1/suggest-reactions. The API reads the first 256 characters, ranks emoji with intent cues, the dictionary and meaning search together, and answers in the same shape as search. Each call counts as one Worker call, except when the embedding model is unavailable.
Call it
From a browser or an extension, use a publishable key in the URL. From a server or a bot, use a secret key in the Authorization header.
const DEFAULT_REACTIONS = ["👍", "❤️", "😂", "🎉"];
export async function suggestReactions(text: string): Promise<string[]> {
try {
const url = "https://api.emojisense.com/v1/suggest-reactions?key=pk_live_…";
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text, locale: "en", limit: 5 }),
});
if (!response.ok) return DEFAULT_REACTIONS;
const { results } = await response.json();
if (results.length === 0) return DEFAULT_REACTIONS;
return results.map((result) => result.emoji);
} catch {
return DEFAULT_REACTIONS; // offline: keep the usual reactions
}
}// A bot or back end: use a secret key, never in a browser.
const response = await fetch("https://api.emojisense.com/v1/suggest-reactions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.EMOJISENSE_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text: message.text, locale: "en", limit: 3 }),
});curl -X POST "https://api.emojisense.com/v1/suggest-reactions" \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"text":"we did it, the launch went perfectly","locale":"en","limit":5}'Request
| Field | Default | Notes |
|---|---|---|
text | — | Required. Whitespace is collapsed, then the text is cut to 256 characters. |
locale | en | Language of the dictionary part: one of en, ar, bn, es, fr, hi, id, pt, ru, tr, zh, or a BCP 47 tag of one, such as pt-BR. Any other language answers 400. Meaning search is multilingual either way. |
limit | 8 | Number of results, 1–50. |
tenant | — | Optional, also as a query parameter. Your id for one of your customers: that tenant’s custom emoji are suggested too. At most 128 characters. |
Response
This is the real answer of the API for “we did it, the launch went perfectly”, captured on 2026-10-02:
{
"query": "we did it the launch went perfectly",
"results": [
{ "emoji": "🙌", "id": "1F64C", "score": 0.933, "source": "alias" },
{ "emoji": "🎉", "id": "1F389", "score": 0.9, "source": "alias" },
{ "emoji": "👏", "id": "1F44F", "score": 0.686, "source": "alias" },
{ "emoji": "🚀", "id": "1F680", "score": 0.673, "source": "alias" },
{ "emoji": "🥳", "id": "1F973", "score": 0.645, "source": "alias" }
],
"packVersion": "0.1.0",
"model": "bge-m3@1024",
"cached": false,
"degraded": false,
"overLimit": false,
"aliasLocale": "en"
}“We did it” is a celebration cue, so the reactions people use for good news lead the list. Intent cues and dictionary matches have "source": "alias". A result that the message embedding found has "source": "semantic", as for messages without a clear cue. The query field echoes the normalized text in the response only. It is not stored. aliasLocale names the language whose dictionary ranked the text.
Fallbacks
- Over the plan limit, the answer has
"overLimit": trueand dictionary results only. - Workers AI unavailable:
"degraded": trueand dictionary results only. - Offline or an HTTP error: keep your usual reactions, as in the browser example.
The status codes are in the HTTP API reference.
For AI assistants
The MCP server has a suggest_reactions tool. It works offline with the bundled packs and calls this endpoint when you give it a secret key.