# Testing
source: https://developer.mastercard.com/commercial-connect-api/documentation/testing/index.md

Use this page to plan and execute Sandbox validation for the Mastercard Commercial Connect API. It covers the recommended workflow, positive and negative coverage, and the reference guides you need for endpoint-level execution.
Tip: Start all validation in Sandbox before moving to Production.

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

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

* [Postman Collection](https://developer.mastercard.com/commercial-connect-api/documentation/developer-tools/postman-collection/index.md) --- pre-built requests with OAuth configured.
* [Insomnia Collection](https://developer.mastercard.com/commercial-connect-api/documentation/developer-tools/insomnia-collection/index.md) --- an alternative API client with a ready-to-use workspace.
* [Reference Application](https://developer.mastercard.com/commercial-connect-api/documentation/developer-tools/reference-app/index.md) --- a working implementation you can run and inspect.
* Custom API client generated as per the guidance in [API Basics](https://developer.mastercard.com/commercial-connect-api/documentation/api-basics/index.md#how-to-consume-the-api).

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

Use this sequence to validate the main endpoint families with a realistic flow:

1. Get entity details.
2. Register a real card.
3. Create a virtual card.
4. Update virtual card controls.
5. Get virtual card.

This flow gives you coverage across create, update, and get card details behavior.

## 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 success codes, such as `200 OK`, `201 Created`, or `204 No Content`.
* Created resources can be retrieved by ID or found through search.
* Updates persist and can be verified with a follow-up GET.
* Search and filter parameters return the expected subset of records.

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

Use the tabs below to view representative positive test cases for each endpoint family.
`GET /hierarchies/entities`

```json
{
  "entityId": "SENTTY5BA786294AB086E21DDB7096803ADA57AB4A3895F5E3FB4D3BB34DCF2656B0951607065524",
  "entityParentId": "SENTTY27A8719BE0A622F48E2A0AF1AE713171175AD8B3D4FAC64183E12F6D606385C71519036959",
  "entityName": "ABC Enterprises",
  "entityNameLine2": "ABC Travel",
  "entityType": "COMPANY",
  "entityStatus": "ACTIVE",
  "ica": 1902,
  "corpNumber": "123456789",
  "createdDate": "2020-10-06T11:09:42.100Z"
}
```

Expected result: `200 OK` and a response body containing a generated `entityId`.
`POST /accounts/real-cards`

```json
{
  "entityId": "SENTTY5BA786294AB086E21DDB7096803ADA57AB4A3895F5E3FB4D3BB34DCF2656B0951607065524",
  "cardDetails": {
    "cardExpiration": "2031-11",
    "cardNumber": "5234567890123456",
    "nameOnCard": "John Doe"
  },
  "cardControls": [
    {
      "alias": "Control Rule Alias",
      "transactionLimit": {
        "spendAmount": 500
      },
      "continuousLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "dailyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "weeklyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "monthlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "quarterlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "yearlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "agingLimit": {
        "authorizationHoldDays": 1234,
        "spendAmount": 1000,
        "timeZone": "UTC",
        "currencyType": "MERCHANT",
        "currencyCode": "825"
      },
      "timeOfDay": {
        "times": [
          {
            "day": "SUNDAY",
            "fromTime": "08:21",
            "toTime": "21:00"
          }
        ],
        "timeZone": "UTC",
        "negate": true
      },
      "countries": {
        "countryCodes": [
          "123",
          "456"
        ],
        "negate": true
      },
      "merchantCategoryCodes": {
        "mccs": [
          "3001",
          "3005"
        ],
        "negate": true
      },
      "validityPeriod": {
        "startDate": "2020-10-06T11:09:42.000Z",
        "endDate": "2020-11-06T11:09:42.000Z"
      },
      "merchantId": {
        "merchantIds": [
          {
            "merchantId": "123456789012345",
            "acquirerId": "3"
          }
        ],
        "negate": true
      },
      "merchantName": {
        "merchantNames": [
          "Amazon"
        ],
        "negate": true
      },
      "amountRange": {
        "minAmount": 1000,
        "maxAmount": 10000
      }
    }
  ],
  "accountContacts": [
    {
      "firstName": "John",
      "middleInitial": "Š",
      "lastName": "Doe",
      "nameSuffix": "Jr",
      "address": {
        "addressLine1": "8589 Lexington Drive",
        "addressLine2": "Temple Hills",
        "addressLine3": "Brooklyn",
        "poBoxNumber": "1234",
        "city": "New York",
        "countrySubdivision": "D",
        "postalCode": "NY 11215",
        "countryCode": "840"
      }
    }
  ]
}
```

Expected result: `201 Created` and a body containing the `entity_id, cardDetails, cardControls, accountDetails`.

Additional checks:

* `GET /accounts/real-cards/{account_id}` returns `200 OK` and the details of an existing real card.
`POST /accounts/virtual-cards`

```json
{
  "entityId": "SENTTY5BA786294AB086E21DDB7096803ADA57AB4A3895F5E3FB4D3BB34DCF2656B0951607065524",
  "cardDetails": {
    "cardExpiration": "2031-11",
    "realCardId": "0ENTf68c76b4884e95ec3f10593c4c1a23daa35d76dc285b4fbf4a336f7140f86ec21742325306"
  },
  "cardControls": [
    {
      "alias": "Control Rule Alias",
      "transactionLimit": {
        "spendAmount": 500
      },
      "continuousLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "dailyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "weeklyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "monthlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "quarterlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "yearlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "agingLimit": {
        "authorizationHoldDays": 1234,
        "spendAmount": 1000,
        "timeZone": "UTC",
        "currencyType": "MERCHANT",
        "currencyCode": "825"
      },
      "timeOfDay": {
        "times": [
          {
            "day": "SUNDAY",
            "fromTime": "08:21",
            "toTime": "21:00"
          }
        ],
        "timeZone": "UTC",
        "negate": true
      },
      "countries": {
        "countryCodes": [
          "123",
          "456"
        ],
        "negate": true
      },
      "merchantCategoryCodes": {
        "mccs": [
          "3001",
          "3005"
        ],
        "negate": true
      },
      "validityPeriod": {
        "startDate": "2020-10-06T11:09:42.000Z",
        "endDate": "2020-11-06T11:09:42.000Z"
      },
      "merchantId": {
        "merchantIds": [
          {
            "merchantId": "123456789012345",
            "acquirerId": "3"
          }
        ],
        "negate": true
      },
      "merchantName": {
        "merchantNames": [
          "Amazon"
        ],
        "negate": true
      },
      "amountRange": {
        "minAmount": 1000,
        "maxAmount": 10000
      }
    }
  ],
  "cardCDFData": {
    "alias": "June Travel Expenses",
    "fields": [
      {
        "name": "myName",
        "value": "myValue"
      }
    ]
  }
}
```

Expected result: `201 Created` and virtual card details.

Additional checks:

* `GET /virtual-cards/{account_id}` returns `200 OK` and virtual card details, usage controls, and card data for an existing virtual card.
`PUT /accounts/virtual-cards/{account_id}/card-controls`

```json
{
  "cardControls": [
    {
      "alias": "Control Rule Alias",
      "transactionLimit": {
        "spendAmount": 500
      },
      "continuousLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "dailyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "weeklyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "monthlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "quarterlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "yearlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      },
      "agingLimit": {
        "authorizationHoldDays": 1234,
        "spendAmount": 1000,
        "timeZone": "UTC",
        "currencyType": "MERCHANT",
        "currencyCode": "825"
      },
      "timeOfDay": {
        "times": [
          {
            "day": "SUNDAY",
            "fromTime": "08:21",
            "toTime": "12:50"
          }
        ],
        "timeZone": "UTC",
        "negate": true
      },
      "countries": {
        "countryCodes": [
          "123",
          "456"
        ],
        "negate": true
      },
      "merchantCategoryCodes": {
        "mccs": [
          "3001",
          "3005"
        ],
        "negate": true
      },
      "validityPeriod": {
        "startDate": "2020-10-06T11:09:42.000Z",
        "endDate": "2020-11-06T11:09:42.000Z"
      },
      "merchantId": {
        "merchantIds": [
          {
            "merchantId": "123456789012345",
            "acquirerId": "3"
          }
        ],
        "negate": true
      },
      "merchantName": {
        "merchantNames": [
          "Amazon"
        ],
        "negate": true
      },
      "amountRange": {
        "minAmount": 1000,
        "maxAmount": 10000
      }
    }
  ]
}
```

Expected result: `204` to update authorization controls on a virtual card.
`GET /accounts/virtual-cards/{account_id}`

```json
{
  "accountId": "0ENT4e2b4ed60c269e15f2b876d43e35ef01c18e2e8f7792256eb58b40113ff2c7f81740158316",
  "entityId": "SENTTY5BA786294AB086E21DDB7096803ADA57AB4A3895F5E3FB4D3BB34DCF2656B0951607065524",
  "accountStatus": "ACTIVE",
  "createdDate": "2020-10-06T11:09:42.100Z",
  "lastUpdatedDate": "2020-10-06T11:09:42.100Z",
  "cardDetails": {
    "cardExpiration": "2031-11",
    "accountBillingCurrency": "EUR",
    "realCardId": "0ENTf68c76b4884e95ec3f10593c4c1a23daa35d76dc285b4fbf4a336f7140f86ec21742325306",
    "cvv": "123",
    "cardNumber": "xxxxxxxxxxxx4456"
  },
  "cardControls": [
    {
      "alias": "Control Rule Alias",
      "transactionLimit": {
        "spendAmount": 500
      },
      "continuousLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "dailyLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "weeklyLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "monthlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "quarterlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "yearlyLimit": {
        "transactionCount": 12,
        "spendAmount": 500,
        "availableBalance": 500
      },
      "agingLimit": {
        "authorizationHoldDays": 1234,
        "spendAmount": 1000,
        "timeZone": "UTC",
        "currencyType": "MERCHANT",
        "currencyCode": "825",
        "availableBalance": 500
      },
      "timeOfDay": {
        "times": [
          {
            "day": "SUNDAY",
            "fromTime": "08:21",
            "toTime": "12:50"
          }
        ],
        "timeZone": "UTC",
        "negate": true
      },
      "countries": {
        "countryCodes": [
          "123",
          "456"
        ],
        "negate": true
      },
      "merchantCategoryCodes": {
        "mccs": [
          "3001",
          "3005"
        ],
        "negate": true
      },
      "validityPeriod": {
        "startDate": "2020-10-06T11:09:42.000Z",
        "endDate": "2020-11-06T11:09:42.000Z"
      },
      "merchantId": {
        "merchantIds": [
          {
            "merchantId": "123456789012345",
            "acquirerId": "3"
          }
        ],
        "negate": true
      },
      "merchantName": {
        "negate": true,
        "merchantNames": [
          "Amazon"
        ]
      },
      "amountRange": {
        "minAmount": 1000,
        "maxAmount": 10000
      }
    }
  ],
  "cardCDFData": {
    "alias": "June Travel Expenses",
    "fields": [
      {
        "name": "myName",
        "value": "myValue"
      }
    ]
  }
}
```

Expected result: `200 OK` and virtual card details, usage controls and card data for an existing virtual card.

### Endpoint use cases {#endpoint-use-cases}

Use cases provide full request examples and endpoint-specific flows:

* [Real Cards](https://developer.mastercard.com/commercial-connect-api/documentation/use-cases/rc/index.md)
* [Virtual Cards](https://developer.mastercard.com/commercial-connect-api/documentation/use-cases/vcn/index.md)
* [Card Controls](https://developer.mastercard.com/commercial-connect-api/documentation/use-cases/card-controls/index.md)
* [Entity Hierarchy](https://developer.mastercard.com/commercial-connect-api/documentation/use-cases/entity-hierarchy/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 `ReasonCode` and description.
* Requests for unknown resources return `404 Not Found`.
* Incorrect or missing authentication data is rejected.

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

Use the tabs below to view representative negative test cases for each endpoint family.
`GET /hierarchies/entities`

```http
GET /commercial/hierarchies/entities HTTP/1.1
Host: {host}
Content-Type: application/json
Authorization: OAuth {OAuth1.0_credentials}
```

Expected result: `400 Not Authorized` because access is not granted for that `entityId`.
Note: The gateway error will occur in these cases:

* If the project is not live
* If you have the incorrect registration token
* If your OAuth 1.0a is not correct

You will also encounter an error if your Commercial Products implementation manager has not set up the entity for you. In that case, you will need to contact your Commercial Products implementation manager.
`POST /accounts/real-cards`

```json
{
  "entityId": "{entityId}",
  "cardDetails": {
    "cardNumber": "{cardNumber}",
    "cardExpiration": "2031-05",
    "nameOnCard": "Emfi Test"
  },
  "cardControls": [
    {
      "continuousLimit": {
        "transactionCount": 12,
        "spendAmount": 500
      }
    }
  ],
  "accountContacts": [
    {
      "firstName": "John",
      "lastName": "Doe",
      "address": {
        "addressLine1": "123 Main St",
        "city": "New York",
        "countryCode": "840",
        "postalCode": "10001"
      }
    }
  ]
}
```

Expected result: `422 Unprocessable Entity` because the card number is already present and no duplicate card numbers are allowed.
Note: If you get a gateway error, it can be the result of:

* The project is not live
* You have the incorrect registration token
* Your OAuth 1.0a is not correct

You will also encounter an error if your test card number does not match the card number provided to you by your Commercial Products implementation manager. Also, ensure that the entity ID you are using match the entity ID you retrieved from `GET /hierarchies/entities` call.
`POST /accounts/virtual-cards`

```json
{
  "cardDetails": {
    "realCardId": "{realCardIdOwnedByDifferentHierarchy}",
    "cardExpiration": "2027-05"
  },
  "cardControls": [
    {
      "continuousLimit": {
        "transactionCount": 1000,
        "spendAmount": 500.12
      },
      "dailyLimit": {
        "transactionCount": 1,
        "spendAmount": 10
      }
    }
  ]
}
```

Expected result: `422 Unprocessable Entity` because the real card is not found.
`PUT /accounts/virtual-cards/{account_id}/card-controls`

```json
{
  "cardControls": [
    {
      "continuousLimit": {
        "transactionCount": 1000,
        "spendAmount": 50000
      },
      "dailyLimit": {
        "transactionCount": 1,
        "spendAmount": 10.12
      },
      "weeklyLimit": {
        "transactionCount": 7,
        "spendAmount": 70
      },
      "monthlyLimit": {
        "transactionCount": 30,
        "spendAmount": 300
      },
      "quarterlyLimit": {
        "transactionCount": 120,
        "spendAmount": 1200
      },
      "yearlyLimit": {
        "transactionCount": 365,
        "spendAmount": 3650
      }
    }
  ]
}
```

Expected result: `404 Not found` because the virtual card is not recognized because the details field is not populated.

Additional checks:

* `PUT /accounts/virtual-cards/{account_id}/card-controls` returns `404 RESOURCE NOT FOUND`.
`GET /accounts/virtual-cards/{account_id}`

```http
GET /commercial/accounts/virtual-cards/{nonExistentVirtualCardId} HTTP/1.1
Host: {host}
Content-Type: application/json
Authorization: OAuth {OAuth1.0_credentials}
```

Expected result: `404 Not found` because the card is not found.

Additional checks:

* `GET /accounts/virtual-cards/{account_id}` returns `401 Unauthorized - access not granted`.

For the complete list of response codes, reason codes, and formatting rules, see [Codes and Formats](https://developer.mastercard.com/commercial-connect-api/documentation/code-and-formats/index.md).

### Next steps {#next-steps}

* See the [API Reference](https://developer.mastercard.com/commercial-connect-api/documentation/api-reference/index.md) for complete endpoint specifications, request and response schemas, and environment URLs.
* See the [Code and Formats](https://developer.mastercard.com/commercial-connect-api/documentation/code-and-formats/index.md) for a complete list of error codes by endpoint.
* If you run into issues, visit [Support](https://developer.mastercard.com/commercial-connect-api/documentation/support/index.md) for FAQs and troubleshooting guidance.
