# Integrate and Test the Loyalty Transaction Service API
source: https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/api-testing-tutorial/index.md

Integrate Loyalty Transactions Service into a rewards application and test account-level transaction searches in Sandbox. Use Postman for a first request or generate a Java client for your backend. Both paths retrieve transaction history and points earned through `POST /transactions/searches`.

For the account-page integration, follow [Display a rewards activity feed](https://developer.mastercard.com/transactions-service/documentation/use-cases/transaction-details-service/index.md#display-a-rewards-activity-feed) to map response fields, paginate, and handle empty or incomplete results. For loyalty-program validation, compare [base and bonus credits](https://developer.mastercard.com/transactions-service/documentation/use-cases/transaction-details-service/index.md#verify-base-and-bonus-rewards-credits) against known test-account activity. API response validation and program-rule validation are separate checks.

## Introduction {#introduction}

This tutorial helps you to create a simple Java application that makes an API call to the Loyalty Transactions Service in the Sandbox environment.

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

|        Method         |                                                                                                                                                                    Start here                                                                                                                                                                    |                                                                                                                 Validate the result                                                                                                                 |
|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Postman               | Follow the [Quick Start Guide](https://developer.mastercard.com/transactions-service/documentation/quick-start-guide/index.md) for project access, request signing, and a complete Sandbox request. The [Postman Collection](https://developer.mastercard.com/transactions-service/documentation/postman-collection/index.md) is also available. | Run the success assertions in the quick start, then the [missing-field test](https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/api-testing-tutorial/index.md#test-a-missing-required-field) below.           |
| Generated Java client | Follow [Environment Set up](https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/api-testing-tutorial/index.md#environment-set-up), generate the client, and configure authentication below. Set `basePath` to `https://sandbox.api.mastercard.com/loyalty/mrs`.                                             | Use [Validate a Successful Response](https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/api-testing-tutorial/index.md#validate-a-successful-response), then repeat the missing-field test through the client. |

Both routes require enabled Sandbox credentials and an available test account. See [Create a Sandbox Project](https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/sandbox-access-tutorial/index.md) before starting.

### What you will learn {#what-you-will-learn}

* How to set up the environment to develop a simple Java application
* How to generate an API client using the [OpenAPI Generator](https://openapi-generator.tech/)
* How to make an API call

### Estimated time to complete this tutorial {#estimated-time-to-complete-this-tutorial}

* 15-20 minutes

### Prerequisites {#prerequisites}

To complete this tutorial, you will need:

* [JDK 11](https://www.java.com/en/) or later
* An IDE of your choice
* Mastercard Developers account with access to the MRS Transactions API
* MRS Transactions Open API specification (Refer to the [Open Specification](https://developer.mastercard.com/transactions-service/documentation/api-reference/index.md) for details.)

Note: Refer to the [API Reference](https://developer.mastercard.com/transactions-service/documentation/api-reference/index.md) page for more details on each API and related parameters.

## Environment Set up {#environment-set-up}

### 1. Create a Maven Project {#1-create-a-maven-project}

* In the IDE, create a new Maven project which sets your directory structure automatically. ![Create maven project](https://static.developer.mastercard.com/content/transactions-service/img/newmaven.png)
* Provide an ArtifactId and a project name as per your choice. ![Add project name](https://static.developer.mastercard.com/content/transactions-service/img/artifactId.png)

### 2. Add Resources {#2-add-resources}

* Add the Transactions API specification to your Maven project resources folder.
* Add the generated Sandbox key (**.p12 file** ) and encryption cert (**.pem file**) to your Maven project resources folder. (This is generated while creating the project on Mastercard Developers).
* Your Maven project directory structure should appear as: ![Maven structure](https://static.developer.mastercard.com/content/transactions-service/img/mavenstructure.png)

### 3. Update pom.xml file {#3-update-pomxml-file}

* In your IDE, add the [OpenAPI Generator maven plugin](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin) to your project **pom.xml** file. Use the Plugin config as shown below: Note: [OpenAPI Generator](https://openapi-generator.tech/) generates API client libraries using OpenAPI Specification. It provides multiple generators and library templates to support multiple languages and frameworks. We will be using the Java generator for this project.

```XML
<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>4.2.2</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>${project.basedir}/src/main/resources/mrs-transactions-api-openapi-v3.yaml</inputSpec>
                <generatorName>java</generatorName>
                <configOptions>
                    <sourceFolder>src/gen/java/main</sourceFolder>
                    <java11>true</java11>
                    <dateLibrary>custom</dateLibrary>
                </configOptions>
                <typeMappings>
                    <typeMapping>Date=String</typeMapping>
                </typeMappings>
            </configuration>
        </execution>
    </executions>
</plugin>
```

* Add the following dependencies to your pom.xml file to add dependencies for the API client library generation and the Mastercard OAuth1 Signer library.

```XML
<properties>
       <!-- Dependencies used by the generated sources -->
       <gson-fire-version>1.8.3</gson-fire-version>
       <swagger-core-version>1.5.22</swagger-core-version>
       <okhttp-version>3.14.2</okhttp-version>
       <gson-version>2.8.5</gson-version>
       <threetenbp-version>1.3.8</threetenbp-version>
       <javax-annotation-version>1.0</javax-annotation-version>
       <junit-version>4.12</junit-version>
   </properties>
 
   <dependencies>
       <dependency>
           <groupId>io.swagger</groupId>
           <artifactId>swagger-annotations</artifactId>
           <version>${swagger-core-version}</version>
       </dependency>
       <dependency>
           <groupId>com.squareup.okhttp3</groupId>
           <artifactId>okhttp</artifactId>
           <version>${okhttp-version}</version>
       </dependency>
       <dependency>
           <groupId>com.squareup.okhttp3</groupId>
           <artifactId>logging-interceptor</artifactId>
           <version>${okhttp-version}</version>
       </dependency>
       <dependency>
           <groupId>com.google.code.gson</groupId>
           <artifactId>gson</artifactId>
           <version>${gson-version}</version>
       </dependency>
       <dependency>
           <groupId>io.gsonfire</groupId>
           <artifactId>gson-fire</artifactId>
           <version>${gson-fire-version}</version>
       </dependency>
       <dependency>
           <groupId>org.threeten</groupId>
           <artifactId>threetenbp</artifactId>
           <version>${threetenbp-version}</version>
       </dependency>
       <dependency>
           <groupId>javax.annotation</groupId>
           <artifactId>jsr250-api</artifactId>
           <version>${javax-annotation-version}</version>
       </dependency>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>${junit-version}</version>
       </dependency>
       <dependency>
           <groupId>com.mastercard.developer</groupId>
           <artifactId>oauth1-signer</artifactId>
           <version>1.2.4</version>
       </dependency>
 
   </dependencies>
```

When using OpenAPI Generator to generate the API client library, you have two options:

* Generate and use the source files on the fly
* Generate and deploy the source files to a Maven repository

<br />

In this tutorial, you will be generating the API client library on the fly, so you include the dependencies that are needed to generate the library. (If you were deploying the source files to a Maven repository, you would only need to include the dependency for that repository.)

In addition, you include the dependency for one of the Mastercard OAuth1 Signer libraries. Mastercard offers OAuth1 Signer Libraries that are developed and maintained by Mastercard's API team, which offer code helpers targeting the HTTP clients used by the different OpenAPI Generator Library templates. The libraries are hosted on [Github](https://github.com/Mastercard?utf8=%E2%9C%93&q=oauth1-signer&type=&language=).

Refer to the following page for more information on [Generating and Configuring a Mastercard API Client](https://developer.mastercard.com/platform/documentation/security-and-authentication/generating-and-configuring-a-mastercard-api-client/#overview).

## Generating the API Client {#generating-the-api-client}

1. Now that you have all the dependencies you need, you can generate the source code. You can navigate to the project root directory within a terminal window and run `mvn clean compile `. ![clean](https://static.developer.mastercard.com/content/transactions-service/img/clean.png)

![install](https://static.developer.mastercard.com/content/transactions-service/img/install.png)
2. Alternatively, you can navigate to the root directory of the project within a terminal window and run mvn clean compile.
![compile](https://static.developer.mastercard.com/content/transactions-service/img/compile.png)

3. A folder named **target** is created within your root directory which contains classes generated for the schemas and API calls defined within the OpenAPI Specification. The generated classes can be found in the target folder as shown below: ![classes](https://static.developer.mastercard.com/content/transactions-service/img/classes.png)

## Making an API Call {#making-an-api-call}

1. Under the `src/main/java/` folder path, create a Java file named **ApiClientConfiguration.java**.
2. To make the API call, you need to make your OAuth credentials available to the program for use.

* A PrivateKey is created with the provided credentials for later use.
* AuthenticationUtils is provided by the Mastercard OAuth signing library.

Note: Calling `loadSigningKey` can throw an exception.

```java
 // Read these values from application properties file
   @Value("${mastercard.api.key.alias}")
   private String signingKeyAlias;
 
   @Value("${mastercard.api.keystore.password}")
   private String signingKeyPassword;
 
   @Value("${mastercard.api.p12.path}")
   private String signingKeyPkcs12FileName;
            
   PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyPkcs12FileName, signingKeyAlias, signingKeyPassword);
```

<br />

3. Instantiate a client with your authentication credentials and configuration object as interceptors before you can send it.

```java
  apiClient = new ApiClient();
    apiClient.setBasePath("https://sandbox.api.mastercard.com/loyalty/mrs");
    apiClient.setDebugging(false);

  OkHttpClient.Builder okHttpClientBuilder = apiClient.getHttpClient().newBuilder();
  okHttpClientBuilder.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey));

  return apiClient.setHttpClient(okHttpClientBuilder.build());
```

Note: For conciseness, only the barebones of what is needed to make the API call is shown above. The full contents of ApiClientConfiguration.java is shown below.

### Contents of ApiClientConfiguration.java {#contents-of-apiclientconfigurationjava}

```java
package com.mastercard.developer.config;
 
import com.mastercard.developer.interceptors.OkHttpOAuth1Interceptor;
import com.mastercard.developer.utils.AuthenticationUtils;
import java.security.PrivateKey;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.openapitools.client.ApiClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
@Service
@Slf4j
public class ApiClientConfiguration {
 
 
    @Value("${mastercard.api.consumer.key}")
    public String consumerKey;
    @Value("${basePath}")
    private String basePath;
    @Value("${mastercard.api.key.alias}")
    private String signingKeyAlias;
 
    @Value("${mastercard.api.keystore.password}")
    private String signingKeyPassword;
 
    @Value("${mastercard.api.p12.path}")
    private String signingKeyPkcs12FileName;
 
    private ApiClient apiClient = null;
 
    public ApiClient getApiClient() {
        createNewApiClient();
        return apiClient;
    }
 
    public ApiClient createNewApiClient() {
        apiClient = new ApiClient();
        try {
 
            PrivateKey signingKey = AuthenticationUtils.loadSigningKey(signingKeyPkcs12FileName, signingKeyAlias, signingKeyPassword);
            apiClient.setBasePath(basePath);
            apiClient.setDebugging(false);
            OkHttpClient.Builder okHttpClientBuilder = apiClient.getHttpClient().newBuilder();
 
            okHttpClientBuilder.addInterceptor(new OkHttpOAuth1Interceptor(consumerKey, signingKey));
 
            return apiClient.setHttpClient(okHttpClientBuilder.build());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return apiClient;
    }
 
}
```

<br />

4. Now put everything together and you can start using the APIs by making use of the generated classes.

```java
@ApiOperation(value = "transactionSearches API Call", notes = "Fetches the transaction details for a given search criteria. Each account can have multiple Transactions.",
            tags = {"transactions"}
    )
    @PostMapping(value = "/transactions/searches")
    public TransactionsDetails getTransactions(@RequestBody SearchTransactions request) {
        TransactionsDetails transactionsSearchDetails;
        try {
            log.info("Method : transactionSearches, Message : Fetches the transaction details for a given search criteria");
            ApiClient apiClient = apiClientConfiguration.createNewApiClient();
            TransactionsApi transactionsApi = getTransactionsApi(apiClient);
            transactionsSearchDetails = transactionsApi.transactionsSearches(request);
        } catch (ApiException e) {
            throw new InvalidRequest(e.getMessage(), e.getResponseBody());
        }
        log.debug("Method : transactionSearches, Message: Successfully fetched Search result of the transactions");
        return transactionsSearchDetails;
    }
 
    public TransactionsApi getTransactionsApi(ApiClient apiClient) {
        return new TransactionsApi(apiClient);
    }
}
```

Tip: Refer to the following [reference app](https://developer.mastercard.com/transactions-service/documentation/reference-app/index.md) for more details.

## Validate a Successful Response {#validate-a-successful-response}

Use the complete request and executable Postman checks in [Sandbox First Call](https://developer.mastercard.com/transactions-service/documentation/quick-start-guide/index.md#sandbox-first-call). For a generated Java client, inspect the HTTP status through the generated response wrapper (the `transactionsSearchesWithHttpInfo` method when available), or record the status in your HTTP client without logging credentials or account data.

1. Expect HTTP `200 OK` with a JSON transaction-details object, not an `Errors` wrapper.
2. Check returned `accountId` against the requested RANAC when present. Inspect `transactions` for transaction dates, amounts, and `basePointsEarned`; compare with the known activity for your test account.
3. Check pagination fields when returned: `count` is the number of items in `transactions`, and `limit` is between 1 and 25. An empty array can be a valid result when no activity matches. The schema does not require every response property, so do not treat absent optional properties as an automatic API failure.
4. Record the environment, test account alias, timestamp, status, and pass/fail outcome. Keep real identifiers and credentials out of shared logs. Use the [API Reference](https://developer.mastercard.com/transactions-service/documentation/api-reference/index.md) for the complete response schema.

## Test a Missing Required Field {#test-a-missing-required-field}

Run this test only in Sandbox after a successful authenticated call, so an authentication failure does not mask request validation.

1. Duplicate the successful `POST /transactions/searches` request, keeping its URL, headers, and authentication. Replace the body with the following JSON, omitting the required `userId`:

```json
{
    "userIdType": "RANAC"
}
```

2. Remove the copied success assertions from the duplicate and add these Postman post-response tests:

```javascript
pm.test("Missing userId returns HTTP 400", () => {
    pm.response.to.have.status(400);
});
pm.test("Error identifies a missing required field", () => {
    const errors = pm.response.json().Errors.Error;
    pm.expect(errors).to.be.an("array").that.is.not.empty;
    const missingField = errors.find(error => error.ReasonCode === "MISSING_REQUIRED_FIELD");
    pm.expect(missingField).to.be.an("object");
    pm.expect(missingField.Recoverable).to.equal(false);
});
```

3. Send the request with a fresh signature or DPoP proof. The OpenAPI specification documents HTTP `400` with this error example:

```json
{
    "Errors": {
        "Error": [
            {
                "Source": "mrs-transactions-api",
                "ReasonCode": "MISSING_REQUIRED_FIELD",
                "Description": "UserId cannot be null or empty.",
                "Recoverable": false
            }
        ]
    }
}
```

4. Read `Description` to identify the missing field. Restore the available Sandbox RANAC as `userId`, regenerate authentication, and rerun the success test. Do not retry the unchanged invalid body.
5. If you receive another status or reason code, use [Code and Formats](https://developer.mastercard.com/transactions-service/documentation/code-and-formats/index.md) to resolve it and repeat the test. Record the actual response rather than assuming the documented example was returned.

## Next Steps {#next-steps}

For failures, follow [Code and Formats](https://developer.mastercard.com/transactions-service/documentation/code-and-formats/index.md) or contact [Support](https://developer.mastercard.com/transactions-service/documentation/support/index.md#get-help) with sanitized evidence. After success and negative tests pass, follow [Move Project to Production](https://developer.mastercard.com/transactions-service/documentation/tutorials-and-guides/production-access-tutorial/index.md).
