Build a quick serverless email collector API using AWS API Gateway, AWS Lambda & AWS DynamoDB.
Published: 2024-03-14 11:44:54



### Introduction

AWS is such an incredible service which allows us to perform quite a number of important technical tasks ranging from building databases, to machine learning, expandable object storage and so many others.

In this mini project, I make use of 3 remarkable AWS services to build a simple API to input user email to a database via a click.

*Out of project scope: Building a front end button to make use of the API. However, testing will be done using postman.*

## Prerequisites

1. [AWS account](https://aws.amazon.com/free) (free tier for new users).
2. Basic python knowledge

## Project Architecture

We will be following a basic flow:

1. Create the DynamoDB database where the user details will be stored.

2. Creating and testing an AWS Lambda function to hold user information.
 
3.Writing the main Lambda function in python to access the AWS DynamoDB database and access the API body inputs from the post request which will be handled by AWS API gateway.

## Part 1: Create the AWS DynamoDB 

*Preamble: AWS DynamoDB is a nosql database which uses key-value pairs to access and populate table elements. It is flexible and can be used without knowledge of SQL or building schemas.*

1. After you log into your AWS console, type DynamoDB in the search panel and view the option to create a new table.

![CREATE AWS DYNAMODB TABLE](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kuhqn0qjfwitznfwzfij.png)

2. Once you click the create button option, you can name your table. Provide a name which corresponds to the data you intend to store. In our case, you can use *storeUserEmail*.

3. Create a proper partition key. A partition key is a unique identifier for your table content. This is commonly known as the *primary key* in databases. It is unique and is used to retrieve data from your table. You may use userId as the partition/ primary key.
![CREATE A PARTITION KEY](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pf5jsq5r07qdfjk117sl.png)
4. You may create a sort key but in our case we do not need one as our project requires only a basic database.

## Part 2: Creating a lambda function to write to your AWS DynamoDB table

### Creating a lambda function:
1. Navigate to AWS Lambda from the AWS console.
2. Click the "Create function" button
![CREATE NEW LAMBDA FUNCTION](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aaxzcikiatuk79eh9clg.png)
3. Select "Author from scratch".
4. Input a function name.
5. Select your preferred runtime option. That is, the programming language you will like to run your function on.
6. For the purpose of this project, you can leave the rest options as default.
7. Complete the process by clicking "create function" at the bottom of the form and your function would have been successfully created.
![CONFIGURE LAMBDA FUNCTION](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/io5wsy8jff0r1vb11jne.png)

### Configuring your Lambda function:
1. From the options right under the function overview, select "code".
2. Paste the following code:
```
# import the json utility package since we will be working with a JSON object
import json
# import the AWS SDK (for Python the package name is boto3)
import boto3
# import two packages to help us with dates and date formatting
from time import gmtime, strftime

# create a DynamoDB object using the AWS SDK
dynamodb = boto3.resource('dynamodb')
# use the DynamoDB object to select our table
table = dynamodb.Table('YOUR-DYNAMODB-TABLE-NAME')
# store the current time in a human readable format in a variable
now = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())

# define the handler function that the Lambda service will use as an entry point
def lambda_handler(event, context):
# extract values from the event object we got from the Lambda service and store in a variable
    user = event['user']
    email = event['email']
# write name and time to the DynamoDB table using the object we instantiated and save response in a variable
    response = table.put_item(
        Item={
            'user': user,
            'email': email,
            'timestamp': now
            })
# return a properly formatted JSON object
#create message
    message = f'hello {user} your {email} has been successfully added to the waitlist'
    return {
        'statusCode': 200,
        'body': json.dumps(message)
    }
```
3. Click "deploy" then select the option to test the function by clicking the arrow beside "Test" button.
4. Select to "configure a test event".
5. Select "create a new event" then provide a test event name.
6. Leave the private option and select an event template.
7. You can select the HelloWorld template and edit it to meet the key value pairs to be expected in the event handler. Example code below:
```
{
  "email": "test@example.com",
  "user": "tester"
}
```
8. Save and return to the lambda function code.
9. Click test above the code and you should get a 200 status response.

## IMPORTANT NOTE TO CONFIGURE LAMBDA TO WRITE TO DYNAMODB: 
Navigate to configuration under your newly created Lambda function. Under configuration click permissions and click the link to the execution role which would redirect you to the IAM service.

![IAM role for Lambda function and dynamodb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cjefcwa1bv7d5lie70qn.png)
Click add permissions and select inline policy
![Create Inline policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n54lza43s6hqmdhbbpcl.png)
 
Replace the following code to the policy editor and replace your table ARN with the ARN.

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "VisualEditor0",
			"Effect": "Allow",
			"Action": [
				"dynamodb:PutItem",
				"dynamodb:DeleteItem",
				"dynamodb:GetItem",
				"dynamodb:Scan",
				"dynamodb:Query",
				"dynamodb:UpdateItem"
			],
			"Resource": "YOUR-DYNAMODB-TABLE-ARN"
		}
	]
}
```

## Part 3: Configure the AWS API gateway to trigger your Lambda function

1. Navigate to AWS API Gateway on the console and select "create api"
![CREATE NEW API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3k4h51gibq7wvht6rmif.PNG)
2. Scroll to "RESTAPI" then click "Build".
![BUILD RESTAPI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spvr3bdaqsz367o58qyl.PNG)
3. Next create new method and enable CORS with default settings.
![Create Method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nkxm0ziwdw8rbp28x6t.png)
4. Configure the API gateway to integrate with Lambda. Create "Post" method from the first method drop down. Select Lambda and click the "lambda function" dropdown to select your preferred Lambda function name. This corresponds to the name of the lambda function you created to this project. Finally, click "create method"
![Configure the API gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12xnugvmxwxvtlsvzpht.png)
5. Next, its time to deploy the API. On the top right page, click "deploy API".
![Deploy API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2q4rcllyavnhnmtwlk1.png)
6. Select a stage or create a "New stage". Give a description and click "deploy".
![Deploy to stage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kolb60cn8id7hzsznb61.png)
7. Get the link to the API endpoint by copying the URL under "Invoke URL".
![Get API URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqz8d9cb36hehj89uld5.png)

## Bonus Stage 3: Test API on Postman

* Paste the "Invoke URL" link from API gateway into the URL tab in postman. 
* Select "Post" and then click "send".
You should get a status 200 okay response and the data will be added to your DynamoDB table.
![Postman test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vl8f34hwbzqaruip7dln.png)

**Thank you for reading and I hope this helps you on your journey navigating AWS cloud services. Please drop a comment with suggestions, challenges and feedback.**