ContactLog In

Start Routing Notifications Today!

Courier is a notification service that centralizes all of your templates and messaging channels in one place which increases visibility and reduces engineering time.


Invoys Header

How to Send Invoice and Add Payment Reminder in Next.js with Courier API

Fazza Razaq Amiarso

January 27, 2023


A lot of open-source invoice management apps are built with Laravel. As a Javascript developer, I wanted to build the “React Solution” for devs that are familiar with React and Javascript.

A problem I found when building with services in Node.js is that there is no built-in mailer. So, I had to find a 3rd party service to do that for me. In this article, I will be integrating Courier to send emails for this project


As this article isn't your typical follow-along (more like "please sit tight and see how I do it"), it's not mandatory to be familiar with all technologies used. However, familiarity with Typescript and Next.js will be beneficial for quicker understanding.

Technologies in this blog:

  • Typescript: type-safety and auto-completion are the best, right?
  • Next.js: a production-ready framework to build a full-stack app, even for beginners.
  • Prisma: a great ORM to work with databases. We use Prisma because of its type-safety and auto-completion, providing great developer experience with typescript added.
  • Trpc: enable us to easily build end-to-end type-safety between our Next.js client and server.
  • Courier API: a great service/platform to handle our notifications, such as email, SMS, and much more.

You can find the full source code here for reference.


Before building the features, let's define our goals.

  1. Send invoice link to client's email.
  2. Send a reminder a day before an invoice's due date.
  3. Cancel an invoice due date reminder when the invoice is already paid.
  4. Handling network errors.

Part 1: Setup Courier Platform

Let's head over to the Courier Dashboard. By default, it's in a production environment. Since I want to test things out, I'm going to change to the test environment by clicking the dropdown in the top-right corner.

We can copy all templates later to production or vice-versa.

Now, I will create a brand for my email notifications.

go to brand

I'm just going to add a logo (beware that the logo width is fixed to 140px) on the header and social links on the footer. The designer UI is pretty straightforward, so here is the final result.

brand template

Don't forget to publish the changes.

Part 2: Send Invoice to Email

Currently, the send email button on the UI is doing nothing.

I'm going to create a courier.ts file in src/lib/ to keep all Courier-related code. Also, I will use courier node.js client library which already abstracted all Courier API endpoints to functions.

Before I build the functionality, let's create the email notification design within Courier's Designer and set up the Gmail provider.

On the email designer page, we will see that the created brand is already integrated. After that, let's design the template accordingly with the needed data. Here is the final result.

email template finalaction button

Notice the value with {} that becomes green, it means it's a variable that can be inserted dynamically. I also set the 'See Invoice' button (or action) with a variable.

Before I can use the template, I need to create a test event by clicking the preview tab. Then, it will show a prompt to name the event and set data in JSON format. That data field is what will populate the value of the green {} variables (the data can be set from code also). Since it's a test event, I will fill it with arbitrary values.

Next, I will publish the template so I can use it. Then, go to send tab. It will show the necessary code to send the email programmatically and the data will be populated with the previous test event that I created.

code snippet


I will copy the test AUTH_TOKEN to the .env file and copy the snippet to src/lib/courier.ts.

Create a sendInvoice function that will be responsible for sending an email. To send an email from the code, I use the courierClient.send() function.

Define types for the sendInvoice function.

Now that I can send the email, I will call it in the sendEmail trpc endpoint that resides in src/server/trpc/router/invoice.ts.

Just remember that trpc endpoint is a Next.js API route. In this case, sendEmail will be the same as calling the /api/trpc/sendEmail route with fetch under the hood. For more explanation

For those who are unfamiliar with trpc, what I did is the same as handling a POST request. Let's break it down.

  1. Trpc way of defining request input from client by validating with Zod. Here I define all data that are needed for the sendInvoice function.
  1. Define a POST request handler (mutation).


