Skip to main content
RapidDev - Software Development Agency
replit-integrationsStandard API Integration

How to Integrate Replit with Campaign Monitor

To integrate Replit with Campaign Monitor, generate an API key from your Campaign Monitor account, store it in Replit Secrets (lock icon πŸ”’), and call the Campaign Monitor API from your Python or Node.js backend to manage subscribers, create campaigns, and send transactional emails. Deploy with Autoscale for web-triggered workflows or Reserved VM for background email automation.

What you'll learn

  • How to generate a Campaign Monitor API key and find your client and list IDs
  • How to store Campaign Monitor credentials securely in Replit Secrets
  • How to add, update, and remove subscribers from email lists in Python and Node.js
  • How to create and send email campaigns programmatically via the Campaign Monitor API
  • How to send transactional emails using Campaign Monitor's transactional API
Book a free consultation
4.9Clutch rating ⭐
600+Happy partners
17+Countries served
190+Team members
Intermediate14 min read25 minutesMarketingMarch 2026RapidDev Engineering Team
TL;DR

To integrate Replit with Campaign Monitor, generate an API key from your Campaign Monitor account, store it in Replit Secrets (lock icon πŸ”’), and call the Campaign Monitor API from your Python or Node.js backend to manage subscribers, create campaigns, and send transactional emails. Deploy with Autoscale for web-triggered workflows or Reserved VM for background email automation.

Why Connect Replit to Campaign Monitor?

Campaign Monitor is favored by design-conscious teams because it combines a polished drag-and-drop email builder with a clean, developer-friendly REST API. Connecting your Replit app to Campaign Monitor lets you automate every part of your email marketing workflow β€” from subscribing new users when they sign up, to triggering personalized transactional emails based on in-app events, to pulling engagement analytics into your own dashboards.

The API is organized around three core objects: Subscriber Lists (collections of email addresses with custom fields), Campaigns (bulk emails sent to one or more lists), and Transactional Emails (individually triggered messages sent via SMTP or API). Replit's server-side Python or Node.js environment is ideal for all three use cases because it keeps your API key off the client and gives you full control over when and how emails are sent.

Replit's Secrets system (lock icon πŸ”’ in the sidebar) keeps your Campaign Monitor API key encrypted and out of your version control history. Because a Campaign Monitor API key grants full account access including the ability to send emails to all your subscribers, treat it with the same care as a production database password. Always call the Campaign Monitor API from server-side code, never from client-side JavaScript.

Integration method

Standard API Integration

You connect Replit to Campaign Monitor by generating an API key from your account settings, saving it to Replit Secrets, and making authenticated HTTP requests to the Campaign Monitor REST API from your server-side Python or Node.js code. The API uses HTTP Basic Auth with your API key as the username. All operations β€” subscriber management, campaign creation, and transactional email β€” use the same key.

Prerequisites

  • A Replit account with a Python or Node.js project created
  • A Campaign Monitor account (free trial available)
  • At least one Subscriber List created in Campaign Monitor
  • Your Campaign Monitor Client ID (found in account settings)
  • Basic familiarity with REST APIs and HTTP Basic Authentication

Step-by-step guide

1

Get Your Campaign Monitor API Key and List ID

Log in to your Campaign Monitor account and click your name in the top-right corner, then select 'Account Settings'. Scroll down to the 'API keys' section and click 'Generate API key'. Copy the generated key β€” it looks like a 32-character hex string such as abc123def456.... Next, find your Subscriber List ID. Navigate to the list you want to use by going to Lists & Subscribers, clicking on your list name, then selecting 'Settings' from the left sidebar. The list ID appears in the URL and in the page settings as a long alphanumeric string. You also need your Client ID, which is required for creating campaigns. Go to Account Settings and look for the 'API Client Credentials' section, or click your client name in the top navigation. The Client ID appears in the URL of your client dashboard. Copy all three values: the API Key, the List ID, and the Client ID. You will add all three to Replit Secrets in the next step.

Pro tip: Campaign Monitor supports multiple clients under one account. If you manage email for several brands or businesses, each has its own Client ID and subscriber lists. Make sure you are using the correct Client ID for the lists you want to target.

Expected result: You have your Campaign Monitor API Key, List ID, and Client ID copied and ready to add to Replit Secrets.

2

Store Campaign Monitor Credentials in Replit Secrets

