DEV Community

unifyport for UnifyPort

Posted on • Originally published at unifyport.ai

How LINE MINI App Service Notification Tokens Work (and Why You Must Rotate Them)

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();
Enter fullscreen mode Exit fullscreen mode

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}\"}"
Enter fullscreen mode Exit fullscreen mode

A successful response looks like this:

{
  "notificationToken": "34c11a03-b726-49e3-8ce0-949387a9f531",
  "expiresIn": 31536000,
  "remainingCount": 5,
  "sessionId": "xD06R2407210008"
}
Enter fullscreen mode Exit fullscreen mode

Store the following values:

  • notificationToken
  • expiresIn
  • remainingCount
  • sessionId
  • 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"
  }'
Enter fullscreen mode Exit fullscreen mode

A few details are easy to miss:

  • target=service is required.
  • templateName must exactly match an approved template.
  • The keys inside params must match the variables defined by that template.
  • If the template has no variables, params is 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"
}
Enter fullscreen mode Exit fullscreen mode

Do not schedule another reminder until the renewed token has been saved successfully.

A safe sequence is:

  1. Lock or version the action record.
  2. Send the approved service-message template.
  3. Receive the successful response.
  4. Replace the stored notification token.
  5. Update remainingCount and expiresIn.
  6. Commit the database transaction.
  7. 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
}
Enter fullscreen mode Exit fullscreen mode

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=service is included
  • [ ] The renewed notification token is saved after every send
  • [ ] remainingCount is 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:

  1. Obtain a fresh LIFF access token.
  2. Exchange it on the server.
  3. Send an approved template.
  4. Save the renewed notification token.
  5. Use the latest remainingCount for 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)