DEV Community

Cover image for Create a serverless API with Next.js and Mailchimp
Kartik Chaturvedi
Kartik Chaturvedi

Posted on • Updated on • Originally published at ikartik.com

Create a serverless API with Next.js and Mailchimp

EDIT: Now updated with environment variables and fetch!


The future is API-driven. We have APIs for weather, payments, travel, and even sports. RESTful architecture and API frameworks are what make ordinary apps and websites into powerful tools in today's connected world.

Using these frameworks, we can create tailored experiences for users, without having to reinvent the systems that power those experiences. In this tutorial, we will use Next.js, a fantastic React-based web development framework,

This tutorial assumes you are familiar with React, Next.js, and RESTful architecture.

Initial Setup

Setting up Next.js is super simple:

npm init next-app
Enter fullscreen mode Exit fullscreen mode

Next.js will set up a default project and install all dependencies for you. Once installed, inside of the pages/ directory, you will find the default Next.js index.js welcome page. If you start the development server and make changes to this file, you will see the changes updated live in your browser.

Create the API

In this tutorial, we’ll be using Mailchimp’s API to add a new email address as a contact in a campaign mailing list.

To create an API, create a folder named api/ in the pages/ directory. Next.js will take any file inside the api/ folder and create an API instead of a page. Here, create a new file named subscribe.js. This API will be accessible from the web at your-site.com/api/subscribe.

Next.js provides a clean framework to handle the request and response in the API. All we need to do here is take the email address from the request and send it to Mailchimp’s API. Let’s start by exporting a default function in subscribe.js that returns a JSON object with one key-value pair:

export default async (req, res) => {
  res.end(JSON.stringify({response: 'hello world'}))
}
Enter fullscreen mode Exit fullscreen mode

The async keyword is important, as we will be using the companion await keyword to make asynchronous calls to Mailchimp.

You can visit the API endpoint in the browser or using a tool like Postman and see the response we coded in the last step.

{
  "response": "hello world"
}
Enter fullscreen mode Exit fullscreen mode

In Next.js, req and res are default parameters sent and expected by the framework. req is an object that contains all of the request data — headers, cookies, query values, and of course, the request body. We should only need the body at this point, accessible via the req.body object. Let's expect a field called emailAddress in the request, which will contain the new email address for the new subscriber. We'll pull that into a variable called email for later.

export default async (req, res) => {
  const email = req.body.emailAddress
}
Enter fullscreen mode Exit fullscreen mode

To call Mailchimp's API that will add an email address to your mailing list, first create an API within your Mailchimp account. Using this key, you will authenticate your requests to Mailchimp, similar to a password. This will be stored and executed from the our subscribe API, so no visitor to your website will ever see it.

To call APIs, we will need to use an HTTP client like fetch, which comes bundled with Next.js.

The fetch API is simple to use. We just need to call fetch() with Mailchimp’s URL and an object containing the required parameters. Since fetch() returns a Promise, we will use await to resolve it. Since both the Promise and the fetch call could fail, we wrap the call in a try-catch block.

try {
  const response = await fetch({
    // parameters will go here
  })
} catch { }
Enter fullscreen mode Exit fullscreen mode

The Mailchimp API documentation defines the endpoint and calls for two fields to be sent in the request: the email_address, for which we will pass the email value extracted from req.body earlier, and the status for that email address, for which we will send subscribed. The fetch documentation shows that the first parameter in the fetch() call is the URL, and the second parameter is an object with additional fields. The body field is where we will pass the email_address and status fields. We need to use JSON.stringify() to convert the fields into a single string.

Mailchimp’s endpoint is a POST call, so let’s set the method to that, and additionally define a headers object so we can pass Content-Type, which will be application/json.

const email = req.body.emailAddress
try {
    const response = await fetch('https://{dc}.api.mailchimp.com/3.0/lists/{listId}/members', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': secret,
      },
      body: JSON.stringify({
        email_address: email,
        status: 'subscribed'
      })
    })
} catch { }
Enter fullscreen mode Exit fullscreen mode

NOTE: To create the complete URL for your Mailchimp mailing list, you will need to find the dc location and list_id for your account in Mailchimp's dashboard.

One last step is to add the Authorization field to the header. This will authenticate our request with Mailchimp's server with HTTP Basic Authentication using the API key created earlier. An easy way to create the Authorization token is using Postman's authorization tool. You can also create it manually by encoding your Mailchimp username and API key in Base64.

The authorization token needs to be passed in the headers object, but we should avoid keeping sensitive data like tokens, keys, and passwords unencrypted as strings in a file. Instead, let’s create an environment variable that will be encrypted and stored securely outside of our code. Our app will find and use it automatically.

Create a .env file in the root of the project. This will store a list of environment variables as key-value pairs. The key can be anything, and the value will be the Base64 encoded token for Mailchimp. Remember to wrap the value in quotes.

MAILCHIMP_SECRET="Basic s0m3L0ngR@ndomStr1nG"
Enter fullscreen mode Exit fullscreen mode

Don’t forget to ignore this file in your source control — we don’t want to be syncing this plaintext file. It is best to recreate this file wherever your code will run. This file will help run your code on your local machine, and you can set up environment variables on most cloud platforms.

Once the token is saved, we can pull it from the env object and send it in our fetch request:

const { MAILCHIMP_AUTH: secret } = process.env
// { ... }
try {
    const response = await fetch('https://{dc}.api.mailchimp.com/3.0/lists/{listId}/members', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': secret,
      },
      body: JSON.stringify({
        email_address: email,
        status: 'subscribed'
      })
    })
} catch { }
Enter fullscreen mode Exit fullscreen mode

Now we just need to return the correct response from our API depending on the response we get from Mailchimp. We will only send back a response status, and leave the response body empty since there is no data to be communicated back to the browser. To keep things simple in this tutorial, if Mailchimp returns a 200 response status, we will also return a 200. If Mailchimp returns anything else, we will return a 400 status. It either subscribed the user, or it didn't.

// const response = { ... }
if (response.status === 200) {
  res.statusCode = 200
  res.end()
} else {
  res.statusCode = 400
  res.end()
}
Enter fullscreen mode Exit fullscreen mode

Now, fetch will throw an error if the call fails. This could be due to a network issue or a legitimate error returned from the Mailchimp API. This error will be caught in the catch block, so let's make sure it returns a response too.

// try { ...
} catch (error) {
  res.statusCode = 400
  res.end()
}
Enter fullscreen mode Exit fullscreen mode

And that's it! We have an API that will call Mailchimp with an email address and return a status code depending on Mailchimp's response. If you run the development server, you can test this in Postman by sending an email address in the body of a POST request. In response, we will either get a 200 code or 400 code, just as we coded for.

{
    "emailAddress" : "user@example.com"
}
Enter fullscreen mode Exit fullscreen mode

In the next part of this tutorial, we will set up some validation and security in our API before deploying to the web, and we will also set up the frontend component — that is, the form itself.

Top comments (0)