Now, I can start to add the functionality to the send email button. I'm going to use the trpc.useMutation() function which is a thin wrapper of tanstack-query'suseMutation`.

Let's add the mutation function. On successful response, I want to send a success toast on UI.

I can just use the function as an inline handler, but I want to create a new handler for the button.

Now I can attach the handler to the send email button.

Here's the working UI.

working ui

Part 3: Send Payment Reminder

To schedule a reminder that will be sent a day before an invoice's due date, I'm going to use Courier's Automation API.

First, let's design the email template in Courier designer. As I already go through the process before, here is the final result.

payment reminder template

Before adding the function, define the types for the parameter and refactor the types.

Now, I add the scheduleReminder function to src/lib/courier

To send the reminder, I will call scheduleReminder after a successful sendInvoice attempt. Let's modify the sendEmail trpc endpoint.

Now if I try to send an invoice by email, I should get a reminder 20 seconds later since I'm in the development environment.

with payment reminder

Part 4: Cancel a reminder

Finally, all the features are ready. However, I got a problem, what if a client had paid before the scheduled date for payment reminder? Currently, the reminder email will still be sent. That's not a great user experience and potentially a confused client. Thankfully, Courier has an automation cancellation feature.

Let's add cancelAutomationWorkflow function that can cancel any automation workflow in src/lib/courier.ts.

What is a cancelation_token? It's a unique token that can be set to an automation workflow, so it's cancelable by sending a cancel action with a matching cancelation_token.

Add cancelation_token to scheduleReminder, I use the invoice's Id as a token.

I will call cancelAutomationWorkflow when an invoice's status is updated to PAID in the updateStatus trpc endpoint.

Here is the working UI.

cancel log

Part 5: Error Handling

An important note when doing network requests is there are possibilities of failed requests/errors. I want to handle the error by throwing it to the client, so it can be reflected in UI.

On error, Courier API throws an error with CourierHttpClientError type by default. I will also have all functions' return value in src/lib/courier.ts consistent with the below format.

Now, I can handle errors by adding a try-catch block to all functions in src/lib/courier.ts.

Let's see a handling example on the sendEmail trpc endpoint.

Part 6: Go To Production

Now that all templates are ready, I will copy all assets in the test environment to production. Here is an example.

copy assets to production


Finally, all the features are integrated with Courier. We've gone through a workflow of integrating Courier API to a Next.js application. Although it's in Next.js and trpc, the workflow will be pretty much the same with any other technology. I hope now you can integrate Courier into your application by yourself.

Get started now:

About the Author

I'm Fazza Razaq Amiarso, a full-stack web developer from Indonesia. I'm also an Open Source enthusiast. I love to share my knowledge and learning on my blog. I occasionally help other developers on FrontendMentor in my free time.

Connect with me on LinkedIn.

🔗 Courier Docs

🔗 Contribute to Invoys

🔗 Invoys Motivation

Start Routing Notifications Today!

Courier is a notification service that centralizes all of your templates and messaging channels in one place which increases visibility and reduces engineering time.


More from Engineering


Simplifying notifications with the Courier iOS SDK

Push notifications are a valuable tool for keeping users informed and increasing their engagement with your app. You can use push notifications to alert users about promotions, new content, or any other important updates. While push notifications are a powerful tool, setting up push notifications in iOS can be a daunting task that requires a significant amount of effort and time. Fortunately, the Courier iOS Mobile Notifications Software Development Kit (SDK) simplifies this process.

Mike Miller

Mike Miller

March 23, 2023

Courier Android SDK thumbnail

Building Android push notifications with Firebase and Courier’s SDK

Push notifications have become an essential part of modern mobile apps, allowing you to keep your users engaged and informed. However, implementing push for different platforms can be a complex and time-consuming task, requiring developers to set up and handle token management, testing, and other logistical details.

Mike Miller

Mike Miller

March 21, 2023

Build your first notification in minutes

Send up to 10,000 notifications every month, for free.

Get started for free

Email & push notification

Build your first notification in minutes

Send up to 10,000 notifications every month, for free.

Get started for free

Email & push notification











API Status


© 2023 Courier. All rights reserved.