Tutorial•3 min read

Sending Transactional Email from Node.js with fetch and Piisend

Learn how to send transactional emails from your Node.js applications using the native fetch API and Piisend's robust REST API. This guide covers basic email sending, error handling, and using templates for developers.

Sending Transactional Email from Node.js with fetch and Piisend

Section 1

Why Use Node.js fetch for Transactional Emails?

The native fetch API in Node.js provides a modern, promise-based way to make HTTP requests without external libraries. When combined with Piisend's transactional email API, it offers a streamlined and efficient method for developers to send critical emails like OTPs, password resets, and order confirmations. This approach simplifies your dependency management while ensuring reliable email delivery for your Node.js applications.

Section 2

Sending Your First Transactional Email with Node.js fetch

The fetch API in Node.js allows you to send transactional emails by making a POST request to the Piisend email API endpoint. You must include your Authorization header with a Bearer token and set the Content-Type to application/json. The request body specifies recipients, subject, and the email content. This example demonstrates a complete function for sending a basic HTML email and handling its response.

javascript
1async function sendBasicEmail(recipientEmail, subject, htmlContent, textContent) {
2 const apiKey = "YOUR_API_KEY";
3 try {
4 const response = await fetch("https://api.piisend.com/api/v1/emails", {
5 method: "POST",
6 headers: {
7 "Authorization": `Bearer ${apiKey}`,
8 "Content-Type": "application/json"
9 },
10 body: JSON.stringify({
11 to: [recipientEmail],
12 subject: subject,
13 html: htmlContent,
14 text: textContent
15 })
16 });
17
18 if (response.ok) {
19 const data = await response.json();
20 console.log("Email sent successfully. Message ID:", data.message_id);
21 return data;
22 } else {
23 const errorData = await response.json();
24 console.error("Failed to send email:", response.status, errorData);
25 throw new Error(`Piisend API error: ${response.status} - ${errorData.error || JSON.stringify(errorData)}`);
26 }
27 } catch (error) {
28 console.error("Network or unexpected error:", error);
29 throw error;
30 }
31}
32
33// Example usage:
34// sendBasicEmail(
35// "user@example.com",
36// "Your Order Confirmation",
37// "<h1>Thank you for your order!</h1><p>Your order #123 has been confirmed.</p>",
38// "Thank you for your order! Your order #123 has been confirmed."
39// );

Section 3

Leveraging Email Templates for Dynamic Content

For consistent branding and dynamic content, Piisend supports sending emails using pre-defined templates. Instead of providing html and text directly, you specify a template_id and pass an object of template_vars. These variables will be merged into your template, allowing for personalized emails like password reset links or OTP verification codes without embedding logic in your application.

javascript
1async function sendTemplatedEmail(recipientEmail, templateId, templateVars) {
2 const apiKey = "YOUR_API_KEY";
3 try {
4 const response = await fetch("https://api.piisend.com/api/v1/emails", {
5 method: "POST",
6 headers: {
7 "Authorization": `Bearer ${apiKey}`,
8 "Content-Type": "application/json"
9 },
10 body: JSON.stringify({
11 to: [recipientEmail],
12 template_id: templateId,
13 template_vars: templateVars
14 })
15 });
16
17 if (response.ok) {
18 const data = await response.json();
19 console.log("Templated email sent successfully. Message ID:", data.message_id);
20 return data;
21 } else {
22 const errorData = await response.json();
23 console.error("Failed to send templated email:", response.status, errorData);
24 throw new Error(`Piisend API error: ${response.status} - ${errorData.error || JSON.stringify(errorData)}`);
25 }
26 } catch (error) {
27 console.error("Network or unexpected error:", error);
28 throw error;
29 }
30}
31
32// Example usage:
33// sendTemplatedEmail(
34// "user@example.com",
35// "welcome_email_template",
36// {
37// "user_name": "Alice",
38// "login_link": "https://app.example.com/login"
39// }
40// );

Section 4

Preventing Duplicate Emails with Idempotency Keys

In distributed systems, network issues can sometimes lead to duplicate API requests. To prevent sending the same transactional email multiple times, Piisend supports idempotency. By including a unique Idempotency-Key header with each request, you ensure that even if the request is retried, the email is processed only once. This is crucial for critical emails like OTPs or order confirmations, enhancing the reliability of your email for developers.

javascript
1async function sendIdempotentEmail(recipientEmail, subject, htmlContent, idempotencyKey) {
2 const apiKey = "YOUR_API_KEY";
3 try {
4 const response = await fetch("https://api.piisend.com/api/v1/emails", {
5 method: "POST",
6 headers: {
7 "Authorization": `Bearer ${apiKey}`,
8 "Content-Type": "application/json",
9 "Idempotency-Key": idempotencyKey // Unique key for this request
10 },
11 body: JSON.stringify({
12 to: [recipientEmail],
13 subject: subject,
14 html: htmlContent
15 })
16 });
17
18 if (response.ok) {
19 const data = await response.json();
20 console.log("Idempotent email sent successfully. Message ID:", data.message_id);
21 return data;
22 } else {
23 const errorData = await response.json();
24 console.error("Failed to send idempotent email:", response.status, errorData);
25 throw new Error(`Piisend API error: ${response.status} - ${errorData.error || JSON.stringify(errorData)}`);
26 }
27 } catch (error) {
28 console.error("Network or unexpected error:", error);
29 throw error;
30 }
31}
32
33// Example usage:
34// const uniqueRequestId = "order-123-confirmation-attempt-1"; // Generate a unique ID per logical send
35// sendIdempotentEmail(
36// "user@example.com",
37// "Order #123 Confirmed",
38// "<p>Your order has been confirmed!</p>",
39// uniqueRequestId
40// );

Start sending

Ship transactional email in minutes

Create an API key, verify a domain, and send your first message with Piisend.