Pay by link (in store)
Send a payment link to a customer who is in your store but prefers to pay on their own device.
Pay by link in a physical store means your staff generates a short URL or QR code at the counter — the customer scans it and completes checkout on their own phone. No card is handed over, no terminal is touched. This flow is useful when a customer forgot their wallet, wants to use a buy-now-pay-later option, or prefers a digital payment method your terminal does not support (Apple Pay via browser, a local wallet, stablecoins). It is distinct from remote pay-by-link, where a link is sent to someone who is not present — see Payment links for that core feature.
Create a link at the counterAsk
Your POS triggers a call to your backend when the cashier initiates a link payment. Your server calls vinr.paymentLinks.create with a short expiry and metadata that ties the link to the physical transaction context. VINR returns a qrCodeUrl (a PNG) that you display on the terminal idle screen or print on a slip.
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const link = await vinr.paymentLinks.create({
amount: 7500,
currency: 'EUR',
expiresAfter: 600,
metadata: {
inStore: true,
terminalId: 'term_01HZ5QXYZ',
staffId: 'staff_9A3BK',
},
});
console.log(link.url); // "https://pay.vinr.com/l/AbCd12"
console.log(link.qrCodeUrl); // PNG render — pass to terminal screen or printerThe returned link.qrCodeUrl is a ready-to-render PNG. Display it full-screen on the terminal or customer-facing display while the customer has their phone ready.
Customer scans and paysAsk
The customer points their phone camera at the QR code. VINR Checkout opens in their browser — no app install required. They can pay with any method enabled on your account: credit or debit cards, BNPL providers, digital wallets (Apple Pay, Google Pay), saved cards, or stablecoins. Your server receives a payment.completed webhook event when the transaction settles.
app.post('/webhooks/vinr', express.raw({ type: 'application/json' }), (req, res) => {
const event = vinr.webhooks.constructEvent(
req.body,
req.headers['vinr-signature'] as string,
process.env.VINR_WEBHOOK_SECRET!,
);
if (event.type === 'payment.completed') {
const payment = event.data;
if (payment.metadata?.inStore) {
await pos.markOrderPaid(payment.metadata.terminalId, payment.id);
}
}
res.sendStatus(200);
});The metadata.terminalId you passed at link creation comes back on the payment object, so you can reconcile the digital payment against the open order on that lane without any additional state.
Fallback if the link expiresAsk
After the configured timeout the link becomes inactive and VINR Checkout shows an expiry message to the customer. At that point the staff member can generate a fresh link or fall back to the standard terminal flow.
Always set a short expiresAfter for in-store links — 600 seconds (10 minutes) is the recommended default. A link with no expiry, or a long one, can be forwarded and reused by anyone who receives it after the customer leaves the store.
To regenerate a link, call vinr.paymentLinks.create again with the same metadata. The previous link is already inactive so there is no risk of double-collection.
MOTO pay by linkAsk
Mail Order / Telephone Order (MOTO) is a related pattern for phone orders. A staff member takes an order over the phone, creates a payment link, and sends it to the customer by SMS or email. The customer pays on their own device at their convenience — the staff member never keys card details into a terminal or dashboard, which keeps your PCI scope clean.
const motoLink = await vinr.paymentLinks.create({
amount: 12000,
currency: 'GBP',
expiresAfter: 86400,
metadata: {
channel: 'moto',
orderId: 'order_7812',
staffId: 'staff_9A3BK',
},
});
await sms.send({
to: customerPhone,
body: `Your VINR payment link: ${motoLink.url}`,
});Compare this approach to card-present MOTO (keying card numbers via the terminal) in In-person features. Pay-by-link MOTO produces a cleaner audit trail and removes the staff member from the card data flow entirely.
Field referenceAsk
Prop
Type
Next stepsAsk
Payment links
Core payment-link API — create, share, and track links for remote and online use cases.
Shopper recognition
Identify shoppers across channels so loyalty, saved cards, and preferences follow them in store.
In-person features
Tipping, MOTO, surcharging, DCC, and the full feature reference for VINR terminals.
Last updated on