Open your Replit project and click the lock icon πŸ”’ in the left sidebar to open the Secrets pane. Add the following secrets one at a time using the 'Add a new secret' form: - Key: CM_API_KEY β€” Value: your 32-character API key - Key: CM_LIST_ID β€” Value: your Subscriber List ID - Key: CM_CLIENT_ID β€” Value: your Campaign Monitor Client ID Click 'Add Secret' after each entry. Replit encrypts these values at rest and injects them as environment variables when your server starts. They never appear in your file tree, your source code, or your Git history. In Python, access these with os.environ['CM_API_KEY']. In Node.js, use process.env.CM_API_KEY. Never hardcode these values in your source files β€” Replit's Secret Scanner will flag hardcoded credentials and they could be exposed if your project is ever made public. For the transactional API (if you use Campaign Monitor's Smart Transactional Email), you may also want to add CM_TX_SMART_EMAIL_ID for the template ID used in transactional sends.

Pro tip: After adding secrets, click 'Run' to restart your Repl so the new environment variables are picked up. Secrets added while the server is running are not automatically injected into the running process.

Expected result: Three secrets (CM_API_KEY, CM_LIST_ID, CM_CLIENT_ID) are visible in the Replit Secrets pane and accessible as environment variables.

3

Manage Subscribers with Python

Campaign Monitor uses HTTP Basic Authentication where the API key is the username and the string 'x' is the password. This is a Campaign Monitor convention β€” any non-empty string works as the password, but 'x' is the documented standard. The base URL for all v3.3 API endpoints is https://api.createsend.com/api/v3.3/. The most common operations are adding subscribers, updating their custom fields, and unsubscribing them. Campaign Monitor uses email address as the unique identifier within a list, so you can upsert (add or update) by POSTing to the same endpoint β€” if the email already exists in the list, Campaign Monitor updates the existing record. The code below shows a complete Python module for subscriber management including adding, unsubscribing, and checking status. Install the requests library first by running pip install requests in the Replit shell.

cm_subscribers.py
1import os
2import requests
3from typing import Optional
4
5API_KEY = os.environ["CM_API_KEY"]
6LIST_ID = os.environ["CM_LIST_ID"]
7BASE_URL = "https://api.createsend.com/api/v3.3"
8
9# Campaign Monitor Basic Auth: API key as username, 'x' as password
10AUTH = (API_KEY, "x")
11
12def add_subscriber(email: str, name: str = "", custom_fields: list = None) -> dict:
13 """
14 Add or update a subscriber in the list (upsert behavior).
15 custom_fields: list of {"Key": "FieldName", "Value": "value"}
16 """
17 url = f"{BASE_URL}/subscribers/{LIST_ID}.json"
18 payload = {
19 "EmailAddress": email,
20 "Name": name,
21 "CustomFields": custom_fields or [],
22 "Resubscribe": True, # Re-subscribe if previously unsubscribed
23 "ConsentToTrack": "Yes" # Required for GDPR compliance tracking
24 }
25 response = requests.post(url, json=payload, auth=AUTH)
26 response.raise_for_status()
27 return response.json()
28
29def get_subscriber(email: str) -> Optional[dict]:
30 """Retrieve subscriber details and status."""
31 url = f"{BASE_URL}/subscribers/{LIST_ID}.json"
32 params = {"email": email}
33 response = requests.get(url, params=params, auth=AUTH)
34 if response.status_code == 400:
35 return None # Subscriber not found
36 response.raise_for_status()
37 return response.json()
38
39def unsubscribe(email: str) -> None:
40 """Unsubscribe a contact from the list."""
41 url = f"{BASE_URL}/subscribers/{LIST_ID}/unsubscribe.json"
42 payload = {"EmailAddress": email}
43 response = requests.post(url, json=payload, auth=AUTH)
44 response.raise_for_status()
45
46def delete_subscriber(email: str) -> None:
47 """Permanently delete a subscriber (GDPR right to erasure)."""
48 url = f"{BASE_URL}/subscribers/{LIST_ID}.json"
49 params = {"email": email}
50 response = requests.delete(url, params=params, auth=AUTH)
51 response.raise_for_status()
52
53# Example usage
54if __name__ == "__main__":
55 result = add_subscriber(
56 email="user@example.com",
57 name="Jane Doe",
58 custom_fields=[
59 {"Key": "City", "Value": "New York"},
60 {"Key": "Plan", "Value": "Pro"}
61 ]
62 )
63 print(f"Subscriber added: {result}")
64
65 sub = get_subscriber("user@example.com")
66 if sub:
67 print(f"Status: {sub['State']}")

Pro tip: Set 'Resubscribe': True when adding subscribers to automatically re-subscribe contacts who had previously unsubscribed. Leave it as False if you want to respect past unsubscribes, which is required in some email marketing regulations.

