PayTo Refunds via PayTo

Refunding PayTo Payments via PayTo

This article will guide you on how to refund a PayTo payment via PayTo.

card icon

🚧

Prerequisites for Using this Feature

To refund a PayTo payment, via PayTo, merchants must ensure the following prerequisites are met:

  • A PayTo-enabled bank account - Your business's bank account must be PayTo enabled.
  • An Active PayTo agreement – You must have an active PayTo agreement setup in your Zepto account against your business's bank account; this account supplies the funds for any refunds.
  • Settled original payment – You can only refund a PayTo payment after it has fully settled.

📘

Key capabilities

  • Issue either a full refund or any partial amount
  • Process several refunds for a single PayTo transaction, provided the combined total never exceeds the original payment value.

Step 1 - Set Up the Refund Agreement:

  1. Create a Refund Agreement:
  • Establish a PayTo mandate with your business account. This will be the source account for refunds.
  • Structure payment terms (e.g., variable amount, ad-hoc frequency) as necessary.
  • Authorise the agreement in your banking app.

📘

Keep the uid as we will use it to process refunds.

Merchants can choose have have a single Refund Agreement and reuse it for all the refunds provided the refunds are within the the original refund agreement terms.

  • Example Payload:
{
    "uid": "MerchantA_Refund_Agreement",
    "purpose": "retail",
    "description": "Refund Agreement",
    "debtor": {
        "party_name": "Merchant A",
        "account_identifier": {
            "type": "alias_phone",
            "value": "+61-402037912"
        },
        "ultimate_party_name": "Merchant A"
    },
    "initiator": {
        "name": "Merchant A",
        "legal_name": "Merchant A",
        "abn": "12345678103"
    },
    "payment_terms": {
        "type": "variable",
        "frequency": "adhoc",
        "max_amount": 1000
    }
}


Step 2 - Initiate a PayTo Refund

❗️

The refund agreement must be authorised and in Active state before refunds can be processed.

ℹ️ Learn more about Agreement States here.

Process a Refund

Endpoint

POST payto/refunds

ParameterDescription
uid* (required)Supplied 64-character unique identifier for the refund request. This identifier ensures payment uniqueness between integrator systems and Zepto.
original_payment_uid* (required)The original PayTo Payment UID to validate and process the refund against.
refund_payment: type* (required)pay_to_payment
refund_payment: agreement_uid* (required)The agreement uid from the refund agreement you created in Step 1.
refund_payment: amount* (required)The amount (in cents) to be refunded.
refund_payment: description* (required)Supplied 280-character free-form text for reconciliation purposes.

Typically this field will be shown to both parties on bank statements.
{
    "refund_payment": {
        "type": "pay_to_payment",
        "agreement_uid": "MerchantA_Refund_Agreement",
        "amount": 50,
        "description": "Refund Description"
    },    
    "uid": "refund_example_uid",
    "original_payment_uid": "original_payment_uid"
}
{
    "data": {
        "uid": "refund_example_uid",
        "original_payment_uid": "original_payment_uid",
        "refund_payment": {
            "type": "pay_to_payment",
            "agreement_uid": "MerchantA_Refund_Agreement",
            "uid": "refund_example_uid",
            "amount": 50,
            "description": "Refund Description"
        },
        "state": "created",
        "failure": null,
        "created_at": "2025-05-23T10:43:43+10:00",
        "metadata": {},
        "links": {
            "self": "https://api.zeptopayments.com/payto/refunds/refund_example_uid",
            "original_payment": "https://api.zeptopayments.com/payto/payments/original_payment_uid"
        }
    }
}
{
    "errors": [
        {
            "title": "Request body is not valid JSON",
            "detail": "Error occurred while parsing request parameters"
        }
    ]
}
{
    "errors": [
        {
            "code": "ZPREF06",
            "title": "Total refunds greater than original payment amount",
            "detail": "The sum of all refunds is greater than the original payment"
        }
    ]
}

Response

Upon submission, a synchronous response will show one of the following:

  • Successful: 201 response
  • Failed:
    • 400: Bad request
    • 422: Unprocessable entity

Webhook

Note: Webhooks are only available for PayTo refund requests that have received a 201 response from Zepto (i.e. successful request).

{
  "data": {
    "id": "0196fab0-a8e6-6753-56f5-3b8f72adf97f",
    "body": null,
    "type": "payto_refund.processed",
    "published_at": "2025-05-23T11:10:03.750+10:00",
    "resource_uid": "refund_example_uid",
    "resource_type": "payto_refund",
    "resource_metadata": {}
  },
  "links": {
    "resource": "https://api.zeptopayments.com/payto/refunds/refund_example_uid"
  }
}
{
  "data": {
    "id": "0196fab0-a8c2-de86-d7f3-9c3ba947d5d4",
    "body": null,
    "type": "payto_payment.settled",
    "published_at": "2025-05-23T11:10:03.714+10:00",
    "resource_uid": "refund_example_uid",
    "resource_type": "payto_payment",
    "resource_metadata": {}
  },
  "links": {
    "resource": "https://api.zeptopayments.com/payto/payments/refund_example_uid"
  }
}

Notable Webhook Fields


typepayto_refund.processed
payto_refund.failed
resource_uidThe unique identifier of the refund
resource_typepayto_refund

Simulations

A special Sandbox testing object is available to simulate outcomes.

Available simulations:

  • creditor_alias_not_found
  • payment_rejected
  • success

Simulation Attribute Sample

"sandbox": {
  "simulate": "success"
}