Refunds
A refund sends money back to the payer’s bank account, from your project’s available balance. Refund any part of a succeeded payment, in one go or several.
#!/usr/bin/env bash# Refund a succeeded payment to the payer's bank account.set -euo pipefail. "$(dirname "$0")/../signed-request.sh"
payment_id=$(mka_required PAYMENT_ID)body=$(cat <<JSON{ "amount": "${AMOUNT:-1000.00}", "currency": "LKR", "reason": "requested_by_customer", "recipient": { "bank_name": "Bank of Ceylon", "account_holder": "N. Fernando", "account_number": "0087654321" }}JSON)mka_request POST "/v1/payments/$payment_id/refunds" "$body" "$(mka_new_key)"// Refund a succeeded payment to the payer's bank account.import { newKey, print, request, required } from "../signed-request.mjs";
const paymentId = required("PAYMENT_ID");const answer = await request("POST", `/v1/payments/${paymentId}/refunds`, { body: { amount: process.env.AMOUNT ?? "1000.00", currency: "LKR", reason: "requested_by_customer", recipient: { bank_name: "Bank of Ceylon", account_holder: "N. Fernando", account_number: "0087654321", }, }, idempotencyKey: newKey(),});print(answer);<?php// Refund a succeeded payment to the payer's bank account.
declare(strict_types=1);
require __DIR__ . '/../signed_request.php';
$paymentId = mka_required('PAYMENT_ID');mka_show(mka_request( 'POST', "/v1/payments/{$paymentId}/refunds", [ 'amount' => getenv('AMOUNT') ?: '1000.00', 'currency' => 'LKR', 'reason' => 'requested_by_customer', 'recipient' => [ 'bank_name' => 'Bank of Ceylon', 'account_holder' => 'N. Fernando', 'account_number' => '0087654321', ], ], mka_new_key(),));"""Refund a succeeded payment to the payer's bank account."""import os
from signed_request import new_key, request, required, show
payment_id = required("PAYMENT_ID")show(request( "POST", f"/v1/payments/{payment_id}/refunds", body={ "amount": os.environ.get("AMOUNT", "1000.00"), "currency": "LKR", "reason": "requested_by_customer", "recipient": { "bank_name": "Bank of Ceylon", "account_holder": "N. Fernando", "account_number": "0087654321", }, }, idempotency_key=new_key(),))//go:build ignore
// Refund a succeeded payment to the payer's bank account.package main
import ( "docs.processing.yolotech.cc/examples/signedrequest")
func main() { paymentID := signedrequest.Required("PAYMENT_ID") signedrequest.Show(signedrequest.Request("POST", "/v1/payments/"+paymentID+"/refunds", map[string]any{ "amount": signedrequest.Env("AMOUNT", "1000.00"), "currency": "LKR", "reason": "requested_by_customer", "recipient": map[string]any{ "bank_name": "Bank of Ceylon", "account_holder": "N. Fernando", "account_number": "0087654321", }, }, signedrequest.NewKey()))}amount— at most what the payment received, less what is already refunded or on its way. More is422 refund_exceeds_payment. Your fee for the payment is not returned.recipient— the payer’s bank account:bank_name,account_holderandaccount_number(6 to 20 digits; spaces and hyphens are dropped). It is stored sealed and read back masked:Bank of Ceylon ••••4321.reason—requested_by_customer,duplicateorfraudulent.
The amount is held from the available balance at once; more than you have is
422 insufficient_available_balance, and nothing is held. Only a succeeded payment can be refunded:
another is 409 payment_not_refundable.
Statuses
Section titled “Statuses”| Status | Meaning |
|---|---|
requested |
Held from your balance; waiting for an Agent to send it. |
processing |
An Agent is sending it. |
succeeded |
The payer got it. Final. |
failed |
Nobody took it within a day (not_taken), or the platform refused it (refused). The hold comes back. Final. |
A refund sent quickly may go from requested straight to succeeded; do not wait for processing.
Webhooks and ordering
Section titled “Webhooks and ordering”Each change is a refund.status_changed event with refund_id and refund_version. The events of one
refund may arrive out of order: keep the highest refund_version you have seen for each refund and ignore a
lower one. When in doubt, read the payment’s refunds:
#!/usr/bin/env bash# A payment's refunds, oldest first.set -euo pipefail. "$(dirname "$0")/../signed-request.sh"
payment_id=$(mka_required PAYMENT_ID)mka_request GET "/v1/payments/$payment_id/refunds"// A payment's refunds, oldest first.import { print, request, required } from "../signed-request.mjs";
const paymentId = required("PAYMENT_ID");const answer = await request("GET", `/v1/payments/${paymentId}/refunds`);print(answer);<?php// A payment's refunds, oldest first.
declare(strict_types=1);
require __DIR__ . '/../signed_request.php';
$paymentId = mka_required('PAYMENT_ID');mka_show(mka_request('GET', "/v1/payments/{$paymentId}/refunds"));"""A payment's refunds, oldest first."""from signed_request import request, required, show
payment_id = required("PAYMENT_ID")show(request("GET", f"/v1/payments/{payment_id}/refunds"))//go:build ignore
// A payment's refunds, oldest first.package main
import ( "docs.processing.yolotech.cc/examples/signedrequest")
func main() { paymentID := signedrequest.Required("PAYMENT_ID") signedrequest.Show(signedrequest.Request("GET", "/v1/payments/"+paymentID+"/refunds", nil, ""))}The same Idempotency-Key and body answer the refund made first, with 201.