LINE MINI App service messages are not ordinary push notifications.
They use a user-bound, action-specific notification token that changes after every successful send. If your application keeps using the original token, later reminders can fail even when the template and channel credentials are correct.
This guide explains the complete flow: issuing the token, sending an approved template, saving the renewed token, and handling retries safely.
Prerequisites
Before implementing the API flow, make sure:
- Your LINE MINI App is verified for production use.
- The service-message template has been approved.
- The message confirms or responds to an action completed by the user.
- The channel access token is stored only on your server.
Unverified MINI Apps can test service messages in a Developing channel, but they cannot send production service messages from a Published channel.
Understand the three tokens
Three different credentials are involved in the flow.
| Credential | Purpose | Important lifecycle rule |
|---|---|---|
| LIFF access token | Identifies the current LINE user | Exchange it shortly after the user completes the action |
| Channel access token | Authorizes server-side LINE API calls | Never expose it to the browser |
| Service notification token | Authorizes notifications for one user action | Replace it after every successful send |
A LIFF access token can be obtained in the MINI App with:
const liffAccessToken = liff.getAccessToken();
Send this value to your backend over HTTPS after the reservation, purchase, check-in, or other approved action succeeds.
Do not write the LIFF access token or service notification token to application logs.
Step 1: Issue a service notification token
Your backend exchanges the LIFF access token for a service notification token:
curl -X POST https://api.line.me/message/v3/notifier/token \
-H "Authorization: Bearer ${LINE_CHANNEL_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"liffAccessToken\":\"${LIFF_ACCESS_TOKEN}\"}"
A successful response looks like this:
{
"notificationToken": "34c11a03-b726-49e3-8ce0-949387a9f531",
"expiresIn": 31536000,
"remainingCount": 5,
"sessionId": "xD06R2407210008"
}
Store the following values:
notificationTokenexpiresInremainingCountsessionId- Your internal order, reservation, or action ID
The token is bound to one user and one action session. It is not a reusable user identifier.
One LIFF access token can issue only one service notification token, so perform the exchange once and persist the result.
Step 2: Send an approved template
Use the service notification token with the official send endpoint:
curl -X POST "https://api.line.me/message/v3/notifier/send?target=service" \
-H "Authorization: Bearer ${LINE_CHANNEL_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"templateName": "thankyou_msg_en",
"params": {
"date": "2026-07-21",
"username": "Brown & Cony"
},
"notificationToken": "34c11a03-b726-49e3-8ce0-949387a9f531"
}'
A few details are easy to miss:
-
target=serviceis required. -
templateNamemust exactly match an approved template. - The keys inside
paramsmust match the variables defined by that template. - If the template has no variables,
paramsis still required and should be{}.
Step 3: Save the renewed token
This is the most important implementation rule:
After every successful send, replace the stored notification token with the new token returned by LINE.
The response contains an updated token and counters:
{
"notificationToken": "renewed-token-value",
"expiresIn": 31536000,
"remainingCount": 4,
"sessionId": "xD06R2407210008"
}
Do not schedule another reminder until the renewed token has been saved successfully.
A safe sequence is:
- Lock or version the action record.
- Send the approved service-message template.
- Receive the successful response.
- Replace the stored notification token.
- Update
remainingCountandexpiresIn. - Commit the database transaction.
- Schedule the next reminder.
This prevents two workers from sending with the same token concurrently.
Example storage model
A minimal action record could look like this:
{
"actionId": "order_12345",
"sessionId": "xD06R2407210008",
"notificationToken": "encrypted-token-value",
"remainingCount": 4,
"expiresAt": "2027-07-21T10:00:00Z",
"version": 2
}
Encrypt the notification token at rest and use the version field—or an equivalent database lock—to prevent concurrent updates.
Handling errors and retries
Treat notification tokens as rotating credentials, not permanent addresses.
HTTP 400
Check:
- Request body format
- Template name
- Template variables
- Recipient state
- Current notification token
Do not repeatedly retry the same invalid request.
HTTP 401
Refresh or verify the server-side channel credential.
If the LIFF access token or service notification token is invalid, start a new eligible user-action flow instead of replaying it indefinitely.
HTTP 403
Confirm:
- The channel is authorized for the operation
- The MINI App has the required status
- The template exists and is approved
Concurrent sends
Never allow two workers to spend the same notification token simultaneously. Use a database lock, compare-and-swap update, or version check around the send operation.
Message limits
A newly issued token is normally valid for up to one year and starts with a limited number of sends.
The reviewed use case may have a different limit, so your application should always treat the latest remainingCount returned by LINE as the runtime source of truth.
Service messages must remain tied to the original user action. They are designed for cases such as:
- Reservation confirmations
- Order results
- Shipping updates
- Reminders related to the original action
They are not intended for:
- Advertising
- Coupons
- Product promotions
- General announcements
- Free-form customer support conversations
Implementation checklist
Before releasing the integration, verify:
- [ ] The LIFF access token is collected after an eligible user action
- [ ] Token exchange happens on the server
- [ ] Channel credentials are never exposed to the browser
- [ ] Tokens are not written to application logs
- [ ] The exact approved template name is used
- [ ]
target=serviceis included - [ ] The renewed notification token is saved after every send
- [ ]
remainingCountis checked before scheduling another message - [ ] Concurrent sends are prevented
- [ ] Failed requests use bounded, reason-specific retry logic
Conclusion
The API calls themselves are straightforward. The difficult part is managing the notification token correctly.
Think of it as a rotating credential associated with one user action:
- Obtain a fresh LIFF access token.
- Exchange it on the server.
- Send an approved template.
- Save the renewed notification token.
- Use the latest
remainingCountfor future decisions.
If you get the rotation and concurrency rules right, follow-up service messages become much more predictable.
Sources
Originally published on UnifyPort.
This article was prepared with AI assistance for language and structure, then technically reviewed and verified by the author.
Top comments (0)