PaymentsIn-Person PaymentsIn-person refunds

In-person refunds

Issue referenced and unreferenced refunds for card-present transactions.

View as MarkdownInstall skills

In-person refunds use the same vinr.refunds.create API as online refunds — the object shape, status lifecycle, and webhook events are identical. The key difference is whether the original card must be presented to the terminal again. A referenced refund re-presents the card to the same terminal; an unreferenced refund carries no card requirement and can be initiated from the dashboard or API alone. See Refunds for the shared concepts (status, timing, fees, failed refunds) that apply to all rails.

Referenced refundsAsk

A referenced refund is the preferred path for in-person returns. The customer brings the physical card back to the terminal, the device reads it, and the funds are credited back through the scheme on the original transaction reference. This keeps interchange fees at their lowest tier and provides the clearest audit trail.

Customer presents the card or device used in the original purchase to the same terminal or any terminal on your account.

Staff selects the original transaction in the VINR terminal app or initiates the refund from the API with presentToTerminal: true.

The terminal prompts the customer to tap, insert, or swipe. A PIN is not required for refunds on most schemes.

VINR creates the refund object, returns a re_ ID, and prints or sends a receipt automatically.

import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const refund = await vinr.refunds.create({
  payment: 'pay_3Nf8x2a',
  presentToTerminal: true,
  reason: 'requested_by_customer',
  metadata: { staffId: 'staff_99', registerId: 'pos_2' },
});

// refund.id               → "re_7Qp2m1c..."
// refund.status           → "pending"
// refund.presentToTerminal → true
curl https://api.vinr.com/v1/refunds \
  -H "X-Api-Key: $VINR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payment": "pay_3Nf8x2a",
    "presentToTerminal": true,
    "reason": "requested_by_customer",
    "metadata": { "staffId": "staff_99", "registerId": "pos_2" }
  }'

Prop

Type

Unreferenced refundsAsk

An unreferenced refund credits a cardholder without requiring the original transaction reference or the physical card. Use this when a customer cannot return to the store, when the refund is initiated days or weeks after the sale, or when the original transaction identifier is unavailable.

Unreferenced refunds attract higher interchange fees from Visa and Mastercard because they bypass the scheme's matched-refund flow. Prefer referenced refunds at the terminal whenever the customer can present the original card.

import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const refund = await vinr.refunds.create({
  payment: 'pay_3Nf8x2a',
  reason: 'requested_by_customer',
  metadata: { caseId: 'CS-1042' },
});

Unreferenced refunds can be created from the API, the VINR Dashboard, or via the terminal without card presentment. The presentToTerminal field is omitted or set to false.

Refund at terminal vs dashboard vs APIAsk

Different teams initiate refunds through different surfaces. The table below shows when each is appropriate.

SurfaceWho initiatesCard-present requiredTypical use case
Terminal appIn-store staffOptional (referenced flow)Customer at counter with card
VINR DashboardOperations / financeNoRemote or delayed refund; batch adjustments
API (vinr.refunds.create)Your serverNoAutomated refund logic; post-purchase workflows

All three surfaces create the same refund object and emit the same webhook events. Terminal-initiated refunds include a terminalId field in the refund's metadata to identify which device processed the return.

Partial refundsAsk

Pass an explicit amount in minor units to refund less than the full charge. The terminal displays the partial amount to the customer before they present their card, so there is no ambiguity at the point of interaction.

import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const partial = await vinr.refunds.create({
  payment: 'pay_3Nf8x2a',
  amount: 500,
  presentToTerminal: true,
  reason: 'product_not_received',
});

// refund.amount → 500  (€5.00 of a larger charge)

When presentToTerminal is true, the terminal screen shows the partial refund amount before reading the card. The customer must confirm before the card interaction completes — on devices with a customer-facing display (Nexgo CT20P, Nexgo N86Pro) the amount appears on the customer screen; on single-screen devices the staff-facing display shows the amount.

Multiple partial refunds can be issued against the same payment until the refundable balance reaches zero. VINR rejects any request that would exceed the remaining balance with a 422 amount_too_large error.

Refund receiptsAsk

VINR generates a refund receipt automatically when the terminal completes a card-present refund. The receipt format and delivery channel depend on device and configuration.

DevicePaper receiptEmail / SMS receipt
Nexgo N92Built-in thermal printerConfigurable
Nexgo N86ProNo printerConfigurable
Nexgo CT20Built-in receipt printerConfigurable
Nexgo CT20PBuilt-in receipt printerConfigurable
Ciontek CM30No printerConfigurable

Email and SMS receipts are enabled per-location in the VINR Dashboard under Settings → Receipts. When both paper and digital are enabled, the terminal prompts staff to choose — or sends both if your configuration specifies receiptDelivery: 'all'. Refund receipts carry the original transaction date, the refund amount, and the re_ reference so customers can match them to their bank statement.

Receipts for unreferenced or dashboard-initiated refunds are sent by email or SMS only. The terminal is not involved and no paper receipt is produced.

Next stepsAsk

Was this page helpful?
Edit on GitHub

Last updated on

On this page