← back to Ventura Claw
server/connectors/mailchimp.js
45 lines
// Mailchimp — REAL. API key includes the data-center suffix (e.g. abc-us6).
function key(creds) {
const k = creds?.MAILCHIMP_API_KEY || process.env.MAILCHIMP_API_KEY;
if (!k) throw new Error("MAILCHIMP_API_KEY not set");
return k;
}
function dc(creds) {
const k = key(creds);
const m = k.match(/-([a-z0-9]+)$/i);
if (!m) throw new Error("MAILCHIMP_API_KEY missing data-center suffix (e.g. -us6)");
return m[1];
}
async function call(method, path, body, creds) {
const url = `https://${dc(creds)}.api.mailchimp.com/3.0${path}`;
const auth = Buffer.from(`apikey:${key(creds)}`).toString("base64");
const r = await fetch(url, {
method,
headers: { "Authorization": `Basic ${auth}`, "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined
});
const d = r.status === 204 ? {} : await r.json();
if (!r.ok) throw new Error(`mailchimp ${path} ${r.status}: ${d.detail || d.title || JSON.stringify(d).slice(0,200)}`);
return d;
}
module.exports = {
meta: { id: "mailchimp", name: "Mailchimp", category: "marketing", docsUrl: "https://mailchimp.com/developer/marketing/api/", auth: "api_key", realImpl: true },
fields: [{ key: "MAILCHIMP_API_KEY", label: "API Key (with -dc suffix)", type: "password", required: true, hint: "e.g. abc123-us6 — Account > Extras > API keys" }],
configured(c) { return !!(c?.MAILCHIMP_API_KEY || process.env.MAILCHIMP_API_KEY); },
async health(c) {
if (!this.configured(c)) return { ok: false, reason: "no_token" };
try { const d = await call("GET", "/", null, c); return { ok: true, account: d.account_name, total_subscribers: d.total_subscribers, dc: dc(c) }; }
catch (e) { return { ok: false, reason: e.message }; }
},
actions: {
async "lists.list"(_, c) { return call("GET", "/lists?count=50", null, c); },
async "list.members.list"({ list_id, count }, c) { return call("GET", `/lists/${list_id}/members?count=${count||50}`, null, c); },
async "member.upsert"({ list_id, email, status, merge_fields, tags }, c) {
const hash = require("crypto").createHash("md5").update(String(email).toLowerCase()).digest("hex");
return call("PUT", `/lists/${list_id}/members/${hash}`, { email_address: email, status_if_new: status||"subscribed", status: status||"subscribed", merge_fields, tags }, c);
},
async "campaigns.list"(_, c) { return call("GET", "/campaigns?count=20", null, c); },
async "campaign.send"({ campaign_id }, c) { return call("POST", `/campaigns/${campaign_id}/actions/send`, null, c); }
}
};