## Overview

The Amplify CLI deploys REST APIs and handlers using [Amazon API Gateway](http://docs.aws.amazon.com/apigateway/latest/developerguide/) and [AWS Lambda](http://docs.aws.amazon.com/lambda/latest/dg/).

The API category will perform SDK code generation which, when used with the `AWSMobileClient` can be used for creating signed requests for Amazon API Gateway when the service Authorization is set to `AWS_IAM` or when using a [Cognito User Pools Authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html).

See [the authentication section for more details](/sdk/auth/getting-started) for using the `AWSMobileClient` in your application.

## Set Up Your Backend

In a terminal window, navigate to your project folder (the folder that typically contains your project level `build.gradle`), and add the SDK to your app.

```bash
cd ./YOUR_PROJECT_FOLDER
amplify add api
```

When prompted select the following options:

```console
> REST
> Create a new Lambda function
> Serverless express function
> Restrict API access? Yes
> Who should have access? Authenticated and Guest users
```

When configuration of your API is complete, the CLI displays a message confirming that you have configured local CLI metadata for this category. You can confirm this by running `amplify status`. Finally deploy your changes to the cloud:

```bash
amplify push
```

Once the deployment completes a folder with the name of your API's resource name will be created in `./src/main/java`. This is the client SDK with the models you will import and use in the `ApiClientFactory()` builder from your code in the following sections.

## Connect to Your Backend

Add the following to your `app/build.gradle`:

```groovy
	dependencies {
		implementation 'com.amazonaws:aws-android-sdk-apigateway-core:ANDROID_SDK_VERSION'
		implementation 'com.amazonaws:aws-android-sdk-mobile-client:ANDROID_SDK_VERSION'
		implementation 'com.amazonaws:aws-android-sdk-auth-userpools:ANDROID_SDK_VERSION'
	}
```

Build your project. Next, you will need to import the client that was generated in `./src/main/java` when you ran `amplify push`. For example, an app named `useamplify` with an API resource named `xyz123`, the path of the code file will be `./src/main/java/xyz123/useamplifyabcdClient.java`. The API client name will be `useamplifyabcdClient`. You would have the following entries in your code:

```java
import YOUR_API_RESOURCE_NAME.YOUR_APP_NAME_XXXXClient;

private YOUR_APP_NAME_XXXXClient apiClient;

apiClient = new ApiClientFactory()
    .credentialsProvider(AWSMobileClient.getInstance())
    .build(YOUR_API_CLIENT_NAME.class);
```

Find the resource name of your API by running `amplify status`. Copy your API client name to use when invoking the API in the following sections.

### IAM authorization

To invoke an API Gateway endpoint from your application, import the generated client as outlined in the last section and use the generated client class, model, and resource paths as in the below example with `YOUR_API_RESOURCE_NAME.YOUR_APP_NAME_XXXXClient`, `YOUR_APP_NAME_XXXXClient`, and `YOUR_API_CLIENT_NAME` replaced appropriately. For AWS IAM authorization use the `AWSMobileClient` as outlined in [the authentication section](/sdk/auth/getting-started).

```java
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;

    import com.amazonaws.http.HttpMethodName;
    import com.amazonaws.mobile.client.AWSMobileClient;
    import com.amazonaws.mobile.client.AWSStartupHandler;
    import com.amazonaws.mobile.client.AWSStartupResult;
    import com.amazonaws.mobileconnectors.apigateway.ApiClientFactory;
    import com.amazonaws.mobileconnectors.apigateway.ApiRequest;
    import com.amazonaws.mobileconnectors.apigateway.ApiResponse;
    import com.amazonaws.util.IOUtils;
    import com.amazonaws.util.StringUtils;

    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;

    // TODO Replace this with your api friendly name and client class name
    import YOUR_API_RESOURCE_NAME.YOUR_APP_NAME_XXXXClient;

    public class MainActivity extends AppCompatActivity {
        private static final String TAG = MainActivity.class.getSimpleName();

        // TODO Replace this with your client class name
        private YOUR_APP_NAME_XXXXClient apiClient;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // Initialize the AWS Mobile Client
            AWSMobileClient.getInstance().initialize(this, new AWSStartupHandler() {
                @Override
                public void onComplete(AWSStartupResult awsStartupResult) {
                    Log.d(TAG, "AWSMobileClient is instantiated and you are connected to AWS!");
                }
            }).execute();

            // Create the client
            apiClient = new ApiClientFactory()
                    .credentialsProvider(AWSMobileClient.getInstance())
                    .build(YOUR_API_CLIENT_NAME.class);

            doInvokeAPI();
        }

        public void doInvokeAPI() {
            // Create components of api request
            final String method = "GET";
            final String path = "/items";

            final String body = "";
            final byte[] content = body.getBytes(StringUtils.UTF8);

            final Map parameters = new HashMap<>();
            parameters.put("lang", "en_US");

            final Map headers = new HashMap<>();

            // Use components to create the api request
            ApiRequest localRequest =
                    new ApiRequest(apiClient.getClass().getSimpleName())
                            .withPath(path)
                            .withHttpMethod(HttpMethodName.valueOf(method))
                            .withHeaders(headers)
                            .addHeader("Content-Type", "application/json")
                            .withParameters(parameters);

            // Only set body if it has content.
            if (body.length() > 0) {
                localRequest = localRequest
                        .addHeader("Content-Length", String.valueOf(content.length))
                        .withBody(content);
            }

            final ApiRequest request = localRequest;

            // Make network call on background thread
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Log.d(TAG,
                                "Invoking API w/ Request : " +
                                        request.getHttpMethod() + ":" +
                                        request.getPath());

                        final ApiResponse response = apiClient.execute(request);

                        final InputStream responseContentStream = response.getContent();

                        if (responseContentStream != null) {
                            final String responseData = IOUtils.toString(responseContentStream);
                            Log.d(TAG, "Response : " + responseData);
                        }

                        Log.d(TAG, response.getStatusCode() + " " + response.getStatusText());

                    } catch (final Exception exception) {
                        Log.e(TAG, exception.getMessage(), exception);
                        exception.printStackTrace();
                    }
                }
            }).start();
        }
      }
```

### Cognito User Pools authorization

When invoking an API Gateway endpoint with Cognito User Pools authorizer, you can leverage the `AWSMobileClient` to dynamically refresh and pass tokens to your endpoint. Using the example from the previous section, update the `doInvokeAPI()` so that it takes a "token" string argument like `doInvokeAPI(String token)`. Next, add a header for the token to be passed with `.addHeader("Authorization", token)` and set the service configuration to have `credentialsProvider(null)`. Finally, overload the `doInvokeAPI()` with a new definition that gets the Cognito User Pools token from the `AWSMobileClient` as below:

```java
//Pass in null for credentialsProvider
apiClient = new ApiClientFactory()
    .credentialsProvider(null)
    .build(YOUR_API_CLIENT_NAME.class);

//New overloaded function that gets Cognito User Pools tokens
public void doInvokeAPI(){
    AWSMobileClient.getInstance().getTokens(new Callback<Tokens>() {
        @Override
        public void onResult(Tokens tokens) {
            doInvokeAPI(tokens.getIdToken().getTokenString());
        }

        @Override
        public void onError(Exception e) {
            e.printStackTrace();
        }
    });
}

//Updated function with arguments and code updates
public void doInvokeAPI(String token) {

ApiRequest localRequest =
    new ApiRequest(apiClient.getClass().getSimpleName())
        .withPath(path)
        .withHttpMethod(HttpMethodName.valueOf(method))
        .withHeaders(headers)
        .addHeader("Content-Type", "application/json")
        .addHeader("Authorization", token)              //Use JWT token
        .withParameters(parameters);

}
```

You can then invoke this method with `doInvokeAPI()` from your application code and it will pass the IdToken from Cognito User Pools as an `Authorization` header.
