# Testing
source: https://developer.mastercard.com/cross-border-services/documentation/testing/index.md

Use this page to plan and execute Sandbox validation for Mastercard Cross-Border Services. It covers the recommended workflow, positive and negative test coverage, and the tutorials you need for endpoint-level execution.
Tip: Start all validation in Sandbox before moving to MTF or Production.

## Choose a testing method {#choose-a-testing-method}

Choose a testing method that best matches how you want to validate requests:

* [Insomnia Collection](https://developer.mastercard.com/cross-border-services/documentation/developer-tools/insomnia-collection/index.md), an alternative API client with a ready-to-use workspace.
* [Reference Application](https://developer.mastercard.com/cross-border-services/documentation/developer-tools/ref-app/index.md), a working implementation you can run and inspect.
* Custom API client generated as per guidance in [API Basics](https://developer.mastercard.com/cross-border-services/documentation/api-basics/index.md).

Warning: If you are a Customer contracted with MTS EU or MTS UK, you must connect using [OAuth 2.0 Authorization Code flow](https://developer.mastercard.com/cross-border-services/documentation/tutorials/oauth2-api-sdk-tutorial-access-token/index.md) for Balance API and [OAuth 2.0 Request Token flow](https://developer.mastercard.com/cross-border-services/documentation/tutorials/oauth2-api-sdk-tutorial-request-token/index.md) for all other APIs to ensure compliance with the jurisdiction-based Regulatory Technical Standards derived from PSD2.

## Recommended testing workflow {#recommended-testing-workflow}

1. Generate your Sandbox credentials and confirm your project is in Sandbox mode.
2. Choose your testing method from the list above and complete the relevant tutorial setup.
3. Submit a payment to the Sandbox environment.
4. Retrieve the payment to confirm it was created successfully.
5. Test additional flows: use a quote or cancel a payment, as applicable to your use case.
6. Optionally, test the following Value-Added Services (VAS), as applicable to your use case:
   * Address Validation
   * Account Validation
   * Bank Information Lookup
   * IBAN Generation
   * Endpoint Guide
   * Cash Pickup
7. Validate negative scenarios using invalid or missing parameters.
8. Once Sandbox testing is complete, request MTF access to test in a production-like environment before going live.

This flow gives you coverage across payment submission, retrieval, FX rate handling, error handling, and authentication.

## Testing in Sandbox {#testing-in-sandbox}

Each API has a dedicated Sandbox testing page with its test cases, sample requests, sample responses, and error codes. The Account Validation and RFI suites open a landing page that lists their individual APIs. Select an entry to open its testing details.

### APIs and suites {#apis-and-suites}

| #  |          API or Suite           |                                       What you can test                                        |                                                     Sandbox Testing                                                      |
|----|---------------------------------|------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| 1  | Quotes API                      | Request an FX quote and review the quoted amounts returned by the API.                         | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/quotes-api/index.md)                 |
| 2  | Quote Confirmation APIs         | Confirm a returned quote and use its proposal ID in a follow-on payment request.               | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/quote-confirmation-apis/index.md)    |
| 3  | Payment API                     | Submit a cross-border payment request and check the simulated success response and payment ID. | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/payment-api/index.md)                |
| 4  | Retrieve Payment API            | Retrieve a previously submitted payment and review the status and details returned.            | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/retrieve-payment-api/index.md)       |
| 5  | Cancel Payment API              | Send a cancel request for a pending payment and check the response.                            | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/cancel-payment-api/index.md)         |
| 6  | Amend API                       | Send an update to a held payment and confirm the change is reflected in the response.          | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/amend-api/index.md)                  |
| 7  | Balance API                     | Review how the Balance API responds and the structure of the balance details it returns.       | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/balance-api/index.md)                |
| 8  | Cash Pickup API                 | Submit a cash pickup payment request and review the status returned.                           | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/cashpickup-api/index.md)             |
| 9  | Address Validation API          | Send an address to the API and review the validation response returned.                        | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/address-validation-api/index.md)     |
| 10 | Endpoint Guide Adapter API      | Test the adapter endpoints used to connect your system to the service.                         | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/endpoint-guide-adapter_api/index.md) |
| 11 | Status Change Push              | Receive simulated status update notifications for payments and quotes.                         | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/status-change-api/index.md)          |
| 12 | Account Validation APIs (suite) | Send account, IBAN, and bank lookup requests and review the responses returned.                | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/account-validation-apis/index.md)    |
| 13 | RFI APIs (suite)                | Test the request-for-information flow: upload, download, retrieve, and update documents.       | [View](https://developer.mastercard.com/cross-border-services/documentation/testing/rfi-apis/index.md)                   |

## Positive testing {#positive-testing}

Positive testing confirms that valid requests succeed and return the expected data.

### Validate these behaviors {#validate-these-behaviors}

* Valid request bodies return `200 OK`.
* Created payment records are retrievable using the returned payment ID.
* Quoted rates are correctly applied to the payment when a quote flow is used.
* Properly signed and encrypted payloads are accepted by the API.

### Positive test cases {#positive-test-cases}

#### Submit a payment (without quote) {#submit-a-payment-without-quote}

Submit a cross-border payment request directly. The API applies the FX rate at processing time, which the Sandbox returns as a simulated value:

    POST https://sandbox.api.mastercard.com/send/v1/partners/{partner-id}/crossborder/payment

Expected: `200 OK` with a payment ID in the response.

Sample request body:

```json
{
  "paymentrequest": {
    "transaction_reference": "09-PYT-WQ-JHSDFR909202wfnvpkubv931455_4",
    "sender_account_uri": "tel:+254108989",
    "recipient_account_uri": "tel:+254068989",
    "payment_amount": {
      "amount": "100.25",
      "currency": "USD"
    },
    "payment_origination_country": "USA",
    "payment_type": "P2B",
    "source_of_income": "Sal",
    "sender": {
      "first_name": "John",
      "middle_name": "L",
      "last_name": "Doe",
      "nationality": "USA",
      "address": {
        "line1": "123 Main Street",
        "line2": "#5A",
        "city": "Arlington",
        "country_subdivision": "VA",
        "postal_code": "22207",
        "country": "USA"
      },
      "date_of_birth": "1980-01-20"
    },
    "recipient": {
      "first_name": "Lee",
      "last_name": "Cardholder",
      "address": {
        "line1": "123 Main Street",
        "city": "Arlington",
        "country_subdivision": "VA",
        "postal_code": "22207",
        "country": "CAN"
      },
      "email": "customer@gmail.com"
    }
  }
}
```

Sample `200 OK` response body:

```json
{
  "payment": {
    "transaction_reference": "09-PYT-WQ-JHSDFR909202wfnvpkubv931455_4",
    "status": "SUCCESS",
    "id": "rem_zoALfF30XHku95_NCWQvAS24d1M",
    "resource_type": "payment",
    "created": "2019-09-09T04:46:19-05:00",
    "status_timestamp": "2019-09-09T04:47:00-05:00",
    "fees_amount": {
      "currency": "USD",
      "amount": "5.35"
    },
    "charged_amount": {
      "currency": "USD",
      "amount": "100.25"
    },
    "credited_amount": {
      "currency": "GBP",
      "amount": "82.63"
    },
    "principal_amount": {
      "currency": "USD",
      "amount": "94.90"
    },
    "sender_account_uri": "tel:+254108989",
    "recipient_account_uri": "tel:+254068989",
    "payment_amount": {
      "currency": "USD",
      "amount": "100.25"
    },
    "payment_origination_country": "USA",
    "payment_type": "P2B",
    "source_of_income": "Sal",
    "fx_rate": "3.7833456828"
  }
}
```

**Additional: Retrieve the payment to confirm the record was created**

    GET https://sandbox.api.mastercard.com/send/v1/partners/{partner-id}/crossborder/{payment-id}

Expected: `200 OK` with full payment details.

Sample `200 OK` response body:

```json
{
  "payment": {
    "transaction_reference": "09-PYT-WQ-JHSDFR909202wfnvpkubv931455_4",
    "status": "SUCCESS",
    "id": "rem_zoALfF30XHku95_NCWQvAS24d1M",
    "resource_type": "payment",
    "created": "2019-09-09T04:46:19-05:00",
    "status_timestamp": "2019-09-09T04:47:00-05:00",
    "fees_amount": {
      "currency": "USD",
      "amount": "5.35"
    },
    "charged_amount": {
      "currency": "USD",
      "amount": "100.25"
    },
    "credited_amount": {
      "currency": "GBP",
      "amount": "82.63"
    },
    "principal_amount": {
      "currency": "USD",
      "amount": "94.90"
    },
    "sender_account_uri": "tel:+254108989",
    "recipient_account_uri": "tel:+254068989",
    "payment_amount": {
      "currency": "USD",
      "amount": "100.25"
    },
    "payment_origination_country": "USA",
    "payment_type": "P2B",
    "source_of_income": "Sal",
    "fx_rate": "3.7833456828"
  }
}
```

You can also use `GET .../crossborder?ref={payment-reference}` to retrieve a payment by partner transaction reference.

#### Submit a payment with a quote {#submit-a-payment-with-a-quote}

Request a quote to lock an FX rate before submitting the payment. In Sandbox, the rate returned is simulated.

**Step 1: Submit a quotes request**

    POST https://sandbox.api.mastercard.com/send/v1/partners/{partner-id}/crossborder/quotes

Sample request body:

```json
{
  "quoterequest": {
    "transaction_reference": "08-DXF-CA-UERTYGH2909202wfnvpobv00734ACFQ",
    "sender_account_uri": "tel:+25406005",
    "recipient_account_uri": "tel:+254069832",
    "payment_amount": {
      "amount": "105.15",
      "currency": "USD"
    },
    "payment_origination_country": "USA",
    "payment_type": "P2P",
    "quote_type": {
      "forward": {
        "receiver_currency": "GBP"
      }
    }
  }
}
```

Sample `200 OK` response body. Capture `proposals.proposal.id` for the next step:

```json
{
  "quote": {
    "transaction_reference": "08-DXF-CA-UERTYGH2909202wfnvpobv00734ACFQ",
    "payment_type": "P2P",
    "proposals": {
      "proposal": {
        "id": "pen_40000796299942448699062004",
        "resource_type": "proposal",
        "fees_included": "true",
        "charged_amount": {
          "currency": "USD",
          "amount": "5.25"
        },
        "credited_amount": {
          "currency": "GBP",
          "amount": "82.63"
        },
        "principal_amount": {
          "currency": "USD",
          "amount": "110.50"
        },
        "expiration_date": "2019-09-09T02:12:11-05:00",
        "quote_fx_rate": "3.7833456828"
      }
    }
  }
}
```

**Step 2: Submit the payment using the proposal ID**

    POST https://sandbox.api.mastercard.com/send/v1/partners/{partner-id}/crossborder/payment

Include `"proposal_id": "pen_40000796299942448699062004"` (the `id` from the quotes response) in the payment request body. Expected: `200 OK` with payment ID.

See [Payment with Quote](https://developer.mastercard.com/cross-border-services/documentation/use-cases/payment-with-quote/index.md) for the full API sequence.

### Endpoint tutorials {#endpoint-tutorials}

* [API Tutorial using OAuth 1.0a](https://developer.mastercard.com/cross-border-services/documentation/tutorials/api-sdk-tutorial/index.md)
* [API Tutorial: OAuth 2.0 Request Token](https://developer.mastercard.com/cross-border-services/documentation/tutorials/oauth2-api-sdk-tutorial-request-token/index.md)
* [API Tutorial: OAuth 2.0 Access Token](https://developer.mastercard.com/cross-border-services/documentation/tutorials/oauth2-api-sdk-tutorial-access-token/index.md)

## Negative testing {#negative-testing}

Negative testing confirms that invalid requests fail cleanly and return useful error details.

### Validate these behaviors {#validate-these-behaviors-1}

* Missing required fields return `400 Bad Request`.
* Invalid field values return validation errors with a clear error structure.
* Requests for unknown or malformed payment IDs return `404 Not Found`.
* Incorrect or missing authentication data is rejected with `401 Unauthorized`.
* Submitting a payment with a duplicate `transaction_reference` returns `409 Conflict`.

### Negative test cases {#negative-test-cases}

#### Missing required field {#missing-required-field}

Submit a payment without a required field such as `transaction_reference`:

```json
{
  "paymentrequest": {
    "sender_account_uri": "tel:+254108989",
    "recipient_account_uri": "tel:+254068989",
    "payment_amount": {
      "amount": "100.25",
      "currency": "USD"
    },
    "payment_origination_country": "USA",
    "payment_type": "P2B"
  }
}
```

Expected: `400 Bad Request` indicating the missing or invalid field.

![400-error](https://static.developer.mastercard.com/content/cross-border-services/uploads/400-bad-req.png)

#### Invalid payment ID {#invalid-payment-id}

Retrieve a payment using a non-existent or malformed payment ID:

    GET https://sandbox.api.mastercard.com/send/v1/partners/{partner-id}/crossborder/invalid-id

Expected: `404 Not Found`.

#### Duplicate transaction reference {#duplicate-transaction-reference}

Submit two payments using the same `transaction_reference`:

Expected: `409 Conflict`.

#### Missing or invalid authentication {#missing-or-invalid-authentication}

Send a request without the required OAuth Authorization header or with an invalid signature:

Expected: `401 Unauthorized`.

### Example error responses {#example-error-responses}

Each failed request returns an `Errors` object containing one or more `Error` entries. Use the `ReasonCode`, `Description`, and `ErrorDetailCode` values to diagnose the failure.

**400 Bad Request** , a single field fails validation (`INVALID_INPUT_FORMAT`):

```json
{
  "Errors": {
    "Error": [
      {
        "Source": "document_id",
        "RequestId": "0.2567d117.1788264304.dd253282",
        "ReasonCode": "INVALID_INPUT_FORMAT",
        "Description": "Value contains invalid character",
        "Recoverable": false,
        "Details": {
          "Detail": {
            "Name": "ErrorDetailCode",
            "Value": "062000"
          }
        }
      }
    ]
  }
}
```

**400 Bad Request** , multiple fields fail validation (each returned as a separate `Error` entry):

```json
{
  "Errors": {
    "Error": [
      {
        "RequestId": "460059370",
        "Source": "sender.address.country",
        "ReasonCode": "INVALID_INPUT_FORMAT",
        "Description": "Value contains invalid character",
        "Recoverable": "false",
        "Details": {
          "Detail": {
            "Name": "ErrorDetailCode",
            "Value": "062000"
          }
        }
      },
      {
        "RequestId": "460059370",
        "Source": "recipient.address.country",
        "ReasonCode": "INVALID_INPUT_FORMAT",
        "Description": "Value contains invalid character",
        "Recoverable": "false",
        "Details": {
          "Detail": {
            "Name": "ErrorDetailCode",
            "Value": "062000"
          }
        }
      }
    ]
  }
}
```

**401 Unauthorized** , authentication fails (`AUTHORIZATION_FAILED`):

```json
{
  "Errors": {
    "Error": [
      {
        "Source": "SYSTEM",
        "RequestId": "0.2567d117.1788245751.d61e2194",
        "ReasonCode": "AUTHORIZATION_FAILED",
        "Description": "Unauthorized Access",
        "Recoverable": "false",
        "Details": {
          "Detail": {
            "Name": "ErrorDetailCode",
            "Value": "050007"
          }
        }
      }
    ]
  }
}
```

**500 Internal Server Error** , the requested resource cannot be found (`RESOURCE_UNKNOWN`):

```json
{
  "Errors": {
    "Error": {
      "RequestId": "460058536",
      "Source": "GetPayment",
      "ReasonCode": "RESOURCE_UNKNOWN",
      "Description": "Record not found",
      "Recoverable": "false",
      "Details": {
        "Detail": {
          "Name": "ErrorDetailCode",
          "Value": "110507"
        }
      }
    }
  }
}
```

For the complete list of response codes and error structures, see the [Response Codes and Error Codes](https://developer.mastercard.com/cross-border-services/documentation/code-and-formats/index.md) section.

## Testing in MTF {#testing-in-mtf}

The Mastercard Test Facility (MTF) is a pre-production environment with access to more powerful testing tools, such as payment test harnesses. Use MTF after Sandbox testing is complete and your contract is signed.

To request MTF access:

1. Go to your **My Projects** page and select your project.
2. Copy the consumer key from the Sandbox keys section.
3. Send an email to your assigned Mastercard Implementation Manager with your Sandbox consumer key to request access to the MTF environment.

Your Mastercard Implementation Manager will create a test plan and test cases for testing in the MTF environment.

For the full step-by-step process of requesting and preparing for MTF, see the [MTF Access Guide](https://developer.mastercard.com/cross-border-services/documentation/tutorials/guide-mtf-access/index.md).

For environment base URLs and descriptions, see [API Basics - Environment Descriptions](https://developer.mastercard.com/cross-border-services/documentation/api-basics/index.md#environment-descriptions).

### Next steps {#next-steps}

* Consult the [API Reference](https://developer.mastercard.com/cross-border-services/documentation/api-ref/index.md) for complete endpoint specifications, request and response schemas, and environment URLs.
* If you encounter issues, visit [Support](https://developer.mastercard.com/cross-border-services/documentation/support/index.md) for FAQs and troubleshooting guidance.
