PUT Reverse a Transaction

PUT /payout/v1/transactions/{transactionId}/reverse

Development Guide

The 'Reverse a Transaction' endpoint will rollback the payout of a transaction, if paid out in error or in the event of a system failure.



1. Headers & authentication:

The application must call the 'Reverse a Transaction ' endpoint with a PUT HTTP method, providing the OAuth access_token and all other required header and parameter values. To invoke the Reverse a Transaction API, the application must pass the transactionId as a path parameter.


Note:

  • MoneyGram uses the OAuth 2.0 framework. The application must use their OAuth client credentials to generate an access_token by calling the Get Access Token endpoint. The token is valid for 1 hour and must be passed as a header value in all subsequent API HTTP calls. Learn More
  • The transaction can only be reversed by the same application and agentPartnerId that committed the payout of the transaction.
  • Only a transaction in a "RECEIVED" status can be reversed.
  • A transaction can only be reversed within 30 minutes from the time the transaction "commit" was invoked.

🚀

Launch Code Example:




2. Provide the referenceNumber & receiveReversalReasonCode in the Request Body

The request body must at a minimum must include the referenceNumber & receiveReversalReasonCode for the transaction to be reversed.


🚀

Launch Code Example:




3. Make a request and handle the response:

The application must call the 'Reverse a transaction' endpoint with a PUT HTTP method and be able to handle the following response scenarios:


  • Success | Parse the Response | 200 OK HTTP Status
    When the 'Reverse a transaction' endpoint responds with a 200 HTTP status, the transaction will change back from a "RECEIVED" status to an "AVAILABLE" status. The transaction will not be settled with MoneyGram, and the partner will be able to try paying out the transaction again.

  • Failed | Handle the Error | 400 Bad Request HTTP Status
    When the 'Reverse a transaction' endpoint responds with 400 HTTP Status, specific error code/s will be returned with an array of offending fields. The application will need to resolve these errors and resubmit the transaction for reversal.

🚀

Launch Code Example:

.




4. You're Done! Provide a receipt:

A receipt most be printed and handed to the customer.




Business Rules to Code


🔎

  1. Making multiple PUT requests to Update the transactionId: if there are any changes needed for consumer data after the Update a transaction endpoint responds, the application should call the Update endpoint to using the same transactionId and payoutId to provide new consumer/transactional data.

  2. Enumerated fields: For all Enumerated Fields (some examples below), agent application must use the valid enumerations returned from the enumerations API response and allow only valid values to be selected. Learn More

  3. Pre-disclosure: It is regulatory requirement to show pre-disclosure on every transfer, in every country and for every service option. Learn More




Code Examples


const axios = require('axios');
const { v4: uuidv4 } = require('uuid');

const reverseTransaction = async () => {

    // Step 1: Read configuration values with upmost security
    const token = "your_access_token_from_oauth_response"
    // For production - api.moneygram.com & For test - sandboxapi.moneygram.com
    const transactionId = "current_transaction_id";
    const host = "sandboxapi.moneygram.com";
    const url = 'https://' + host + '/payout/v1/transactions/' + transactionId + '/reverse';

    // Step 2: Create the PUT request headers, params & body

    const headers = {
        'Content-Type': 'application/json',
        'X-MG-ClientRequestId': uuidv4(), // New UUID for each request tracing
        'Authorization': 'Bearer ' + token,
    };

    const params = {
        agentPartnerId: "your_partner_id",
        targetAudience: "AGENT_FACING",
        userLanguage: "en-US"
    }

    const request = {
        referenceNumber: "your_reference_number",
        receiveReversalReasonCode: "WRONG_TX"
    }

    try {
        // Step 3: Send the request and obtain the response
        axios.put(url, request, { params, headers })
            .then(function (response) {
                // Step 4: Parse the success response and process further
                console.log(JSON.stringify(response.data, null, 2))
            })
            .catch(function (error) {
                // Step 5: Parse the error response and handle the errors
                if (error.response) {
                    console.log('Response status:', error.response.status);
                    console.log('Response body:', error.response.data);
                } else {
                    // TODO: handle generic errors
                    console.error('Error:', error.message);
                }
            });
    } catch (error) {
        // TODO: handle exception
        console.error('Error:', error.message);
    }
};

reverseTransaction();
import requests
import uuid
import json

