# How to Integrate Retool with Mailchimp

- Tool: Retool
- Difficulty: Beginner
- Time required: 15 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Mailchimp by creating a REST API Resource using Mailchimp's API key for Basic Auth. The base URL must include your data center prefix (e.g., https://us14.api.mailchimp.com/3.0). Once configured, build queries to manage lists, view campaign stats, add subscribers, and trigger campaigns from a centralized Retool email marketing dashboard.

## Build a Mailchimp Email Marketing Dashboard in Retool

Mailchimp's native analytics dashboard shows campaign performance, but navigating between lists, segments, and campaigns to find specific data is cumbersome. Marketing operations teams often need a single view showing all active campaigns with open rates, click rates, and subscriber counts side by side — or a subscriber management panel where they can search, add, remove, and tag contacts without going through Mailchimp's multi-step UI.

Mailchimp's Marketing API v3 provides complete programmatic access to your audiences (lists), campaigns, templates, and automations. Authentication uses an API key that you generate in your Mailchimp account settings. The key encodes the data center (server) your account is hosted on — this data center prefix must be included in the base URL, which is the most common configuration mistake when connecting Mailchimp to external tools.

Retool's REST API Resource handles Mailchimp's Basic Auth scheme cleanly — you configure it once and all subsequent queries inherit the authentication. Build a dashboard where marketing teams can view campaign metrics at a glance, manage subscriber lists, and trigger campaigns without leaving Retool.

## Before you start

- A Mailchimp account with at least one audience (list) and ideally some campaigns
- A Mailchimp API key (generated from Account → Extras → API Keys in Mailchimp)
- Your Mailchimp data center prefix (the last segment of your API key, e.g., 'us14' from a key ending in '-us14')
- A Retool account with permission to create Resources
- Basic familiarity with Retool's query editor and Table/Chart components

## Step-by-step guide

### 1. Generate a Mailchimp API key and identify your data center

In Mailchimp, click your account avatar (top-right) → Account & Billing → Extras → API Keys. Click Create A Key. Give it a descriptive name like 'Retool Integration' and click Generate Key. Copy the API key — it looks like: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us14.

The critical detail is the data center suffix at the end of the key — the part after the dash (in this example, 'us14'). This tells you which Mailchimp data center your account is hosted on, and it must be included in your API base URL. Every Mailchimp API call for your account must go to https://us14.api.mailchimp.com (or whichever prefix yours shows).

If your key ends in '-us1', use https://us1.api.mailchimp.com. If it ends in '-us6', use https://us6.api.mailchimp.com — the number varies. Using the wrong data center prefix (or omitting it entirely and using https://api.mailchimp.com) will result in 404 or redirect errors.

Also note your Mailchimp audience (list) IDs — you'll need these for subscriber queries. Find them in Mailchimp under Audience → Manage Audience → Settings → Audience Name and Defaults → the Audience ID is shown there.

**Expected result:** You have a Mailchimp API key, know your data center prefix (e.g., us14), and have your audience ID ready.

### 2. Create the Mailchimp REST API Resource in Retool

In Retool, navigate to the Resources tab and click Add Resource. Select REST API.

Name: Mailchimp API

Base URL: https://YOUR_DC.api.mailchimp.com/3.0

Replace YOUR_DC with your data center prefix (e.g., us14). Include the /3.0 version path in the base URL — all Mailchimp Marketing API v3 endpoints start with this.

Authentication: Select Basic Auth. In the Username field, enter anystring (literally — Mailchimp accepts any value for the username when using API key auth, 'anystring' is the conventional placeholder). In the Password field, enter your API key.

Alternatively, if you prefer to store the key in Configuration Variables: go to Settings → Configuration Variables, create MAILCHIMP_API_KEY with your key value, mark it as secret, then use the Password field value: {{ retoolContext.configVars.MAILCHIMP_API_KEY }}.

Add a Content-Type header: Key: Content-Type, Value: application/json. This is needed for POST/PATCH requests.

Click Create Resource. Test with a GET to /lists — if it returns a JSON object with a lists array, the connection is working. If you get an error, double-check the data center prefix in the base URL.

**Expected result:** The Mailchimp API resource is created and a test GET /lists returns your Mailchimp audiences in JSON format.

### 3. Fetch campaigns and build the campaign list

Create a query named getCampaigns. Set method to GET and path to /campaigns. Mailchimp campaigns can be filtered by status and type using query parameters:

- status: sent (show only sent campaigns; use 'sending', 'paused', 'schedule', 'draft', 'canceled' for other states)
- type: regular (use 'absplit', 'rss', 'automation', 'variate' for other types)
- count: {{ pagination.pageSize || 25 }}
- offset: {{ pagination.offset || 0 }}
- sort_field: send_time
- sort_dir: DESC