Expected result: Running the Python script successfully adds a test subscriber to your Campaign Monitor list and prints their subscription details.

4

Create and Send Campaigns with Node.js

Creating and sending a campaign in Campaign Monitor is a two-step process: first you create a campaign draft with the content and settings, then you schedule it (or send it immediately). The Client ID is required for campaign creation because Campaign Monitor organizes campaigns under clients. Campaign content can be provided as inline HTML or as a URL to a hosted template. For programmatically generated campaigns, inline HTML is simpler. For branded campaigns, use Campaign Monitor's template system and reference a template ID. The Node.js code below uses the built-in https module (no external dependencies needed) to create a campaign draft and immediately send it. In a production workflow, you would typically schedule the send for an optimal time rather than sending immediately. Install axios first with npm install axios for a cleaner API, or use the built-in https module as shown.

server.js
1const axios = require('axios');
2
3const API_KEY = process.env.CM_API_KEY;
4const CLIENT_ID = process.env.CM_CLIENT_ID;
5const LIST_ID = process.env.CM_LIST_ID;
6const BASE_URL = 'https://api.createsend.com/api/v3.3';
7
8// Campaign Monitor uses Basic Auth: API key as username, 'x' as password
9const auth = {
10 username: API_KEY,
11 password: 'x'
12};
13
14async function addSubscriber(email, name) {
15 const url = `${BASE_URL}/subscribers/${LIST_ID}.json`;
16 const response = await axios.post(url, {
17 EmailAddress: email,
18 Name: name,
19 Resubscribe: true,
20 ConsentToTrack: 'Yes'
21 }, { auth });
22 return response.data;
23}
24
25async function createCampaign(subject, fromName, fromEmail, replyTo, htmlContent) {
26 const url = `${BASE_URL}/campaigns/${CLIENT_ID}.json`;
27 const response = await axios.post(url, {
28 Subject: subject,
29 Name: `Campaign - ${new Date().toISOString()}`,
30 FromName: fromName,
31 FromEmail: fromEmail,
32 ReplyTo: replyTo,
33 HtmlUrl: '',
34 Html: htmlContent,
35 ListIDs: [LIST_ID]
36 }, { auth });
37 return response.data; // Returns campaign ID
38}
39
40async function sendCampaignImmediately(campaignId, confirmationEmail) {
41 const url = `${BASE_URL}/campaigns/${campaignId}/send.json`;
42 const response = await axios.post(url, {
43 ConfirmationEmail: confirmationEmail,
44 SendDate: 'Immediately'
45 }, { auth });
46 return response.data;
47}
48
49async function getCampaignStats(campaignId) {
50 const url = `${BASE_URL}/campaigns/${campaignId}/summary.json`;
51 const response = await axios.get(url, { auth });
52 return response.data;
53}
54
55// Express integration example
56const express = require('express');
57const app = express();
58app.use(express.json());
59
60app.post('/subscribe', async (req, res) => {
61 const { email, name } = req.body;
62 try {
63 await addSubscriber(email, name);
64 res.json({ success: true, message: 'Subscriber added successfully' });
65 } catch (error) {
66 console.error('Campaign Monitor error:', error.response?.data || error.message);
67 res.status(500).json({ error: 'Failed to add subscriber' });
68 }
69});
70
71app.listen(3000, '0.0.0.0', () => console.log('Server running on port 3000'));

Pro tip: When creating campaigns, Campaign Monitor requires you to include an unsubscribe link in the HTML content or the campaign will fail validation. Use the [unsubscribelink] merge tag in your HTML: <a href="[unsubscribelink]">Unsubscribe</a>.

Expected result: The Express server starts on port 3000 and successfully adds subscribers via POST /subscribe, returning a success JSON response.

5

Send Transactional Emails via the Smart Email API

Campaign Monitor's Transactional API lets you send individually triggered emails using pre-designed Smart Email templates. Unlike bulk campaigns, transactional emails are sent to one recipient at a time and are ideal for order confirmations, password resets, and event-driven notifications. To use the Transactional API, first create a Smart Email template in the Campaign Monitor dashboard under Transactional > Smart Transactional Email. Design the template and note the Smart Email ID from the settings page. The Transactional API has a different base URL (mail.createsend.com) and uses the same API key authentication. Deploy your Replit project as Autoscale if this server receives traffic from user-facing actions, or as Reserved VM if it runs background jobs on a schedule. For Autoscale, ensure your .replit file sets the run command to node server.js and the deployment target to cloudrun.

