Loyalty.lt
SDKsJavaScript

QR Login

Sign a customer in by having them scan a QR code

QR Login

QR login signs a customer in on a screen with no keyboard — a POS terminal or a checkout page. You generate a session, render the QR code, and the customer confirms in the Loyalty.lt mobile app. You get back a JWT for that customer.

Sessions expire after 5 minutes.

Subscribe to the result

subscribeToQrLogin opens the session's realtime channel for you and fires the callback the moment the status changes. This is the way to do it.

const session = await sdk.generateQrLogin('Till 3', shopId);

// Render session.qr_code — for example with qrcode.react
// <QRCodeSVG value={session.qr_code} size={256} />

const subscription = await sdk.subscribeToQrLogin(session.session_id, ({ data }) => {
  if (data.status === 'scanned') {
    console.log('Customer scanned — waiting for confirmation');
  }
  if (data.status === 'authenticated') {
    console.log('Token:', data.token);
    console.log('User:', data.user);
  }
});

Call subscription.unsubscribe() and sdk.disconnectWebSocket() when the screen unmounts.

Fallback: polling

Only if your environment cannot hold a WebSocket open. It is slower for the customer standing at the till and costs a request per second per session.

const session = await sdk.generateQrLogin('Till 3', shopId);

const timer = setInterval(async () => {
  const status = await sdk.pollQrLoginStatus(session.session_id);

  if (status.status === 'authenticated') {
    clearInterval(timer);
    console.log(status.token, status.user);
  }
  if (status.status === 'expired') {
    clearInterval(timer);
    // generate a new session
  }
}, 1000);

Statuses

StatusMeaning
pendingWaiting for the customer to scan
scannedScanned; waiting for them to confirm in the app
confirmedConfirmed in the app; the token is being issued
authenticatedDone — token and user are in the payload
cancelledThe customer declined in the app
expiredThe 5-minute window elapsed; generate a new session

If the customer has no app

Text them the download link rather than leaving them stuck:

await sdk.sendAppLink('+37060000001', shopId);

Using the token

The token identifies that one customer. Send it as Authorization: Bearer <token> on customer-scoped endpoints such as GET /{locale}/shop/auth/me.

The Shop API has no refresh or logout endpoint — when a token expires, run QR login again. See Authentication.

Next

<QRLogin /> does all of the above for you

Every channel, event and payload — including the live basket the SDK does not wrap

On this page