def reverse_transaction():

    # Step 1: Read configuration values with upmost security
    token = "your_access_token_from_oauth_response"
    # For production - api.moneygram.com & For test - sandboxapi.moneygram.com
    transactionId = "current_transaction_id";
    host = "sandboxapi.moneygram.com";
    url = 'https://' + host + '/payout/v1/transactions/' + transactionId + '/reverse';

    # Step 2: Create the PUT request headers, params & body
    headers = {
        'Content-Type': 'application/json',
        'X-MG-ClientRequestId': str(uuid.uuid4()), # New UUID for each request tracing
        'Authorization': 'Bearer ' + token,
    }
    
    params = {
        'agentPartnerId': 'your_partner_id',
        'targetAudience': 'AGENT_FACING',
        'userLanguage': 'en-US'
    }

    request = {
        'referenceNumber': "your_reference_number", 
        'receiveReversalReasonCode': "WRONG_TX"
    }

    try:
        # Step 3: Send the request and obtain the response
        response = requests.put(url, json=request, params=params, headers=headers)

        # Step 4: Parse the success response and process further
        if response.status_code == 200:
            parsed_response = json.dumps(json.loads(response.text), indent=2)
            print(parsed_response)
        else:
            # Step 5: Parse the error response and handle the errors
            print("Request failed with status code:", response.status_code)
            print(json.dumps(json.loads(response.text), indent=2))

    except requests.exceptions.RequestException as e:
        # Print any error that occurred during the request
        # TODO: handle exception
        print("An error occurred:", e)

reverse_transaction()

package payout;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;

public class ReverseTransaction {

    public static void main(String[] args) {
        // Step 1: Read configuration values with upmost security
        String token = "your_access_token_from_oauth_response";

        // For production - api.moneygram.com & For test - sandboxapi.moneygram.com
        String host = "sandboxapi.moneygram.com";
        String transactionId = "current_transaction_id";
        String uri = "https://" + host + "/payout/v1/transactions/" + transactionId + "/reverse" + "?"
                + "agentPartnerId=" + agentPartnerId
                + "&userLanguage=" + userLanguage
                + (targetAudience.isBlank() ? "" : "&targetAudience=" + targetAudience);

        // Step 2: Create the PUT request header, params & body
        // Create a JSON object
        JsonObjectBuilder requestBuilder = Json.createObjectBuilder()
                .add("referencenumber", "your_reference_number")
                .add("receiveReversalReasonCode", "WRONG_TX")

        JsonObject jsonObject = requestBuilder.build();
        // Create a StringWriter to write the JSON string
        StringWriter stringWriter = new StringWriter();
        try (JsonWriter jsonWriter = Json.createWriter(stringWriter)) {
            jsonWriter.writeObject(jsonObject);
        }
        // Get the JSON string from the StringWriter
        String jsonString = stringWriter.toString();

        HttpClient httpClient = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(uri))
                .PUT(HttpRequest.BodyPublishers.ofString(jsonString))
                .setHeader("Authorization", "Bearer " + token)
                .setHeader("X-MG-ClientRequestId", String.valueOf(UUID.randomUUID()))
                .build();

        try {
            // Step 3: Send the request and obtain the response
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

            // Retrieve the status code and body from the response
            int statusCode = response.statusCode();

            // Step 4: Parse the success response and process further
            if (statusCode == 200) {
                String responseBody = response.body();
                System.out.println(responseBody);
            } else {
                // Step 5: Parse the error response and handle the errors
                String responseBody = response.body();
                System.out.println(responseBody);
            }
        } catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }
    }
}






API Structure


Header Parameters

NameTypeRequired
/Optional
Description
X-MG-ClientRequestIdStringOptionalClient Request Id that can be passed by the client application. Client request Id must be unique within a single session for unique requests. This attribute can be used for ensuring idempotent request processing for some APIs. MoneyGram recommends using a UUID for the value of this field.
X-MG-ConsumerIPAddressStringOptionalIP Address of the system initiating the session.



Query Parameters


FieldTypeRequired/
Optional
Description
targetAudienceStringOptionalIdentifies the client. Error messages and attribute metadata tailored to client [agent (store client) vs consumer (digital client)]
userLanguageStringRequiredLanguage used by the user/operator
agentPartnerIdStringRequiredUnique agent or partner identifier
posIdStringOptionalPoint of sale identifier of the client performing the API Call
operataorIdStringOptionalOperator name or ID of the user performing the transaction. Name or ID must be populated from the agent/partner system and cannot be edited by the user.



Path Parameters

FieldTypeRequired/
Optional
Description
transactionIdStringRequiredUnique identifier for the transaction resource



Request Body

FieldTypeRequired/
Optional
Description
referenceNumberStringRequiredUnique identifier for the transaction resource
retryIndicatorBoolean OptionalIf agent application has sent a receive reversal request and did not receive a response, the application can retry the receive reversal request again and set this indicator to true
receiveReversalReasonCodeStringOptionalReason for the reversal of transaction (Enumerated values)

NOTE: For a list of accepted enumerated values for receive reversal reason codes see the Reference Data API Module - Enumerations endpoint - RCV_REVERSAL_RSNS



Response fields

FieldTypeRequired/OptionalDescription
receiveReversalSuccessBooleanRequiredIndicates whether the reversal is success or failure