The response includes a campaigns array. Each campaign has an id, web_id, settings.subject_line, settings.from_name, send_time, status, and a report_summary object containing opens.open_rate, clicks.click_rate, emails_sent, and unsubscribes.

Create a transformer to flatten campaign data for the Table component. Map the nested settings, report_summary, and recipients objects into flat fields that Retool's Table can display without nested object rendering.

```
// Transformer for Mailchimp campaigns
const campaigns = data.campaigns || [];
return campaigns.map(campaign => ({
  id: campaign.id,
  web_id: campaign.web_id,
  subject: campaign.settings?.subject_line || '(no subject)',
  from_name: campaign.settings?.from_name || '',
  status: campaign.status,
  type: campaign.type,
  emails_sent: campaign.emails_sent || 0,
  send_time: campaign.send_time ? new Date(campaign.send_time).toLocaleDateString() : 'Not sent',
  open_rate: campaign.report_summary?.open_rate
    ? `${(campaign.report_summary.open_rate * 100).toFixed(1)}%` : 'N/A',
  click_rate: campaign.report_summary?.click_rate
    ? `${(campaign.report_summary.click_rate * 100).toFixed(1)}%` : 'N/A',
  unsubscribes: campaign.report_summary?.unsubscribes || 0,
  list_name: campaign.recipients?.list_name || '',
  archive_url: campaign.archive_url || ''
}));
```

**Expected result:** The getCampaigns query returns a flat array of campaigns with open and click rates displayed as percentages in the Retool Table.

### 4. Fetch audience lists and subscriber data

Create a query named getLists to fetch your Mailchimp audiences. Set method to GET and path to /lists. Add count: 100 to get all lists. The response includes a lists array with each audience's id, name, stats.member_count, stats.open_rate, stats.click_rate, and date_created.

Bind the response to a Select component (select_list) for the subscriber management view. When a list is selected, fetch subscribers with a getMembers query: GET /lists/{{ select_list.value }}/members.

Subscriber query parameters:
- count: {{ pagination.pageSize || 25 }}
- offset: {{ pagination.offset || 0 }}
- status: subscribed (or 'unsubscribed', 'cleaned', 'pending')
- fields: members.id,members.email_address,members.status,members.merge_fields,members.stats,members.timestamp_signup,members.tags

Using the fields parameter limits the response size significantly — Mailchimp subscriber objects can be very large. Select only the fields you need for display.

The merge_fields object contains standard fields like FNAME (first name) and LNAME (last name). Your specific audience may have additional custom merge fields — check Mailchimp → Audience → Signup Forms to see all merge fields and their tags.

```
// Transformer for Mailchimp subscribers
const members = data.members || [];
return members.map(member => ({
  id: member.id,
  email: member.email_address,
  status: member.status,
  first_name: member.merge_fields?.FNAME || '',
  last_name: member.merge_fields?.LNAME || '',
  full_name: `${member.merge_fields?.FNAME || ''} ${member.merge_fields?.LNAME || ''}`.trim(),
  open_rate: member.stats?.avg_open_rate
    ? `${(member.stats.avg_open_rate * 100).toFixed(1)}%` : 'N/A',
  click_rate: member.stats?.avg_click_rate
    ? `${(member.stats.avg_click_rate * 100).toFixed(1)}%` : 'N/A',
  joined: member.timestamp_signup ? new Date(member.timestamp_signup).toLocaleDateString() : '',
  tags: (member.tags || []).map(t => t.name).join(', '),
  source: member.source || ''
}));
```

**Expected result:** The getLists and getMembers queries populate a subscriber management panel showing contact details, engagement stats, and tags.

### 5. Add subscriber management actions

With subscriber data displayed in the Table, add CRUD operations for subscriber management. The key endpoints are:

Add subscriber (subscribe): PUT /lists/{{ select_list.value }}/members/{{ MD5_of_email_lowercase }} with a body containing email_address, status: 'subscribed', and merge_fields. Mailchimp uses the MD5 hash of the lowercase email as the member ID for PUT operations — you'll need a JavaScript expression to compute this. Retool doesn't have built-in MD5, so compute it in a JavaScript query or use Retool's Built-in crypto if available.

Alternatively, use POST /lists/{{ select_list.value }}/members to add new members (with email_address, status, and merge_fields).

Update subscriber tags: POST /lists/{{ select_list.value }}/members/{{ table1.selectedRow.data.id }}/tags with body: {"tags": [{"name": "{{ textInput_tag.value }}", "status": "active"}]}.

Unsubscribe: PATCH /lists/{{ select_list.value }}/members/{{ table1.selectedRow.data.id }} with body: {"status": "unsubscribed"}.

