# 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.

## Availability

| 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 flow

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 payment

```typescript
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.checkoutUrl
```

Fulfill from the webhook:

```typescript
// 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 expiry

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 & timing

Twint payments are confirmed within seconds. The captured amount lands in your [balance](/docs/operations/balances) immediately in CHF and follows your normal [settlement](/docs/operations/settlement) schedule.

## Refunds

Refunds are returned to the customer's Twint account (linked bank account), typically within one to three business days.

```typescript
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.

## Testing

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.

## Limitations

- **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 also

[Local methods](/docs/payments/payment-methods/add-payment-methods/local-methods) — Overview of all region-specific payment methods.

[iDEAL](/docs/payments/payment-methods/add-payment-methods/local-methods/ideal) — Bank redirect for Dutch customers.

[Refunds](/docs/payments/payment-operations/refund) — Issue full or partial refunds via the API.
