PayOrc
Manage Payment

Refund

Refund a captured payment to return funds to the customer.

Refund

Version: 3.0.0

Prerequisite: Refund a transaction that has already been captured (or SALE). You cannot refund a pure authorization — use Void instead. Refund must also be enabled on your MID (allowRefunds).

When and Why to Use Refund

Use Refund to return money to a customer after capture:

  1. Customer returns a product.
  2. Overcharge correction.
  3. Service cancellation after payment.
  4. Partial refund for a subset of items.

Refund Limits

RuleDetail
MaximumTotal refunds cannot exceed the original captured amount
Minimumamount.value must be at least 1 in the order currency (same minimum as order amount)
Multiple partialsAllowed until the captured balance is fully refunded
Order statusAfter a partial refund, data.status is PARTIALLY_REFUNDED. When the captured amount is fully refunded, data.status is REFUNDED
Settlement timeIssuing banks may take 5–10 business days to show the credit on the customer's statement

Over-refund attempts: If the requested refund plus any prior refunds would exceed the captured amount, the PSP rejects the request. The API typically returns HTTP 200 with { "success": false, "message": "<PSP-specific error>" }. Edge validation errors (transaction not in a refundable state, refund disabled on MID) return HTTP 400 with { "status": "fail", "code": "E0044", "message": "..." }.

Endpoint

Refund, Capture, and Void share the same Manage Payment endpoint — only action changes.

MethodURL
POSThttps://api.payorc.com/orders/v1/transaction

Please use the test credentials for sandbox testing.


Headers

FieldTypeRequiredDescription
merchant-keyStringYesYour merchant API key
merchant-secretStringYesYour merchant API secret
Content-TypeStringYesMust be application/json

Request Body

The request body is flat (not nested under data).

FieldTypeRequiredDescription
actionStringYesMust be REFUND
transaction_idStringYesPayOrc transaction ID to refund
amountObjectYesAmount object
amount.currencyCodeStringYesISO currency code (e.g. AED)
amount.valueNumberYesRefund amount (full or partial)
reasonStringNoMerchant notes

Code Examples

Example 1 — Full Refund

curl --location 'https://api.payorc.com/orders/v1/transaction' \
--header 'merchant-key: {merchant-key}' \
--header 'merchant-secret: {merchant-secret}' \
--header 'Content-Type: application/json' \
--data '{
    "action": "REFUND",
    "transaction_id": "1000010118",
    "amount": {
        "currencyCode": "AED",
        "value": 100.00
    },
    "reason": "Customer returned item - full refund"
}'

Example 2 — Partial Refund

curl --location 'https://api.payorc.com/orders/v1/transaction' \
--header 'merchant-key: {merchant-key}' \
--header 'merchant-secret: {merchant-secret}' \
--header 'Content-Type: application/json' \
--data '{
    "action": "REFUND",
    "transaction_id": "1000010118",
    "amount": {
        "currencyCode": "AED",
        "value": 35.00
    },
    "reason": "Partial return - 1 of 3 items returned"
}'

Partial refund: You can issue multiple partial refunds against one transaction as long as the total does not exceed the captured amount. Order status becomes PARTIALLY_REFUNDED or REFUNDED.

Example 3 — Node.js

const axios = require('axios');

const config = {
  method: 'post',
  url: 'https://api.payorc.com/orders/v1/transaction',
  headers: {
    'merchant-key': '{merchant-key}',
    'merchant-secret': '{merchant-secret}',
    'Content-Type': 'application/json'
  },
  data: {
    action: 'REFUND',
    transaction_id: '1000010118',
    amount: {
      currencyCode: 'AED',
      value: 100.00
    },
    reason: 'Full refund - order cancelled'
  }
};

axios(config)
  .then(response => console.log(JSON.stringify(response.data)))
  .catch(error => console.log(error.response?.data || error));

Example 4 — Python

import requests
import json

url = 'https://api.payorc.com/orders/v1/transaction'

payload = {
    "action": "REFUND",
    "transaction_id": "1000010118",
    "amount": {
        "currencyCode": "AED",
        "value": 25.00
    },
    "reason": "Partial refund - shipping fee adjustment"
}

headers = {
    'merchant-key': '{merchant-key}',
    'merchant-secret': '{merchant-secret}',
    'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, json=payload)
print(json.dumps(response.json(), indent=2))

Response — Success (200)

{
    "data": {
        "status": "REFUNDED",
        "m_order_id": "ORD-2024-001",
        "p_order_id": 1000010228,
        "transaction_id": 1000010223,
        "amount": "100.00",
        "currency": "AED",
        "date": "04/08/2023"
    },
    "message": "Refunded Successfully.",
    "status": "success",
    "code": "00"
}

Capture, Void, and Refund share the same data shape: status, m_order_id, p_order_id, transaction_id, amount, currency, date. For partial refunds, status is PARTIALLY_REFUNDED.

Response — Error

{
    "message": "Transaction can't be refunded, already refunded or not in state of to be refunded",
    "status": "fail",
    "code": "E0044"
}

Full vs Partial Refund

AspectFull RefundPartial Refund
Amount100% of captured amountLess than captured amount
Order statusREFUNDEDPARTIALLY_REFUNDED
Further refunds?NoYes, up to remaining amount

On this page