@todoforai/mailchimp-api
v1.1.0
Published
JSON-first CLI for the official Mailchimp Marketing API
Readme
Mailchimp Marketing CLI
Independent CLI over the official Mailchimp Marketing API v3.0. It is not an official Mailchimp product. Built for scripts and agents: JSON output, 1:1 API fields, discoverable payload schemas, and explicit write confirmation.
Run locally
cd api-apps/mailchimp-api
npm install --workspaces=false
bun run build
node dist/index.js --help
# Optional: install the built CLI on this machine
npm pack
npm install -g ./todoforai-mailchimp-api-1.0.0.tgz --ignore-scripts
mailchimp-api --versionRequires Node >=20 for the built executable, Bun for development. This package has not necessarily been published to npm; the commands above work from the checkout.
Authentication
Create a Mailchimp API key under Account & billing → Extras → API keys. An API key grants broad account access. Use a secret manager or stdin, not a committed file or literal shell argument.
# With MAILCHIMP_API_KEY already supplied securely by your environment:
mailchimp-api whoami
mailchimp-api auth # verifies and saves that key
# Or pipe an API key from your secret manager:
# <secret-manager-command> | mailchimp-api auth --key-stdinOAuth. In TODOforAI, Connect Mailchimp runs the OAuth consent in your browser; the server exchanges the code and pipes only the access token into mailchimp-api auth --token-stdin on your machine, which resolves the data center from Mailchimp's OAuth metadata and saves it like a key. Tokens never expire — revoke them in Mailchimp (Profile → Extras → Connected apps). Manually: MAILCHIMP_ACCESS_TOKEN + MAILCHIMP_SERVER_PREFIX. When both are present, an API key wins over a token.
The data center is inferred from the key suffix (-us21). Override with MAILCHIMP_SERVER_PREFIX. Credentials are saved as ~/.config/mailchimp-api/credentials.json, mode 0600; XDG_CONFIG_HOME is respected. Environment keys override stored credentials. This implements own-account API-key auth, not multi-user OAuth onboarding.
Coverage
155 API endpoint commands in 25 groups, generated from Mailchimp's official expanded Swagger specification. Generated files are committed; no runtime spec download is required.
| Area | Groups and operations |
|---|---|
| Audiences | lists: create/update/delete, activity, growth, tag search, bulk member subscribe/update |
| Contacts | members: list/get/create/upsert/update/archive/permanent delete, activity; search members; email addresses accepted wherever subscriber_hash is expected |
| Organization | tags, segments, segment-members, merge-fields, interest-categories, interests, notes, events |
| Campaigns | campaigns: drafts/settings/content, checklist, test, send, schedule/unschedule, replicate, resend, pause/resume; campaign-folders; search campaigns |
| Reporting | reports: summary, clicks/link members, opens, recipient activity, delivery recipients, unsubscribes, abuse, locations, domains, subreports, landing-page reports |
| Content | templates, template-folders, files, file-folders, landing-pages |
| Automation | automations: classic workflows, email settings, queues, start/pause/archive; journeys trigger for an existing API-trigger step |
| Operations | webhooks, batches, batch-webhooks, verified-domains, account info and ping |
| Escape hatch | request for other Marketing API endpoints, including account-specific newer APIs |
Email-marketing audiences are exposed as lists, matching the established /lists API. Mailchimp's newer /audiences omni-channel APIs are not silently substituted; use request when needed.
Intentionally not given dedicated commands: Transactional/Mandrill, Open Commerce, SMS, ads, ecommerce-store synchronization, surveys, conversations, connected sites, and account administration. These are separate products or secondary workflows, not prerequisites for core email marketing. The raw command only accesses the Marketing API; it cannot call separate product APIs.
The API does not expose everything the Mailchimp UI can do. There is no visual journey builder here; journey triggers require an existing configured journey. Feature access, scheduling and sending quotas depend on the account and paid plan.
Examples
All writes—including draft edits and test sends—require --yes. Inspect before executing.
mailchimp-api lists list --all
mailchimp-api members list LIST_ID --status subscribed --all
mailchimp-api search members --query [email protected]
# Inspect request fields, without auth or network (use placeholder IDs as needed):
mailchimp-api members upsert LIST_ID [email protected] --schema
# Add a new contact with double opt-in; do not force existing unsubscribed contacts back in:
mailchimp-api members upsert LIST_ID [email protected] \
--data '{"email_address":"[email protected]","status_if_new":"pending"}' --dry-run
# Replace --dry-run with --yes only after reviewing.
mailchimp-api tags update LIST_ID [email protected] \
--data '{"tags":[{"name":"Customers","status":"active"}]}' --yes
mailchimp-api campaigns create --data '{"type":"regular","recipients":{"list_id":"LIST_ID"},"settings":{"subject_line":"News","title":"Newsletter draft","from_name":"Your Team","reply_to":"[email protected]"}}' --yes
mailchimp-api campaigns set-content CAMPAIGN_ID --data @content.json --yes
# content.json: {"html":"<html><body>...</body></html>"}
mailchimp-api campaigns test CAMPAIGN_ID \
--data '{"test_emails":["[email protected]"],"send_type":"html"}' --yes
mailchimp-api campaigns send-checklist CAMPAIGN_ID
mailchimp-api campaigns send CAMPAIGN_ID --dry-run
# Sending to the audience requires changing --dry-run to --yes.
mailchimp-api campaigns schedule CAMPAIGN_ID \
--data '{"schedule_time":"2030-01-15T10:00:00+00:00"}' --dry-run
mailchimp-api reports get CAMPAIGN_ID
mailchimp-api reports email-activity CAMPAIGN_ID --all
mailchimp-api lists batch-members LIST_ID --data @members.json --dry-run
mailchimp-api batches create --data @operations.json --dry-run
mailchimp-api batches get BATCH_ID
mailchimp-api request GET /lists --query count=100
mailchimp-api request GET /lists/LIST_ID/members --all membersNamed options retain API spelling (--sort_field, --since_send_time). Use --param key=value on endpoint commands for additional query fields, or --query key=value on raw requests. Search commands use --query for Mailchimp's actual search text. JSON payloads can be inline, @file.json, or - for stdin. --schema prints the endpoint, supported query parameters, and request-body schema.
Safety and operational behavior
- Read commands do not need confirmation. Every write requires
--yes, including raw API calls and batches whose payload could send a campaign or delete contacts. No interactive prompts in automation. --dry-runmakes no network requests and needs no credential. Its output can include contact data or campaign content; treat previews as private.- Archive is reversible in ways permanent deletion is not:
members archiveuses DELETE on a member;delete-permanenterases personal data and prevents re-import. Never use permanent deletion for routine list cleanup. - Consent is your responsibility.
status_if_new=pendingrequests double opt-in for new contacts; do not blindly setstatus=subscribedon existing contacts. --allfetches pages sequentially, preserving the response envelope.countis 1–1000,offsetis the starting position. It accumulates data in memory and rejectsfields/exclude_fieldsto prevent incomplete exports. Avoid changing the audience during an offset-based export.- API errors go to stderr as JSON, with non-zero exit status and Retry-After where supplied. CLI parser errors (unknown commands/options or missing arguments) use Commander's standard stderr diagnostics.
- No automatic retries, especially no replay of writes. The API allows at most 10 concurrent connections/account; timeout is 120 seconds. Retry read requests after backoff when appropriate.
- Batch creation is asynchronous, not evidence of completion. Inspect
batches get,status, anderrored_operations; a finished batch can contain failures. Use the returnedresponse_body_urlto retrieve results promptly. The CLI does not automatically download or extract batch archives. - Keys are sent only to the selected
https://usN.api.mailchimp.com/3.0/endpoint. Absolute URLs, path traversal and redirects are rejected. - API payload validation belongs to Mailchimp. CLI preview is not a server-side validation or delivery guarantee.
Development and verification
bun test
bun run test:node
node dist/index.js --help
# Regenerate endpoint definitions, then review and run tests:
curl -fsSL 'https://api.mailchimp.com/schema/3.0/Swagger.json?expand' -o /tmp/mailchimp.json
python3 scripts/generate.py /tmp/mailchimp.jsonTests cover all 155 command mappings, write guards, payload input, credentials, request construction, HTTP failures, pagination, and endpoint isolation using local fixtures. Live account/plan behavior still needs a real Mailchimp account; no tests send campaigns or touch live contacts.
Docs: https://mailchimp.com/developer/marketing/
Release integration
The package is registered in the API-apps workspace, npm publish workflow, and shared tool catalog. Publish the package before deploying the catalog entry; otherwise the connector install button will receive an npm 404. Catalog registration alone does not publish or deploy anything.