cm_transactional.py
1import os
2import requests
3
4API_KEY = os.environ["CM_API_KEY"]
5TX_BASE_URL = "https://mail.createsend.com/api/v3.3/transactional"
6AUTH = (API_KEY, "x")
7
8def send_transactional_email(
9 smart_email_id: str,
10 to_email: str,
11 to_name: str,
12 data: dict
13) -> dict:
14 """
15 Send a transactional Smart Email to one recipient.
16 data: dict of merge fields defined in the Smart Email template
17 e.g., {"order_number": "ORD-1234", "total": "$49.99"}
18 """
19 url = f"{TX_BASE_URL}/smartEmail/{smart_email_id}/send"
20 payload = {
21 "To": [f"{to_name} <{to_email}>"],
22 "Data": data,
23 "ConsentToTrack": "Yes"
24 }
25 response = requests.post(url, json=payload, auth=AUTH)
26 response.raise_for_status()
27 return response.json()
28
29# Example: Order confirmation email
30if __name__ == "__main__":
31 smart_email_id = os.environ.get("CM_TX_SMART_EMAIL_ID", "your-smart-email-id")
32 result = send_transactional_email(
33 smart_email_id=smart_email_id,
34 to_email="customer@example.com",
35 to_name="Jane Doe",
36 data={
37 "order_number": "ORD-5678",
38 "order_total": "$99.00",
39 "customer_name": "Jane Doe",
40 "delivery_date": "April 5, 2026"
41 }
42 )
43 print(f"Transactional email sent: {result}")

Pro tip: Transactional emails have separate analytics from bulk campaigns. Track delivery, opens, and clicks via the Transactional > Reports section in Campaign Monitor, or pull stats programmatically from GET /transactional/statistics.

Expected result: The transactional email is sent successfully and the recipient receives the formatted email using the Smart Email template with your dynamic data injected.

Common use cases

Automated Welcome Email on User Registration

When a user registers in your Replit web app, automatically add them to a Campaign Monitor subscriber list and trigger a welcome transactional email. The subscriber record is enriched with custom fields like first name and signup source so future campaigns can be personalized.

Replit Prompt

Build a Flask registration endpoint that saves a new user to a database and simultaneously adds them to a Campaign Monitor list using the CAMPAIGN_MONITOR_API_KEY and CAMPAIGN_MONITOR_LIST_ID from Replit Secrets, sending them a welcome transactional email.

Copy this prompt to try it in Replit

Segment-Based Campaign Trigger

A Replit backend script queries your database for users who completed a specific action β€” for example, completing a product trial β€” and creates a targeted Campaign Monitor campaign to that segment. This replaces manual CSV exports with an automated pipeline that runs on a schedule.

Replit Prompt

Write a Python script that queries a PostgreSQL database for users who completed a 14-day trial, adds them to a Campaign Monitor segment, and creates a campaign using the Campaign Monitor API to send a conversion offer email.

Copy this prompt to try it in Replit

Transactional Order Confirmation Emails

After a purchase is processed in your Replit e-commerce app, call the Campaign Monitor Transactional API to send a beautifully designed order confirmation using a pre-built template. Dynamic fields like order number, item list, and total are injected at send time.

Replit Prompt

Create an Express endpoint that receives order completion events and sends a transactional email via the Campaign Monitor API using a template ID, passing order details as dynamic content to the CAMPAIGN_MONITOR_TX_SMART_EMAIL_ID template.

Copy this prompt to try it in Replit

Troubleshooting

API returns 401 Unauthorized on every request

Cause: The API key is incorrect, has been revoked, or the Basic Auth header is not formatted correctly. Campaign Monitor expects the API key as the username with any non-empty string as the password.

Solution: Verify your API key in Campaign Monitor Account Settings > API keys. Regenerate it if needed and update the CM_API_KEY secret in Replit. Double-check that your auth tuple is (API_KEY, 'x') and not (API_KEY, '') β€” an empty password may cause issues with some HTTP clients.

typescript
1# Correct auth format for Campaign Monitor
2AUTH = (os.environ["CM_API_KEY"], "x") # 'x' is the conventional password

POST to /subscribers/{listID}.json returns 400 with 'Subscriber not in list' or invalid email error

Cause: The List ID is incorrect, the email address format is invalid, or the ConsentToTrack field is missing. Campaign Monitor requires ConsentToTrack for all subscriber additions.

