Skip to content

Add App API newsletter core methods - #235

Merged
mike-engel merged 3 commits into
mainfrom
cdp-6270
Jul 9, 2026
Merged

mike-engel merged 3 commits into
mainfrom
cdp-6270

Conversation

@mike-engel

@mike-engel mike-engel commented Jul 8, 2026 •

Copy link
Copy Markdown
Collaborator

A new set of the App API backfill which adds the core newsletter endpoints (CRUD, contents, metrics, send/schedule). Localization + test groups are added in #236

New methods (14)

listNewsletters, createNewsletter, getNewsletter, deleteNewsletter, getNewsletterContents, getNewsletterContent, updateNewsletterContent, getNewsletterContentMetrics, getNewsletterContentMetricsLinks, getNewsletterMetrics, getNewsletterMetricsLinks, getNewsletterMessages, sendNewsletter, scheduleNewsletter.

Assisted by AI 🤖


Note

Medium Risk
Adds sendNewsletter and scheduleNewsletter, which can trigger real customer messaging; otherwise additive SDK wrappers with validation consistent with existing broadcast methods.

Overview
Extends APIClient with Customer.io App API newsletter support, reusing the existing campaign/broadcast pattern via an updated resourceBase('newsletters', …) helper.

Core surface: list/create/get/delete newsletters; content variants (list/get/update); newsletter- and content-level metrics and link metrics; messages listing with channel filters; sendNewsletter and scheduleNewsletter.

Also in this diff: language CRUD on newsletters and on test groups (list/create test groups plus per-group language endpoints). New option types include ListNewslettersOptions, NewsletterMetricsOptions (no per-channel type on metrics), NewsletterChannelType, and NewsletterMessagesOptions.

Docs in docs/app.md document every new method. Tests stub HTTP paths and query strings in test/api.ts; test/integration/live.ts adds read-only checks for listNewsletters and optional CIO_TEST_NEWSLETTER_ID lookups (mutating/send paths stay unit-tested only).

Reviewed by Cursor Bugbot for commit edf85ee. Bugbot is set up for automated code reviews on this repo. Configure here.

Batch 6 of the App API backfill. Adds fourteen newsletter methods to APIClient:

- listNewsletters / createNewsletter / getNewsletter / deleteNewsletter
- getNewsletterContents / getNewsletterContent / updateNewsletterContent
- getNewsletterContentMetrics / getNewsletterContentMetricsLinks
- getNewsletterMetrics / getNewsletterMetricsLinks / getNewsletterMessages
- sendNewsletter / scheduleNewsletter

Reuses buildQueryString, LinkMetricsOptions, and the private resourceBase()
helper (widened to include 'newsletters'). Adds newsletter-specific option
types (ListNewslettersOptions, NewsletterMetricType, NewsletterMetricsOptions,
NewsletterMessagesOptions) since newsletters use a different channel set
(inbox; no whatsapp/slack).

Includes unit tests (100% coverage), live integration coverage (reads gated on
the existing CIO_TEST_NEWSLETTER_ID; send/schedule/create left to unit tests),
and docs in docs/app.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mike-engel mike-engel changed the title Add App API newsletter core methods (CDP-6270) Add App API newsletter core methods Jul 8, 2026
@mike-engel mike-engel self-assigned this Jul 8, 2026
Comment thread lib/api.ts
Comment on lines +1985 to +2003
getNewsletterContentMetricsLinks(
newsletterId: string | number,
contentId: string | number,
options: NewsletterMetricsOptions = {},
) {
if (isEmpty(newsletterId)) {
throw new MissingParamError('newsletterId');
}

if (isEmpty(contentId)) {
throw new MissingParamError('contentId');
}

const query = buildQueryString({ period: options.period, steps: options.steps, type: options.type });

return this.request.get(
`${this.resourceBase('newsletters', newsletterId)}/contents/${encodeURIComponent(contentId)}/metrics/links${query}`,
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex is flagging that the current backend link metrics handler reads unique for content link metrics. So this should use LinkMetricsOptions and serialize { period, steps, unique }

Comment thread lib/api.ts
Comment on lines +216 to +221
export type NewsletterMetricsOptions = {
period?: MetricsPeriod;
steps?: number;
/** Scope the report to a single channel. */
type?: NewsletterMetricType;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Another issue flagged by codex:

NewsletterMetricsOptions advertises type, and getNewsletterContentMetrics / getNewsletterMetrics forward it, but current services origin/main newsletter metrics always use channeltype.All. So getNewsletterMetrics(id, { type: "email" }) silently returns all-channel metrics. Either remove type from the SDK/docs/tests for newsletter metrics or land backend support first.

Comment thread lib/api.ts
Comment on lines +223 to +233
/** Options for {@link APIClient.getNewsletterMessages}. */
export type NewsletterMessagesOptions = PaginationOptions & {
/** Filter to deliveries with this metric (e.g. `delivered`, `opened`, `bounced`). */
metric?: string;
/** Only include deliveries after this Unix timestamp (seconds). */
start_ts?: number;
/** Only include deliveries before this Unix timestamp (seconds). */
end_ts?: number;
/** When `true`, include tracked responses on each delivery. */
get_tracked_responses?: boolean;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should this expose type? The shared deliveries handler supports it, and the campaign/broadcast message methods already include it.

mattander
mattander previously approved these changes Jul 8, 2026

@mattander mattander 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.

A few issues then this should be fine.

…ples (CDP-6270 review)

Verified against the backend (ext_api/newsletters + ext_api/deliveries):

- Newsletter metrics are always aggregated across all channels
  (metrics.go uses channeltype.All); the API ignores a channel `type` filter.
  Removed `type` from getNewsletterMetrics / getNewsletterContentMetrics.
- Content link metrics read `unique`, not `type` (link_metrics.go). Switched
  getNewsletterContentMetricsLinks to LinkMetricsOptions.
- Newsletter messages DO support a channel `type` filter (shared
  deliveries.Index / parse.go), so added `type` to getNewsletterMessages.
- createNewsletter requires `recipients`; scheduleNewsletter uses
  `scheduled_at` + `timezone` (not `timestamp`). Fixed docs/examples/tests.

Renamed NewsletterMetricType -> NewsletterChannelType (now used for the
messages channel filter).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mike-engel
mike-engel merged commit 103af0c into main Jul 9, 2026
11 checks passed
@mike-engel
mike-engel deleted the cdp-6270 branch July 9, 2026 09:35
@mike-engel mike-engel mentioned this pull request Jul 15, 2026
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.

2 participants