Twint
Accept Twint — Switzerland's leading mobile payment app — with VINR.
Twint is Switzerland's dominant mobile payment method, with tens of millions of registered users and near-universal acceptance across Swiss merchants. Customers pay by scanning a QR code with the Twint app or, on mobile, by being redirected directly into the app to confirm. Payments are final on confirmation — there is no chargeback path.
AvailabilityAsk
| Detail | Value |
|---|---|
| Countries | Switzerland |
| Currency | CHF only |
| Flow | QR code scan (desktop) or app redirect (mobile) |
| Finality | Final on confirmation |
| Refunds | Supported via standard refund API |
Payment flowAsk
Twint adapts to the customer's device:
Desktop: QR code
Create the payment
Create a payment with methods: ['twint'] and a CHF amount. The VINR-hosted checkout renders a QR code.
Customer scans the QR code
The customer opens the Twint app on their phone, taps the QR scanner, and scans the QR code on your checkout page.
Customer confirms in the app
The app displays the merchant name and amount. The customer confirms with their Twint PIN or biometrics.
Payment completes
Twint confirms to VINR. The payment moves to completed and the desktop checkout page updates automatically.
Mobile: app redirect
On mobile, the hosted checkout replaces the QR code with a "Pay with Twint" button. Tapping it opens the Twint app directly (or the Twint-connected banking app). The customer confirms in the app and is returned to your returnUrl.
Creating a Twint paymentAsk
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const payment = await vinr.payments.create({
amount: 5500, // CHF 55.00 in minor units (Rappen)
currency: 'CHF',
description: 'Order #9923',
methods: ['twint'],
returnUrl: 'https://yoursite.com/payment/complete',
metadata: { orderId: '9923' },
});
// Redirect the customer to payment.checkoutUrlFulfill from the webhook:
// POST /webhooks/vinr
const event = vinr.webhooks.verify(rawBody, req.headers['x-vinr-signature']);
if (event.type === 'payment.completed') {
const payment = event.data;
// payment.method → "twint"
await fulfillOrder(payment.metadata.orderId);
}On desktop, the checkout page polls for confirmation and updates without a page reload. The customer does not leave your site. Drive fulfillment from the webhook regardless — the page update is cosmetic.
QR code expiryAsk
Twint QR codes are valid for a limited window (typically a few minutes). If the customer takes too long to scan, the payment moves to expired. Create a new payment to display a fresh QR code.
Settlement & timingAsk
Twint payments are confirmed within seconds. The captured amount lands in your balance immediately in CHF and follows your normal settlement schedule.
RefundsAsk
Refunds are returned to the customer's Twint account (linked bank account), typically within one to three business days.
const refund = await vinr.refunds.create({
payment: 'pay_...',
amount: 5500, // full refund; omit amount for full
reason: 'requested_by_customer',
});Because Twint payments are final, there are no chargebacks. A refund is the only way to return funds after the payment completes.
TestingAsk
In the VINR sandbox, Twint flows open a VINR test page where you choose Approve or Fail — no real Twint account or Swiss phone is needed.
LimitationsAsk
- CHF only. Twint cannot process amounts in any other currency.
- Switzerland only. The method only appears for customers with a Twint-linked Swiss bank account; presenting it outside Switzerland returns
method_not_available. - No manual capture. Twint captures in full at confirmation.
- QR codes expire. Customers must scan within the validity window.
See alsoAsk
Local methods
Overview of all region-specific payment methods.
iDEAL
Bank redirect for Dutch customers.
Refunds
Issue full or partial refunds via the API.
Last updated on