In-person refunds
Issue referenced and unreferenced refunds for card-present transactions.
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 → truecurl 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.
| Surface | Who initiates | Card-present required | Typical use case |
|---|---|---|---|
| Terminal app | In-store staff | Optional (referenced flow) | Customer at counter with card |
| VINR Dashboard | Operations / finance | No | Remote or delayed refund; batch adjustments |
API (vinr.refunds.create) | Your server | No | Automated 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.
| Device | Paper receipt | Email / SMS receipt |
|---|---|---|
| Nexgo N92 | Built-in thermal printer | Configurable |
| Nexgo N86Pro | No printer | Configurable |
| Nexgo CT20 | Built-in receipt printer | Configurable |
| Nexgo CT20P | Built-in receipt printer | Configurable |
| Ciontek CM30 | No printer | Configurable |
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
Refunds
Shared refund concepts: status lifecycle, fees, failed refunds, and webhooks.
Accept an in-person payment
Create a payment intent and present it to a VINR terminal.
Reconciliation
How in-person refunds net against terminal settlement and payouts.
Last updated on