Delete subscriber: DELETE /lists/{{ select_list.value }}/members/{{ table1.selectedRow.data.id }}.

For all write operations, set query to run on Manual trigger only and wire them to button components with confirmation dialogs (use Retool's confirmModal.show() for the destructive delete/unsubscribe operations).

```
// Add subscriber request body
{
  "email_address": "{{ textInput_email.value.toLowerCase() }}",
  "status": "subscribed",
  "merge_fields": {
    "FNAME": "{{ textInput_firstName.value }}",
    "LNAME": "{{ textInput_lastName.value }}"
  },
  "tags": {{ JSON.stringify((textInput_tags.value || '').split(',').map(t => t.trim()).filter(Boolean)) }}
}
```

**Expected result:** The subscriber management panel supports adding, tagging, unsubscribing, and deleting contacts directly from Retool, with each action refreshing the subscriber Table.

### 6. Build campaign performance charts

Add visual analytics to your dashboard using Retool's Chart component (Plotly.js-powered). For campaign performance trends, create a Chart showing open rate and click rate over time using getCampaigns data filtered to the last 12 months.

For list growth visualization, use the /lists/{{ select_list.value }}/growth-history endpoint which returns monthly subscriber counts and unsubscribe rates. This gives you the data for a Line chart showing audience growth over time.

Create a getGrowthHistory query: GET /lists/{{ select_list.value }}/growth-history with count: 12 for the last 12 months. The response includes a history array with month (YYYY-MM format), subscribed, and unsubscribed counts.

For the Chart component, configure:
- X-axis: month field from growth history
- Y-axis: two traces — subscribed (blue) and unsubscribed (red)
- Chart type: Line

For subscriber geographic distribution, use the /reports/{campaign_id}/locations endpoint which returns countries/cities where the campaign was opened. Display this in a Table sorted by opens count.

Add Stat components at the top of the dashboard showing: Total Audiences, Total Subscribers (sum across all lists), Average Open Rate (average of all campaign open rates), and Campaigns Sent This Month.

```
// Transformer for growth history chart data
const history = data.history || [];
const sorted = history.sort((a, b) => a.month.localeCompare(b.month));

return {
  x: sorted.map(h => h.month),
  subscribed: sorted.map(h => h.subscribed),
  unsubscribed: sorted.map(h => h.unsubscribed),
  net_growth: sorted.map(h => h.subscribed - h.unsubscribed)
};
```

**Expected result:** A campaign performance dashboard with trend charts, list growth history, and summary stats. Marketing teams can see email performance trends at a glance.

## Best practices

- Always include the data center prefix in your Mailchimp base URL — using the wrong server will cause all requests to fail silently or return 404 errors.
- Store the Mailchimp API key in Retool Configuration Variables (Settings → Configuration Variables) marked as secret rather than hardcoding it in the resource configuration.
- Use the fields query parameter on subscriber list requests to limit response size — Mailchimp subscriber objects are large and requesting all fields for 1000+ subscribers creates slow queries.
- Use PUT instead of POST for subscriber operations when the subscriber may already exist — PUT is idempotent and handles both create and update scenarios.
- Implement MD5 hashing for subscriber hash IDs in a JavaScript query rather than computing them in the URL template, as inline crypto is not available in all Retool expression contexts.
- Set destructive operations (unsubscribe, delete) to require manual confirmation using Retool's modal or confirm dialog before executing — email list changes are hard to reverse.
- Cache the getLists query for at least 5 minutes since audience list changes are infrequent — this reduces API calls and improves dashboard load time.
- Use Mailchimp's batch endpoint (POST /batches) for bulk operations on many subscribers — it's more efficient and less likely to hit rate limits than individual requests.

## Use cases

### Build a campaign performance monitoring dashboard

Create a Retool dashboard showing all recent Mailchimp campaigns with their send stats: open rate, click rate, unsubscribe rate, and total recipients. Marketing managers can compare performance across campaigns, identify underperforming sends, and drill into individual campaign reports.

Prompt example:

```
Build a Retool email marketing dashboard showing recent Mailchimp campaigns in a Table. Include campaign name, send date, subject line, open rate, click rate, unsubscribe count, and total sends. Add a Chart showing open rate trend over time. Include a Date Range filter for the campaign list.
```

### Build a subscriber management panel

Build a Retool tool for managing Mailchimp subscribers: search for contacts by email or tag, view their engagement history, add new subscribers to lists, and update tags or segments. This is faster than Mailchimp's native audience management UI for high-frequency subscriber operations.

Prompt example:

```
Build a Retool subscriber management panel with a search input for email address or name. Show subscriber status (subscribed/unsubscribed), join date, email open rate, and current tags in a Table. Include a form to add new subscribers with email, first name, last name, and tags. Add an Unsubscribe button for selected rows.
```

### Build a list health and engagement report

Create a Retool analytics panel showing audience health metrics: total subscribers, growth rate, average engagement score, top performing segments, and geographic distribution of opens. Helps marketing teams understand list quality and identify re-engagement opportunities.

Prompt example:

```
Build a Retool audience health dashboard showing Mailchimp list stats: total subscribed, total unsubscribed, open rate trend, and click rate trend. Show a Chart of subscriber growth over the last 12 months. Include a Table of top segments by engagement. Add stat components for average email client and device breakdown.
```

## Troubleshooting

### All API requests return a 404 or redirect to a generic error page

Cause: The base URL is missing the data center prefix or is using the wrong data center. Mailchimp requires your account's specific data center in the URL.

Solution: Check the end of your API key for the data center suffix (e.g., the key 'abc123-us14' means use https://us14.api.mailchimp.com/3.0). Update your Retool resource's base URL to include the correct data center. Verify by navigating to https://us14.api.mailchimp.com/3.0/ in a browser with your API key as Basic Auth — you should see account metadata.

### 401 Unauthorized despite correct API key

Cause: Mailchimp's Basic Auth requires 'anystring' as the username and the API key as the password. If the username and password fields are reversed, authentication fails.

Solution: In the Retool resource Basic Auth configuration, confirm that Username is 'anystring' (or any literal string) and Password is your API key. The username value itself doesn't matter — Mailchimp only checks the password field for the API key.

### Subscriber operations fail with 400: 'Member Exists'

Cause: Using POST to add a subscriber who is already in the list (even if unsubscribed) returns this error. POST only works for truly new email addresses.

Solution: Use PUT /lists/{listId}/members/{subscriberHash} instead of POST when you're not sure if the subscriber exists. PUT creates a new member if not found, or updates the existing member if they are. The subscriberHash is the MD5 hash of the subscriber's email address in lowercase.

```
// To compute subscriber hash for the URL:
// In a JavaScript query:
const email = textInput_email.value.toLowerCase();
// Note: You'll need an MD5 library or use CryptoJS if available
// The hash format: md5(email) converts to hex string
```

### Campaign report data (open rate, click rate) is null or missing

Cause: Campaign reports are only available for campaigns with status 'sent'. Drafts, scheduled, and paused campaigns don't have report_summary data.

Solution: Filter your getCampaigns query with status=sent to only show sent campaigns. Add null checks in your transformer: campaign.report_summary?.open_rate ?? 0 to handle campaigns where report data hasn't populated yet.

## Frequently asked questions

### Does Retool have a native Mailchimp connector?

No, Retool does not have a dedicated native Mailchimp connector. You connect via a REST API Resource using Mailchimp's API key in Basic Auth. The connection setup takes about 15 minutes and gives full access to all Mailchimp Marketing API v3 endpoints.

### Why does my Mailchimp API call return a different data center error?

Mailchimp routes each account to a specific server cluster (data center). The data center prefix (e.g., us14) is encoded in your API key. If you use the wrong data center in the URL, Mailchimp returns an error directing you to use the correct server. Check your API key's suffix to find the right data center prefix for your base URL.

### Can I send campaigns from Retool through Mailchimp?

Yes. Use POST /campaigns/{id}/actions/send to send a draft campaign that's already been created and configured in Mailchimp. You can also schedule a campaign using POST /campaigns/{id}/actions/schedule with a schedule_time in ISO 8601 format. Creating entire campaigns from scratch via the API is possible but complex — it's usually more practical to use Mailchimp's UI to design campaigns and use Retool to trigger sends based on business logic.

### What is a Mailchimp audience (list) and how does it relate to subscriber management?

In Mailchimp, an 'audience' (formerly called a 'list') is the primary organizational unit for contacts. Each audience has its own subscription settings, merge fields, groups, and segments. Most accounts have one audience for all contacts; larger accounts may have separate audiences for different products or regions. When adding subscribers via the API, you must specify which audience (list) to add them to using the list ID.

### How do I handle Mailchimp API rate limits?

Mailchimp allows 10 simultaneous connections and has a rate limit of around 300 requests per minute for the Marketing API. For bulk subscriber imports (hundreds or thousands of contacts), use Mailchimp's batch endpoint (POST /batches) which accepts up to 500 operations per batch request. For regular dashboard queries, avoid polling faster than every 60 seconds to stay comfortably within limits.

---

Source: https://www.rapidevelopers.com/retool-integrations/mailchimp
© RapidDev — https://www.rapidevelopers.com/retool-integrations/mailchimp
