Skip to content

MT-22401: Add Email Campaigns API - #148

Open
Rabsztok wants to merge 6 commits into
mainfrom
MT-22401-nodejs-email-campaigns
Open

MT-22401: Add Email Campaigns API#148
Rabsztok wants to merge 6 commits into
mainfrom
MT-22401-nodejs-email-campaigns

Conversation

@Rabsztok

@Rabsztok Rabsztok commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Draft until the server-side Email Campaigns API changes are released.

Motivation

MT-22401

Port the Email Campaigns public API (MT-21113) to the Node.js SDK. The MCP server's campaigns tools depend on this landing and being released to npm.

Changes

  • Add client.emailCampaigns covering the full contract: getList (page-token pagination + search), get, create, update, delete (204 → void), the five lifecycle actions (start, schedule, cancel, terminate, reset), and getStats with an optional date range
  • Types follow the published OpenAPI schema: flat request bodies, {data} response envelopes (Webhooks convention), numeric domain_id (matching the Sending Domains endpoints ids), rapid/gradual delivery modes, 10-value CampaignState, audience id arrays, TemplateAttributes (subject required on create) with body_html/body_text/merge_tags, per-recipient state-metadata errors
  • Full-lifecycle example in examples/email-campaigns/everything.ts + README bullet

How to test

  • Run examples/email-campaigns/everything.ts with a real API token and a verified sending domain — create a draft, update design/audience, schedule + cancel, fetch stats, delete
  • Verify a lifecycle 422 (e.g. cancel on a draft) surfaces the API error message

Summary by CodeRabbit

  • New Features

    • Added email campaign management, including creation, editing, scheduling, sending, cancellation, termination, reset, and deletion.
    • Added campaign performance statistics with optional date filtering.
    • Added typed support for campaign states, templates, delivery options, pagination, and lifecycle responses.
  • Documentation

    • Added an end-to-end email campaigns workflow example.
  • Tests

    • Added coverage for campaign operations, requests, responses, and error handling.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a typed Email Campaigns API with CRUD, lifecycle actions, scheduling, termination, reset, statistics, MailtrapClient exposure, Axios-mock tests, and an end-to-end example documented in the README.

Changes

Email campaigns integration

Layer / File(s) Summary
Campaign contracts and resource operations
src/types/api/common.ts, src/types/api/email-campaigns.ts, src/lib/api/resources/EmailCampaigns.ts, src/__tests__/lib/api/resources/EmailCampaigns.test.ts
Defines campaign entities, request parameters, responses, lifecycle states, pagination, and statistics. Implements and tests the corresponding Axios endpoints.
MailtrapClient exposure
src/lib/MailtrapClient.ts, src/lib/api/EmailCampaigns.ts, src/__tests__/lib/api/EmailCampaigns.test.ts
Adds the emailCampaigns getter and binds the resource operations through the base API using the shared Axios instance.
End-to-end usage example
examples/email-campaigns/everything.ts, README.md
Adds a complete campaign workflow and links it from the supported examples list.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant MailtrapClient
  participant EmailCampaignsBaseAPI
  participant EmailCampaignsApi
  participant MailtrapAPI
  Client->>MailtrapClient: access emailCampaigns
  MailtrapClient->>EmailCampaignsBaseAPI: construct accessor with shared Axios instance
  EmailCampaignsBaseAPI->>EmailCampaignsApi: bind campaign methods
  EmailCampaignsApi->>MailtrapAPI: send CRUD or lifecycle request
  MailtrapAPI-->>EmailCampaignsApi: return campaign, stats, or error
Loading

Possibly related PRs

Suggested labels: feature request

Suggested reviewers: piobeny, vladimirtaytor, mklocek

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes motivation, detailed changes, and test steps; only the non-critical images section is omitted.
Title check ✅ Passed The title clearly and concisely identifies the addition of the Email Campaigns API.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Rabsztok
Rabsztok marked this pull request as ready for review July 30, 2026 12:03
@Rabsztok
Rabsztok requested review from IgorDobryn and piobeny July 30, 2026 12:12
@Rabsztok

Copy link
Copy Markdown
Contributor Author

Applied the same fix CodeRabbit raised on the Python PR: client.emailCampaigns no longer calls validateAccountIdPresence() — the endpoint is token-scoped (matches the inbound getter precedent), and the example no longer configures accountId. Full suite (410 tests) + lint green.

