UnifyPortでメッセージのリアクションを追加・削除する
UnifyPortでリアクションを追加するには、選択したアカウント、会話、メッセージ、元の送信者、emoji を指定して POST /v1/messages/reaction を呼び出します。接続アカウント自身の既存リアクションを削除する場合は、同じ対象に emoji: "" を送ります。重要なのは、sender_id がリアクション対象メッセージの投稿者を指すことです。操作担当者や、リアクションを書き換えたい任意の人物を指定するフィールドではありません。
要点
- 現在の送信操作は
whatsappとtelegramに対応します。リアクションイベントの受信とは別の機能です。 - 対象には選択した元メッセージを使います。リアクションイベント自体のメッセージIDではありません。
- 他の人のメッセージには
sender_idを明示します。省略時は接続アカウント自身が既定値になります。 - 追加と削除を明示的な操作にし、エラーのたびに切り替えるトグルにはしないでください。
リクエストの各フィールドを元メッセージに対応させる
リアクションAPIのリファレンスは、既存メッセージに対する操作を定義しています。絵文字を含むテキスト送信でも、引用返信用トークンを使う操作でもありません。
| リクエストフィールド | 保存済み message.received イベントからの取得元 |
|---|---|
account_id | トップレベルの account_id |
conversation_id | data.conversation.id |
message_id | data.message.id |
sender_id | 元メッセージ投稿者の data.sender.id |
emoji | 選択した絵文字。削除時は空文字列 |
グループでは会話IDがグループを、送信者IDが参加者を示します。個別チャットで似て見える場合があっても、会話IDを送信者IDで置き換えないでください。プロバイダーの識別子はそのまま保存し、表示名や電話番号から組み立てないようにします。
message.reaction イベントから操作を始める場合は、さらに区別が必要です。data.message.id はリアクション自体、data.message.target_message_id は元メッセージを指します。そのイベントの送信者はリアクションした人であり、元メッセージの投稿者とは限りません。まず保存済みの元メッセージを取得してください。リアクションwebhookの処理ガイドは受信と状態の反映を扱います。本記事は新しい送信リクエストを扱います。
追加・削除を明示したリクエストを作る
以下はリクエスト生成用のJavaScript例です。実行済みの結合テストや完全な受信サーバーではありません。入力には、署名検証と永続保存を済ませ、権限のある担当者が選択した元メッセージのイベントを使います。関数名とエラー文字列はアプリ側のコードです。
function buildReactionRequest(original, emoji) {
if (original.type !== 'message.received' ||
!['whatsapp', 'telegram'].includes(original.provider)) {
throw new Error('Select a supported original message');
}
const conversation = original.data?.conversation;
const message = original.data?.message;
const sender = original.data?.sender;
if (!original.account_id || !conversation?.id ||
!message?.id || !sender?.id) {
throw new Error('Original message context is incomplete');
}
if (typeof emoji !== 'string') {
throw new Error('Choose an emoji or an empty string');
}
return {
account_id: original.account_id,
conversation_id: conversation.id,
message_id: message.id,
sender_id: sender.id,
emoji
};
}
追加には "👍"、削除には "" を渡します。この関数が検証するのは対象の情報と値の型だけで、すべての絵文字が上流で受理されることは保証しません。削除値を null に変えたり、省略したり、未定義の remove フラグを追加したりしないでください。
生成したJSONはバックエンドから X-Api-Key 認証で POST /v1/messages/reaction に送信します。キーをブラウザーのコードに置かないでください。送信前にメッセージングアカウントと対象への操作権限を確認し、新着メッセージが届いても選択対象が変わらないよう固定します。
絵文字ではなく元メッセージを引用した文章で返したい場合は、別の WhatsApp引用返信フローを使います。不透明な reply_token はリアクションの識別子ではありません。
受信できることと送信できることは別
現在のプロバイダー別操作対応表と webhookイベント対応表は、異なる機能を示しています。
| プロバイダー | このAPIでリアクションを送信 | リアクションイベントのマッピング |
|---|---|---|
whatsapp | 対応 | 対応 |
telegram | 対応 | 対応 |
line | 非対応 | 対応 |
twitter、zalo、tiktok、whatsapp-protocol | 非対応 | 非対応 |
特にLINEを含む共有受信箱では、この違いが重要です。届いたリアクションを表示できても、送信ボタンを有効にできるわけではありません。表はアダプターの対応状況であり、すべてのアカウントや上流条件での利用を保証するものではありません。非対応の組み合わせは 501 unsupported_by_provider となり、繰り返しても対応機能は増えません。
UnifyPortは接続アカウント向けの非公式インターフェースです。Telegram公式の Bot APIには、ボット用の setMessageReaction が別に定義されています。ボットの身元で動作する必要がある場合は、そのネイティブな契約を使用してください。リクエスト形式や制限をUnifyPortにそのまま当てはめてはいけません。
意図、HTTP結果、観測状態を分ける
リファレンスの成功例は 200 OK と data.ok: true です。実際のHTTP結果と返された request_id を記録し、他の人がリアクションを見た証拠にはしないでください。
アプリ側では次を推奨します。
- 同じアカウント・対象メッセージの操作を直列化します。古い追加処理が新しい削除処理の後に実行されないよう管理します。
- 送信前に意図した絵文字を記録し、HTTP結果とは別に保存します。
react_message_failedはエラーと元の対象を調査します。タイムアウトは結果不明として保持し、自動で逆の操作を送らないでください。- 一致するイベントが届けば、冪等に観測状態を更新します。全リクエストにコールバックが届くことや到着順序は仮定しません。
受信側は signing_secret を設定し、配信リファレンスに従います。タイムスタンプ、ドット、生の本文を対象にHMAC-SHA256を検証し、時刻の鮮度を確認して永続保存後に応答します。webhookを受け取ったこと自体は、新たな送信操作の許可ではありません。
受け入れ確認とFAQ
有効化前に、受信した個別メッセージ、他のグループ参加者の投稿、自分のアカウントの投稿、空文字列による削除、非対応プロバイダー、通信結果不明を試してください。新着によって選択対象が変わらないことも確認します。これは推奨テスト項目であり、実施済みの結果ではありません。
sender_idでリアクションする人を指定できますか?
いいえ。指定するのは対象メッセージの投稿者です。操作するのは接続アカウントであり、別の人物としてリアクションするためのフィールドではありません。
同じ絵文字をもう一度送れば削除されますか?
文書化された削除方法は emoji: "" です。トグル動作を前提にしないでください。
LINEのリアクションを受信できるのに送信できないのはなぜですか?
受信イベント解析と送信操作は別の対応表を持つためです。現在の送信リアクション操作はTelegramとWhatsAppに対応しています。
次のステップと参照元
リアクションAPIに沿って対象チェックを実装してから、受信箱に操作ボタンを追加してください。証拠が不足する場合は未確定の状態を残し、未文書化の照会APIや再配信保証を想定しないでください。
確認日:2026-10-16。
メッセージ連携を安定したプロダクトパイプラインへ。
まずは 1 つの API で送信を始め、標準イベントですべての inbound メッセージを業務システムへ戻しましょう。