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
| Status | Meaning |
|---|---|
pending | Waiting for the customer to scan |
scanned | Scanned; waiting for them to confirm in the app |
confirmed | Confirmed in the app; the token is being issued |
authenticated | Done — token and user are in the payload |
cancelled | The customer declined in the app |
expired | The 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