Solution: Verify your List ID in Campaign Monitor by navigating to Lists & Subscribers > your list > Settings and checking the List ID in the URL. Ensure the email address is a valid format and that ConsentToTrack is set to 'Yes', 'No', or 'Unchanged' (never omit this field).

typescript
1payload = {
2 "EmailAddress": email,
3 "Name": name,
4 "Resubscribe": True,
5 "ConsentToTrack": "Yes" # Required β€” do not omit
6}

Campaign creation returns 400 with 'Campaign must include unsubscribe link'

Cause: Campaign Monitor requires every HTML campaign to include an unsubscribe link using the [unsubscribelink] merge tag. This is a legal compliance requirement and Campaign Monitor enforces it at the API level.

Solution: Add the unsubscribe merge tag to your HTML campaign content before the closing body tag. This is mandatory for all bulk email campaigns.

typescript
1html_content = """
2<html><body>
3 <p>Your campaign content here.</p>
4 <p style="font-size:12px">
5 <a href="[unsubscribelink]">Unsubscribe</a> |
6 <a href="[webversion]">View in browser</a>
7 </p>
8</body></html>
9"""

Transactional API returns 404 β€” Smart Email not found

Cause: The Smart Email ID is incorrect, or the Smart Email is in draft status rather than active. Transactional Smart Emails must be activated before they can receive API send requests.

Solution: In Campaign Monitor, go to Transactional > Smart Transactional Email, find your template, and ensure its status is 'Active'. Copy the Smart Email ID from the template's settings page (not from the URL β€” look for the ID field explicitly). Store this as CM_TX_SMART_EMAIL_ID in Replit Secrets.

Best practices

  • Always store CM_API_KEY, CM_LIST_ID, and CM_CLIENT_ID in Replit Secrets β€” never hardcode them in source files
  • Use the upsert behavior (POST with Resubscribe: True) for adding subscribers to avoid duplicate entry errors when users re-register
  • Always include the [unsubscribelink] merge tag in bulk campaign HTML to comply with CAN-SPAM and GDPR requirements
  • Set ConsentToTrack to 'Yes' only when users have explicitly consented to email tracking β€” use 'No' for jurisdictions with strict privacy laws
  • Use separate Subscriber Lists for different audience segments rather than relying solely on custom fields and tags for filtering
  • Pull campaign analytics 24-48 hours after sending, not immediately β€” open and click data accumulates over time
  • For transactional emails, use Smart Email templates designed in the Campaign Monitor editor rather than inline HTML to benefit from Campaign Monitor's rendering engine and deliverability optimizations
  • Deploy on Replit Autoscale for web-app-driven subscriber flows, and use a scheduled Reserved VM job for batch campaign triggers based on database queries

Alternatives

Frequently asked questions

How do I connect Replit to Campaign Monitor?

Generate an API key in Campaign Monitor Account Settings, then add it as CM_API_KEY in Replit Secrets (lock icon πŸ”’ in the sidebar). Use HTTP Basic Auth with the API key as the username and 'x' as the password when making requests from your Python or Node.js backend.

Does Replit work with Campaign Monitor's free trial?

Yes. Campaign Monitor's free trial gives you access to all API features including subscriber management and campaign creation. You can build and test the full integration before paying. The trial limits sending to a small number of subscribers until you activate a paid plan.

How do I store my Campaign Monitor API key securely in Replit?

Open your Replit project, click the lock icon πŸ”’ in the left sidebar, and add a new secret with key CM_API_KEY and your Campaign Monitor API key as the value. Access it in Python with os.environ['CM_API_KEY'] or in Node.js with process.env.CM_API_KEY. Never paste API keys directly into your source code.

Can I send transactional emails with Campaign Monitor from Replit?

Yes. Use Campaign Monitor's Transactional Smart Email API with the base URL mail.createsend.com. Create a Smart Email template in the Campaign Monitor dashboard, activate it, then call the send endpoint from your Replit backend with the recipient's email and any dynamic merge data.

What deployment type should I use on Replit for Campaign Monitor integrations?

Use Autoscale deployment if your Campaign Monitor calls are triggered by incoming HTTP requests (for example, subscribing a user when they register on your website). Use Reserved VM if you run scheduled batch jobs, such as nightly scripts that pull database records and trigger campaigns.

Why am I getting a 400 error when creating a Campaign Monitor campaign via the API?

The most common causes are: missing [unsubscribelink] merge tag in the HTML content (required by law and enforced by Campaign Monitor), an incorrect Client ID, or a List ID that does not belong to the specified client. Check all three values in your Replit Secrets and ensure the HTML contains an unsubscribe link.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation β€” no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.