@Rabsztok
Rabsztok marked this pull request as draft July 31, 2026 11:56
Decisions:
- Request bodies are flat (no email_campaign wrapper) per the current OpenAPI contract
- Single-object and stats responses keep the {data} envelope (Webhooks convention; the axios interceptor only unwraps the HTTP body)
- delete() returns void — the API responds 204 No Content
- Added the five lifecycle endpoints (start/schedule/cancel/terminate/reset) with schedule taking {datetime}
- current_state typed as the 10-value enum; domain_id is the numeric sending-domain ID from the Sending Domains endpoints; template_attributes shared between create and update with no template id
@Rabsztok
Rabsztok force-pushed the MT-22401-nodejs-email-campaigns branch from ac3adfd to 47c3416 Compare August 6, 2026 12:05
@Rabsztok
Rabsztok marked this pull request as ready for review August 7, 2026 07:24
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/email-campaigns/everything.ts`:
- Around line 62-66: Replace the hard-coded past datetime in the schedule call
with an execution-relative future time, and update the statistics request to
omit the fixed May 2026 filter or generate a window covering the campaign’s
actual send time. Preserve the subsequent cancellation, sending, termination,
statistics, and deletion flow in the example.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a6faa18b-135f-4a61-a765-a94f584cc216

📥 Commits

Reviewing files that changed from the base of the PR and between 85245f4 and 47c3416.

📒 Files selected for processing (8)
  • README.md
  • examples/email-campaigns/everything.ts
  • src/__tests__/lib/api/EmailCampaigns.test.ts
  • src/__tests__/lib/api/resources/EmailCampaigns.test.ts
  • src/lib/MailtrapClient.ts
  • src/lib/api/EmailCampaigns.ts
  • src/lib/api/resources/EmailCampaigns.ts
  • src/types/api/email-campaigns.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • README.md
  • src/tests/lib/api/EmailCampaigns.test.ts
  • src/lib/MailtrapClient.ts
  • src/lib/api/EmailCampaigns.ts
  • src/tests/lib/api/resources/EmailCampaigns.test.ts
  • src/types/api/email-campaigns.ts
  • src/lib/api/resources/EmailCampaigns.ts

Comment thread examples/email-campaigns/everything.ts
Decisions:
- The endpoint is token-scoped and resolves the account server-side, so
  requiring accountId made a valid token-only client unusable (matches
  the inbound getter precedent and the fix applied to the Python SDK)
- Example no longer configures accountId
@Rabsztok
Rabsztok force-pushed the MT-22401-nodejs-email-campaigns branch from 47c3416 to d5a81a9 Compare August 7, 2026 09:54
Decisions:
- Nothing in the payload is campaign-specific; the next paginated resource
  should reuse it rather than redeclare it
Decisions:
- "/api/accounts/{account_id}/email_campaigns" does not exist, so there is no
  need to contrast the real path against it
- Keep the positive fact that the account comes from the API token; it explains
  why the path takes no account id
Comment thread examples/email-campaigns/everything.ts Outdated
Comment thread src/lib/api/resources/EmailCampaigns.ts Outdated
Comment on lines +91 to +92
* Delete an email campaign by ID. The campaign must not be in a sending
* state. Returns nothing (204 No Content).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Delete an email campaign by ID. The campaign must not be in a sending
* state. Returns nothing (204 No Content).
* Delete an email campaign by ID. Only a campaign in the draft state can be deleted.
* Returns nothing (204 No Content).

Comment thread README.md
- Custom fields CRUD – [`contact-fields/everything.ts`](examples/contact-fields/everything.ts)
- Import/Export – [`contact-imports/everything.ts`](examples/contact-imports/everything.ts), [`contact-exports/everything.ts`](examples/contact-exports/everything.ts)
- Events – [`contact-events/everything.ts`](examples/contact-events/everything.ts)
- Email campaigns CRUD, lifecycle & stats – [`email-campaigns/everything.ts`](examples/email-campaigns/everything.ts)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is "Contact management:" the correct section for this?

Decisions:
- The backend allows deleting only a campaign in the draft state
  (EmailCampaign#validate_soft_delete), not merely a non-sending one
- Examples deleted a campaign after start/terminate, which would 422; a started
  campaign can never return to draft, so they now delete a fresh draft
Decisions:
- Campaigns are an Email Marketing feature, not contact management or Email
  API/SMTP, so they were filed under the wrong heading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants