Sending LINE Messages
LINE has become one of the most popular chat channels between businesses and customers in Asia, especially in Japan, Taiwan, and Thailand. LINE's 2019 strategy, "Life on LINE," depicts a user's daily life surrounded with LINE's service, e.g., LINE Login, LINE Pay, LINE Music, LINE Today, LINE Things, LINE Spot. The completeness of the LINE's ecosystem offers more dynamic, integrated, online to offline possibilities of LINE Bots.
LINE Bots can be invited into a group, or focus on 1:1 communication. LINE Bots for group chat benefit from organic growth. Once a bot joined a group, it gains more exposure.
Reply API & Push API
Due to cost concerns, one thing developers should clearly understand before sending any messages is the difference between Reply API
and Push API.
Push API
allows developers to send messages directly to users anytime. However, it is only free in development. In production, you may refer to LINE Official Account Subscription Plans to check out the messaging fee of your official account.Using
Reply API
is free. But bots can only reply once to a user who interacted with your LINE official account. For each bot reply, you can send up to 5Message Objects
(See LINE's official document, "Sending reply messages"). If you attempt to reply more than 5Message Objects
, you will see an error in console.
Note:
- It's a bit tricky to count the number of
Message Objects.
For example, each function call ofSending Message,
Sending Text Message,
orSending Template Messages
is calculated as oneMessage Object.
, while the final attachedQuick Reply
doesn't count as aMessage Object.
Sending Messages
Bottender aims to support every feature of each chat channel. In the code below, you can see the most primitive way to send any LINE messages by Bottender.
await context.send([
{
type: 'text',
text: 'hello',
},
]);
Bottender also cares about "Developer Experience." In the following section, you can see a full set of syntactic sugar to make codes in Bottender much readable and expressive.
Sending Text Messages
Text message
is the most frequent and common message types among all chat channels. It also offers a minimal format while carrying out dynamic data, e.g., stock price and weather info.
Plain Text
The following example shows how to reply with plain text.
async function SendHi(context) {
await context.sendText('Hi!');
}
Note: For more info, please refer to LINE's official doc,
Text Message
Text with LINE emoji
You can include LINE's original emoji (usually involves LINE Friends) in text messages using character code. You can find the list of LINE emoji in emoji list.
async function SendHi(context) {
await context.sendText(`${String.fromCodePoint(0x100084)} Hi!`);
}
Sending Multiple Messages
Bottender collects all sending messages in a single request. You can see two different approaches below.
await context.send([
{
type: 'text',
text: 'hello',
},
{
type: 'text',
text: 'world',
},
]);
or
await context.sendText('hello');
await context.sendText('world');
Sending Rich Media Messages
Rich Media Messages
of LINE consist of stickers, images, videos, audios, locations, and imagemaps. Rich Media Messages
is useful when your priority is to catch the user's attention, e.g., limited promotion. Plus, it is also handy to create an immersive experience, e.g., telling a story.
Sticker
By Stickers,
LINE creates a versatile, communicative language. Stickers
make your bot expressive and engaging. To send a sticker, you need to indicate the package ID and sticker ID of the sticker.
await context.sendSticker({
packageId: '1',
stickerId: '1',
});
Note:
- You can only send LINE's original
Stickers.
You can find the sticker's package ID and sticker ID in the sticker list.- For more info, please refer to LINE's official doc,
Sticker Message
Image
To send an Image,
you need to prepare URLs of the original image and a smaller preview image. Users can see the preview image in the chat. When the user clicked the preview image, s/he can see the original image.
If you want to set up a call to action on the image, you may refer to Imagemaps.
await context.sendImage({
originalContentUrl: 'https://example.com/image.jpg',
previewImageUrl: 'https://example.com/preview.jpg',
});
Note:
- The URLs must use HTTPS over TLS 1.2 or later.
- For more info, please refer to LINE's official doc,
Image Message
Video
To send a Video,
you need to prepare the URL of the video file and the URL of a preview image. The user can play the video by tapping on the preview image.
await context.sendVideo({
originalContentUrl: 'https://example.com/video.mp4',
previewImageUrl: 'https://example.com/preview.jpg',
});
Note:
- The URLs must use HTTPS over TLS 1.2 or later.
- For more info, please refer to LINE's official doc,
Video Message
Audio
To send an Audio
file, you need to prepare the URL of the file and the duration of the audio.
await context.sendAudio({
originalContentUrl: 'https://example.com/audio.mp3',
duration: 240000,
});
Note:
- The URLs must use HTTPS over TLS 1.2 or later.
- For more info, please refer to LINE's official doc,
Audio Message
Location
To send your location information to users, you have to prepare a title, address, and latitude and longitude.
await context.sendLocation({
title: 'my location',
address: '〒150-0002 東京都渋谷区渋谷2丁目21−1',
latitude: 35.65910807942215,
longitude: 139.70372892916203,
});
Note:
- The URLs must use HTTPS over TLS 1.2 or later.
- For more info, please refer to LINE's official doc,
Location Message
Imagemap
Imagemap
offers very flexible and interactive usage. It is an image with multiple tappable areas. When a user taps one of these areas, the user can link to a webpage or send a message on their behalf.
const imagemap = {
baseUrl: 'https://example.com/bot/images/rm001',
baseSize: {
height: 1040,
width: 1040,
},
actions: [
{
type: 'uri',
linkUri: 'https://example.com/',
area: {
x: 0,
y: 0,
width: 520,
height: 1040,
},
},
{
type: 'message',
text: 'hello',
area: {
x: 520,
y: 0,
width: 520,
height: 1040,
},
},
],
};
const altText = 'this is an imagemap';
await context.sendImagemap(altText, imagemap);
Note: For more info, please refer to LINE's official doc,
Imagemap Message
Sending Template Messages
Template message
is an interactive gallery composed of image, video, title, subtitle, and buttons.
Template message
is the key to offer rich media interaction. It is usually used in the scenario of display multiple choices and next actions to the user, e.g., applying coupons, booking a room, making a reservation.
Note: Compared with
Template Message,
we highly depend onFlex Message
once it is available. There are two main reasons:
Flex Message
supports both desktop and mobile devices, whileTemplate Message
only supports mobile devices.Flex Message
is an HTML-like chat UI, which creates a better, engaging user experience.
const template = {
type: 'buttons',
thumbnailImageUrl: 'https://example.com/bot/images/image.jpg',
title: 'Menu',
text: 'Please select',
actions: [
{
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=123',
},
{
type: 'postback',
label: 'Add to cart',
data: 'action=add&itemid=123',
},
{
type: 'uri',
label: 'View detail',
uri: 'http://example.com/page/123',
},
],
};
const altText = 'this is a template';
await context.sendTemplate(altText, template);
Confirm Template
A Confirm Template
is designed for confirmation.
const template = {
text: 'Are you sure?',
actions: [
{
type: 'message',
label: 'Yes',
text: 'yes',
},
{
type: 'message',
label: 'No',
text: 'no',
},
],
};
const altText = 'this is a confirm template'
await context.sendConfirmTemplate(, template);
Note: For more info, please refer to LINE's official doc,
Confirm Template
Buttons Template
A Buttons Template
has an image, title, text, and multiple action buttons.
const template = {
thumbnailImageUrl: 'https://example.com/bot/images/image.jpg',
title: 'Menu',
text: 'Please select',
actions: [
{
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=123',
},
{
type: 'postback',
label: 'Add to cart',
data: 'action=add&itemid=123',
},
{
type: 'uri',
label: 'View detail',
uri: 'http://example.com/page/123',
},
],
};
const altText = 'this is a button template';
await context.sendButtonTemplate(altText, template);
Note:
- Depending on the character width, the message text may not fully be displayed due to the height limitation of the text area.
- For more info, please refer to LINE's official doc,
Buttons Template
Carousel Template
A Carousel Template
is an upgraded version of Buttons Template.
For each Buttons Template,
you can have an image, title, text, and multiple action buttons.
You can have up to 10 Buttons Template
in a row to compose a Carousel Template.
const template = [
{
thumbnailImageUrl: 'https://example.com/bot/images/item1.jpg',
title: 'this is menu',
text: 'description',
actions: [
{
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=111',
},
{
type: 'postback',
label: 'Add to cart',
data: 'action=add&itemid=111',
},
{
type: 'uri',
label: 'View detail',
uri: 'http://example.com/page/111',
},
],
},
{
thumbnailImageUrl: 'https://example.com/bot/images/item2.jpg',
title: 'this is menu',
text: 'description',
actions: [
{
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=222',
},
{
type: 'postback',
label: 'Add to cart',
data: 'action=add&itemid=222',
},
{
type: 'uri',
label: 'View detail',
uri: 'http://example.com/page/222',
},
],
},
];
const altText = 'this is a carousel template';
await context.sendCarouselTemplate(altText, template);
Note:
- Depending on the character width, the message text may not fully be displayed due to the height limitation of the text area.
- You have to keep the number of actions consistent for all columns.
- For more info, please refer to LINE's official doc,
Carousel Template
Image Carousel Template
Image Carousel Template
has multiple images that can be cycled like a carousel. Users can scroll the images horizontally to browse possible choices. Without the bother of buttons, it helps your user focus on the product images.
const template = [
{
imageUrl: 'https://example.com/bot/images/item1.jpg',
action: {
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=111',
},
},
{
imageUrl: 'https://example.com/bot/images/item2.jpg',
action: {
type: 'message',
label: 'Yes',
text: 'yes',
},
},
{
imageUrl: 'https://example.com/bot/images/item3.jpg',
action: {
type: 'uri',
label: 'View detail',
uri: 'http://example.com/page/222',
},
},
];
const altText = 'this is a image carousel template';
await context.sendImageCarouselTemplate(altText, template);
Note: For more info, please refer to LINE's official doc,
Image Carousel Template
Sending Flex Messages
Since we love Flex Message
and inspired by its flexiblity and interactive, we wrote a seperate doc, Flex Message
.
Sending with Quick Replies
We would recommend you to treat Quick Reply
as an alternative to user text input.
When a user receives a message that contains Quick Reply Buttons
from a LINE official account, those buttons appear at the bottom of the chat screen. The user can tap one of the buttons as a reply.
A Quick Reply
consists of up to 13 Quick Reply Buttons.
When the user taps a Quick Reply Button,
the Quick Reply
dismissed. Then, the title of the tapped button posts to the conversation as a response. Meanwhile, the user triggers the action bound with the Quick Reply Button.
Quick Reply
can be used in a 1:1 chat with a LINE official account, a group, and a room.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'cameraRoll',
label: 'Send photo',
},
},
{
type: 'action',
action: {
type: 'camera',
label: 'Open camera',
},
},
],
};
Note: For more info, please refer to LINE's official doc,
Using Quick Reply
Sending Quick Reply
Since Quick Reply
works as an alternative of user input, you have to send Quick Reply
as an attachment of other messages, e.g., Text Message,
Template Message,
or Flex.
Sending Quick Reply with Message
await context.send([
{
type: 'text',
text: 'hello',
quickReply,
},
]);
Sending Quick Reply with Text Message
await context.sendText('hello', { quickReply });
Sending Quick Reply with Template Message
await context.sendTemplate(altText, template, { quickReply });
Sending Quick Reply with Buttons Template Message
await context.sendButtonTemplate(altText, template, { quickReply });
Sending Quick Reply with Confirm Template Message
await context.sendConfirmTemplate(altText, template, { quickReply });
Sending Quick Reply with Carousel Template Message
await context.sendCarouselTemplate(altText, template, { quickReply });
Sending Quick Reply with Flex Message
await context.sendFlex(altText, contents, { quickReply });
In the following sections, you can see various types of Quick Reply.
Text Quick Reply
When this action is tapped, the string in the text property is sent as a message from the user.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'message',
label: 'Yes',
text: 'Yes',
},
},
],
};
Note: For more info, please refer to LINE's official doc,
Message Actions
Postback Quick Replay
When the action is tapped, a postback event is returned via webhook with the specified string in the data property.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'postback',
label: 'Buy',
data: 'action=buy&itemid=111',
text: 'Buy',
},
},
],
};
Note: For more info, please refer to LINE's official doc,
Postback Actions
URI Quick Reply
The URI opened when the action is performed. The available schemes for URI are http
, https,
line,
and tel.
For the LINE URL scheme, you can trigger the following actions:
- Opening the camera and camera roll
- Opening the location screen
- Sharing your LINE official account
- Opening your LINE official account's Timeline and account page
- Sending text messages
- Opening profile information
- Opening common LINE screens
- Opening LINE settings screens
- Opening the Sticker Shop
- Opening the Theme Shop
- Making phone calls with LINE Out
- Opening a LIFF app
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'uri',
label: 'View details',
uri: 'http://example.com/page/222',
altUri: {
desktop: 'http://example.com/pc/page/222',
},
},
},
],
};
Note:
- The altUri.desktop property is supported only when you set URI actions in Flex Messages.
- For more information about the LINE URL scheme, see Using the
LINE URL Scheme
.- For more info, please refer to LINE's official doc,
URI Actions
Datetime Picker Quick Reply
When a control associated with this action is tapped, a postback event is returned via webhook with the date and time selected by the user from the date and time selection dialog. The Datetime Picker
action does not support time zones.
There are three different modes:
- date: Pick a date
- time: Pick time
- datetime: Pick date and time
const quickReply = {
items: [
{
type: 'datetimepicker',
label: 'Select date',
data: 'storeId=12345',
mode: 'datetime',
initial: '2017-12-25t00:00',
max: '2018-01-24t23:59',
min: '2017-12-25t00:00',
},
],
};
Note:
- The datetime picker action is only supported on versions equal to or later than LINE 7.9.0 for iOS and LINE 7.12.0 for Android.
- For more info, please refer to LINE's official doc,
Datatime Picker Actions
.
Camera Quick Reply
This action can be configured only with quick reply buttons. When a button associated with this action is tapped, the camera screen in LINE is opened.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'camera',
label: 'Camera',
},
},
],
};
Note:
- For more info, please refer to LINE's official doc,
Camera Actions
Camera Roll Quick Reply
This action can be configured only with quick reply buttons. When a button associated with this action is tapped, the camera roll screen in LINE is opened.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'cameraRoll',
label: 'Camera roll',
},
},
],
};
Note:
- For more info, please refer to LINE's official doc,
Camera Roll Actions
Location Quick Reply
This action can be configured only with quick reply buttons. When a button associated with this action is tapped, the location screen in LINE is opened.
const quickReply = {
items: [
{
type: 'action',
action: {
type: 'location',
label: 'Location',
},
},
],
};
Note:
- For more info, please refer to LINE's official doc,
Location Action
Thinking in Bottender: Send Messages, Reply Messages & Push Messages
Bottender aims to offer better abstract concepts for multiple chat channels support. Apart from LINE's unique Reply API
and Push API,
Bottender offers Send API
as a configurable middleware.
For example, If you don't want to pay extra fee for bot response, in bottender.config.js,
you can config your Send API
sending messages by Reply API.
However, if you want to send more than 5 Message Objects
in one reply, you can also ask Bottender use Push API
to send every message by Send API.
// bottender.config.js
module.exports = {
channels: {
line: {
enabled: true,
// sendMethod can be either "push" or "reply"
sendMethod: 'reply',
accessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN,
channelSecret: process.env.LINE_CHANNEL_SECRET,
},
},
};
Send Messages
Bottender offers the following Send API:
- send
- sendText
- sendSticker
- sendImage
- sendAudio
- sendVideo
- sendLocation
- sendImagemap
- sendFlex
- sendTemplate
- sendBottonTemplate
- sendConfirmTemplate
- sendCarouselTemplate
- sendImageCarouselTemplate
Reply Messages
If you are confident that all you need is Reply API,
you can use the following Reply API.
Bottender helps you manage the reply token, so you don't have to manage it by yourself.
Bottender offers the following Reply API:
- reply
- replyText
- replySticker
- replyImage
- replyAudio
- replyVideo
- replyLocation
- replyImagemap
- replyFlex
- replyTemplate
- replyBottonTemplate
- replyConfirmTemplate
- replyCarouselTemplate
- replyImageCarouselTemplate
Note: For sample code, please refer to Bottender's API doc, Reply API
Push Messages
If messaging cost is not an issue to you, you may focus on Push API.
Bottender offers the following Push API:
- push
- pushText
- pushSticker
- pushImage
- pushAudio
- pushVideo
- pushLocation
- pushImagemap
- pushFlex
- pushTemplate
- pushBottonTemplate
- pushConfirmTemplate
- pushCarouselTemplate
- pushImageCarouselTemplate
Note: For sample code, please refer to Bottender's API doc, Push API
Rate Limits
Just like many chat channels, LINE has rate limits for each endpoint. If you continue to send requests exceeding the rate limit for an extended period, your bot might stop responding. It is because LINE blocks incoming requests to your bot.
You have to take care Rate Limits
if you attempt to build a campaign bot with massive sudden traffic, e.g., super discount for Black Friday.
Send API
For Send API,
you have to follow the below Rate Limits
:
100,000 requests per minute
1,700 requests per second
Note: For more info, please refer to LINE's API doc, Rate Limits