Skip to main content

Refund POS Charge

POST /pos/charge/:chargeID/refund

Refunds a previously approved POS charge. Supports both full and partial refunds by specifying the refund amount. The charge must be in an approved state to be eligible for a refund.

MSK encryption: Request and response bodies use MSK-encrypted envelopes (TR31-DATA). HMAC is computed over the encrypted request body. See End-to-End Example.

Purpose

  • Issue a full or partial refund for a completed charge
  • Track refund reason for reconciliation and reporting
  • Return a unique refund ID for tracking the refund status

Authentication

POS HMAC Signature — requires device identification headers and HMAC signature for every request.

Device Identification Headers

HeaderRequiredFormatDescription
X-Terminal-IdYesTerminal ID stringIdentifier of the terminal processing the refund. Example: TERM-001
User-AgentYesViopay-POS/{version} ({OS}; {model})POS app version string. Must start with Viopay-POS/. Example: Viopay-POS/1.4.2 (Android 12; PAX-A920)
X-Client-TypeYesposClient type identifier. Always pos for POS devices.

Signature Headers

HeaderRequiredFormatDescription
X-Key-IdYesFree-form stringIdentifier of the HMAC key used to generate the signature. Example: hmac-key-2025-01
X-TimestampYesRFC3339Current time in UTC. Must be within 5 minutes of server time. Example: 2025-12-13T14:25:30Z
X-NonceYesAlphanumeric stringUnique random value for each request. At least 12 characters. Example: a1b2c3d4e5f6
X-SignatureYesv1={base64_hmac}HMAC-SHA256 signature over the request. See Signature Computation.

See the Headers Reference for complete details on all POS headers.

Request

Path Parameters

ParameterTypeRequiredDescription
chargeIDstringYesThe charge ID to refund (returned from Create POS Charge)

Body Parameters

FieldTypeRequiredDescription
amountobjectYesRefund amount
amount.valuestringYesAmount in minor units (e.g. "1500" for 15.00). For a full refund, use the original charge amount. For a partial refund, use a smaller value.
amount.currencystringYesISO 4217 currency code. Must match the original charge currency.
reasonstringNoReason for the refund (e.g. "customer_request", "defective_product")
transaction_referencestringNoExternal reference ID for the refund transaction

Body — MSK envelope (wire format)

{
"format": "TR31-DATA",
"ciphertext": "A1B2C3...",
"initialization_vector": "000102030405060708090A0B0C0D0E0F",
"mode": "CBC"
}

Plaintext (before MSK encrypt)

{
"amount": {
"value": "1500",
"currency": "EUR"
},
"reason": "customer_request",
"transaction_reference": "REF-2025-001"
}

Response

200 OK — MSK-encrypted envelope

Decrypt with MSK to obtain:

{
"refund_id": "rf_xyz789abc012",
"status": "approved",
"amount": {
"value": "1500",
"currency": "EUR"
}
}
FieldTypeDescription
refund_idstringUnique identifier for the refund
statusstringRefund status: approved, declined, pending
amountobjectConfirmed refund amount
amount.valuestringAmount in minor units
amount.currencystringISO 4217 currency code

400 Bad Request

Returned when the charge ID is missing, the request body is invalid, or the refund amount exceeds the original charge.

{
"error": {
"code": "4000",
"message": "Invalid refund request",
"trace_id": "abc123..."
}
}

401 Unauthorized

Returned when HMAC signature validation fails.

{
"error": {
"code": "4001",
"message": "Invalid signature",
"trace_id": "abc123..."
}
}

500 Internal Server Error

Returned when the payment gateway returns an error or processing fails.

{
"error": {
"code": "5000",
"message": "Gateway processing error",
"trace_id": "abc123..."
}
}

Code Examples

curl -X POST https://api.viopay.io/pos/charge/ch_abc123def456/refund \
-H "X-Terminal-Id: TERM-001" \
-H "User-Agent: Viopay-POS/1.4.2 (Android 12; PAX-A920)" \
-H "X-Client-Type: pos" \
-H "X-Key-Id: hmac-key-2025-01" \
-H "X-Timestamp: 2025-12-13T14:25:30Z" \
-H "X-Nonce: a1b2c3d4e5f6" \
-H "X-Signature: v1=SGVsbG8gV29ybGQ=" \
-H "Content-Type: application/json" \
-d '{
"amount": {
"value": "1500",
"currency": "EUR"
},
"reason": "customer_request"
}'

What's Next?