はじめに
昨日(2025/08/06)、Messaging APIの新機能が発表されました。
クーポンを作成して、公式アカウントからメッセージで配信できるというものです。
これはかなり使えそうなので、早速どのようにして実装するのか試してみます。
補足
クーポンの機能自体は以前から存在していました。
今まではLINE Official Account Managerからクーポンを作成することができました。

今回のアップデートによって、それがMessaging APIからも可能になったということです。
クーポンの詳細についてはこちら
事前準備
Messaging APIの機能を使うためには以下のような事前の準備が必要になります。
- アカウント、チャネルの準備
- チャネルアクセストークンの確認
- LINEユーザーIDの確認
私が書いた過去の記事の中で簡単にまとめていますので、できていない方はそちらを参考にしてください。
APIでできるようになったこと
概要
今回新たに追加されたのは以下の4つ + 1つです。
- 新規APIでの実行
- クーポンの作成
- クーポンの終了
- クーポンの一覧確認
- クーポンの詳細確認
- 既存APIでの実行
- クーポンの送信
クーポンの送信については、既存のメッセージ送信APIを使用します。
新たに追加されたcoupon
のメッセージタイプを使用して、メッセージ送信を行います。
それぞれの処理について、簡易的な実装を通して詳しく見ていきます。
なお、実装においてはNode.js、TypeScript、Expressを使用しています。
最後に完全な実装例を示します。
クーポンの作成
概要
クーポンを作成できます。また、実行結果としてクーポンIDを受け取ります。
クーポンIDはクーポンの終了、クーポンの詳細取得、クーポンの送信に使用します。
作成したクーポンは後述のAPIのほか、LINE Official Account Managerからも確認できます。
なお、作成したクーポンは修正ができないので、間違ってしまった場合はクーポンを終了させる必要があります。
実装例
app.get("/create-coupon", async (req, res) => {
try {
const requestBody = {
// クーポンのタイトル
title: "検証用クーポン",
// クーポンの獲得条件
acquisitionCondition: {
type: "normal",
},
// クーポンの使用上限
maxUseCountPerTicket: 1,
// クーポンの有効期間開始日時(UNIX時間)
startTimestamp: 0,
// クーポンの有効期間終了日時(UNIX時間)
endTimestamp: 1756566000,
// クーポンの有効期間に適用されるタイムゾーン
timezone: "ASIA_TOKYO",
// クーポンの種類、および詳細
reward: {
type: "free",
},
// クーポンをLINEヤフーサービスへの掲載かどうか
visibility: "UNLISTED",
};
const result = await axios.post(
`${API_DOMAIN}/v2/bot/coupon`,
requestBody,
{
headers: HEADERS,
}
);
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
エンドポイント
POST /v2/bot/coupon
リクエストボディ
必須項目についてのみ解説します。
詳細は以下の公式の解説を参照してください。
-
title
クーポンのタイトルです。この名前が各所に表示されます。 -
acquisitionCondition
クーポンの獲得条件です。(acquisitionは「取得、獲得」という意味)
値としてオブジェクトを設定します。-
type
normal
とlottery
のいずれかを指定可能です。
normal
は条件なし、lottery
は抽選での獲得となります。
クーポンの獲得条件として「友だち紹介」もありますが、APIでの作成はできません。
※lottery
を指定した場合には、当選確率と当選者数上限の指定が必要になります。
-
type
-
maxUseCountPerTicket
クーポンの使用可能上限です。1、または-1を指定できます。
1の場合は1回のみ、-1の場合は無制限となります。 -
startTimestamp
クーポンの有効期間の開始日時です。UNIX時間で指定する必要があります。 -
endTimestamp
クーポンの有効期間の終了日時です。こちらもUNIX時間で指定する必要があります。 -
timezone
startTimestamp、endTimestampの基準となるタイムゾーンです。
指定可能なタイムゾーンは指定されているので、詳細はドキュメントを確認してください。 -
reward
クーポンの種類と、どのようなクーポンかを表す詳細です。
値としてオブジェクトを設定します。-
type
cashBack
、discount
、free
、gift
、others
のいずれかを指定できます。
cashBack
、discount
の場合には更にその詳細を示すpriceInfo
という値(オブジェクト)の設定が必要になります。
-
type
実行結果確認
確認用APIを実行して、クーポンを作成します。
クーポンIDは後ほど使用するので控えておきます。
LINE Official Account Managerも確認してみます。

Messaging APIを使用してクーポンを作成できることが確認できました。
クーポンの終了
概要
クーポンは有効期間がすぎると自動的に終了しますが、APIを使用して任意のタイミングで終了させることもできます。
クーポンを終了させると、ユーザーが新規にクーポンを獲得できなくるほか、獲得済のクーポンの使用も不可となります。
実装例
app.get("/close-coupon", async (req, res) => {
try {
const couponId = "01K1ZVAQZ573BCDCH97HFBBYYN";
await axios.put(`${API_DOMAIN}/v2/bot/coupon/${couponId}/close`, null, {
headers: HEADERS,
});
res.send("coupon closed");
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
エンドポイント
PUT /v2/bot/coupon/{couponId}/close
実行結果確認
先ほど作成したクーポンを終了させてみます。
実装例のcouponId
に取得したクーポンIDを設定します。
LINE Official Account Managerから、終了できたかを確認してみます。

作成完了時に表示されていたクーポンは無くなっています。
次に「期限切れ・終了」タブを確認します。
先ほど作成したクーポンが終了に移動していることがわかります。
クーポンの一覧確認
概要
作成したクーポン、及び終了したクーポンの一覧を確認できます。
APIを使って処理したクーポンだけでなく、LINE Official Account Managerから操作したクーポンも表示されます。
APIでの作成はできませんが、下書きのクーポンも一覧として表示されます。
実装例
app.get("/list-coupon", async (req, res) => {
try {
const result = await axios.get(`${API_DOMAIN}/v2/bot/coupon`, {
headers: HEADERS,
params: {
// 取得するクーポンの最大件数
limit: null,
// 継続トークン
start: null,
// 取得するクーポンのステータス
status: null,
},
});
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
エンドポイント
GET /v2/bot/coupon
クエリパラメータ
クエリパラメータはいずれも省略可能です。
-
limit
一度のリクエストで取得するクーポンの最大数を指定します。
省略した場合のデフォルト値は20です。 -
start
継続トークンです。limitで指定した以上のクーポンが存在しており、一度のリクエストで取得しきれない場合に使用します。
limit以上のクーポンが存在する場合、レスポンスとしてクーポンの配列以外にこの継続トークンを受け取ります。
次のリクエストで継続トークンを設定することで、続きからクーポンを取得することができます。 -
status
取得対象とするクーポンのステータスです。
RUNNING
(有効期間前、または有効期間中)、DRAFT
(下書き)、CLOSED
(期限切れ、または終了済)のいずれかを指定できます。
複数指定することも可能です。
省略した場合はすべてのクーポンを取得します。
実行結果確認
クエリパラメータを何も指定していないので、すべてのクーポンを取得しています。
先ほど終了させた「検証用クーポン」が表示されています。
※「お試しクーポン」は別で試したものなので関係なし
では、上限を絞ってリストを取得するとどうなるか確認してみます。
先ほどの実装例のlimitを2にして実行します。

2件分のクーポンと、nextの値が取得できました。
このnextをクエリパラメータのstartに設定して再度取得処理を実行することで、続きからクーポンを取得できます。
なお、nextトークンの有効期間は24時間です。
通常はdo...while
などを使ってnextが取得できる限り取得処理を続けるループ処理を実装します。
クーポンの詳細確認
概要
クーポン作成時にLINE Official Account Managerで確認したクーポンの内容を、APIを使って取得できます。
APIで作成したものだけでなく、LINE Official Account Managerから作成したクーポンの詳細も確認可能です。
(つまりAPIからは作成不可の下書きクーポンの詳細もみられる。)
実装例
app.get("/detail-coupon", async (req, res) => {
try {
const couponId = "your coupon id";
const result = await axios.get(`${API_DOMAIN}/v2/bot/coupon/${couponId}`, {
headers: HEADERS,
});
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
エンドポイント
GET /v2/bot/coupon/{couponId}
実行結果確認
実装例のcouponId
に取得したクーポンIDを設定します。

クーポンの詳細情報を取得することができました。
レスポンスの内容は、クーポン作成時に指定できる内容とほとんど同じです。
status
(クーポンのステータス)、createdTimestamp
(クーポン作成日時)が詳細情報にしか無いデータとなります。
クーポンの送信
概要
クーポンは既存のメッセージ送信処理を使用して送ることができます。
今回はプッシュメッセージを使用してその結果を確認します。
実装例
app.get("/send-coupon", async (req, res) => {
try {
const couponId = "your coupon id";
const lineUserId = "your line user id";
const requestBody = {
to: lineUserId,
messages: [{ type: "coupon", couponId: couponId }],
};
await axios.post(`${API_DOMAIN}/v2/bot/message/push`, requestBody);
res.send("coupon sent");
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
送信するメッセージのtype
をcoupon
とし、couponId
を設定することでクーポンの送信ができます。
その他の設定内容は通常のメッセージ送信と同じです。
プッシュメッセージのほか、以下のメッセージでも送信ができます。
- マルチキャストメッセージ
- ブロードキャストメッセージ
- ナローキャストメッセージ
- 応答メッセージ
また、LINE Official Account Managerからも送信することができます。
実行結果確認
現在有効なクーポンが無いので、作成処理で適当なクーポンを生成しておきます。
lineUserIdにも適切なIDを設定して、確認用APIを実行すると、以下のようなクーポンが送信されてきました。

「クーポンを見る」をタップすると、クーポンの詳細を確認することができます。
その他できること、便利なこと
クーポンの分析
LINE Official Account Managerの分析タブ > ツール > クーポンから、クーポンがどのくらい使われているのかなどの情報を確認することができます。

クーポンを選択すると、画面下部に更に詳細な情報が表示されます。
作成、配信したクーポンがどれくらい有効活用されているのかなどの分析が可能になります。
テンプレートの使用
今回の処理では実施していませんが、クーポン作成時に画像を使用することもできます。
画像を使うがより訴求力を高めることができますが、一から作るのは大変です。
LINEではいくつかテンプレートを提供してくれているので、そちらを使って簡単に作成することができます。
これらをうまく使えば、リッチなクーポンをサクッと作成することができそうです。
まとめ
今回は新しく機能追加されたMessaging APIでのクーポン関連の処理について解説しました。
今まではLINE Official Account Managerからしか作成できなかったのが、ロジックを組んでできるようになったので、クーポンの幅がかなり広がったのではと思っています。
クーポンの発行タイミングや発行先も自由にコントロールできるので、LIFFアプリやLINEミニアプリと組み合わせてより効果的なサービス展開をすることができそうです。
ここ最近、ミニアプリへ広告掲載が可能になったり、複数のLIFFアプリが使用可能になったり、LINEミニアプリへの導線を強化する予定があったり、アップデートが目白押しで、開発関連が盛り上がってきているのを感じています。
最近なかなかキャッチアップができていなかったので、これを機に色々試してみようと思いました。
完全な実装
記事内で使用したコードの全量を記載しておきます。
参考にしてください。
実装例
```typescript:index.ts import express from "express"; import axios from "axios"; import dotenv from "dotenv";dotenv.config();
const PORT: number = Number(process.env.PORT) || 3000;
const API_DOMAIN = "https://api.line.me";
const HEADERS = {
"Content-Type": "application/json",
Authorization: Bearer ${process.env.LINE_ACCESS_TOKEN}
,
};
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.sendStatus(200);
});
// クーポン作成確認用API
app.get("/create-coupon", async (req, res) => {
try {
const requestBody = {
// クーポンのタイトル
title: "検証用クーポン",
// クーポンの獲得条件
acquisitionCondition: {
type: "normal",
},
// クーポンの使用上限
maxUseCountPerTicket: 1,
// クーポンの有効期間開始日時(UNIX時間)
startTimestamp: 0,
// クーポンの有効期間終了日時(UNIX時間)
endTimestamp: 1756566000,
// クーポンの有効期間に適用されるタイムゾーン
timezone: "ASIA_TOKYO",
// クーポンの種類、および詳細
reward: {
type: "free",
},
// クーポンをLINEヤフーサービスへの掲載かどうか
visibility: "UNLISTED",
};
const result = await axios.post(
${API_DOMAIN}/v2/bot/coupon
,
requestBody,
{
headers: HEADERS,
}
);
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
// クーポン終了確認用API
app.get("/close-coupon", async (req, res) => {
try {
const couponId = "your coupon id";
await axios.put(${API_DOMAIN}/v2/bot/coupon/${couponId}/close
, null, {
headers: HEADERS,
});
res.send("coupon closed");
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
// クーポン一覧確認用API
app.get("/list-coupon", async (req, res) => {
try {
const result = await axios.get(${API_DOMAIN}/v2/bot/coupon
, {
headers: HEADERS,
params: {
// 取得するクーポンの最大位数
limit: 2,
// 継続トークン
start: null,
// 取得するクーポンのステータス
status: null,
},
});
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
// クーポン詳細確認用API
app.get("/detail-coupon", async (req, res) => {
try {
const couponId = "your coupon id";
const result = await axios.get(${API_DOMAIN}/v2/bot/coupon/${couponId}
, {
headers: HEADERS,
});
res.json(result.data);
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
// クーポン送信確認用API
app.get("/send-coupon", async (req, res) => {
try {
const couponId = "your coupon id";
const lineUserId = "your line user id";
const requestBody = {
to: lineUserId,
messages: [{ type: "coupon", couponId: couponId }],
};
await axios.post(${API_DOMAIN}/v2/bot/message/push
, requestBody, {
headers: HEADERS,
});
res.send("coupon sent");
} catch (error) {
console.error(error);
res.status(500).json(error);
}
});
// リスナーの設定
app.listen(PORT, () => {
console.log(Example app listening at http://localhost:${PORT}
);
});
</details>