feat(klaviyo): Upgrade API to 2026-01-15 with feature flag#3707
feat(klaviyo): Upgrade API to 2026-01-15 with feature flag#3707harsh-joshi99 wants to merge 4 commits intomainfrom
Conversation
- Create versioning-info.ts with KLAVIYO_API_REVISION (2025-01-15) and KLAVIYO_CANARY_API_REVISION (2026-01-15) - Add FLAGON_NAME constant 'klaviyo-canary-api-revision' and getApiRevision(features) helper in functions.ts - Update buildHeaders() to accept optional features parameter for feature-flagged revision header - Update extendRequest in index.ts to pass features to buildHeaders - Add feature flag tests verifying stable and canary revision headers - All 135 tests passing Breaking changes analysis: no breaking changes in 2025-01-15 → 2026-01-15 window Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the api-version-upgrade Claude Code skill to .claude/skills/ for shared use across the team. Includes the main SKILL.md workflow, reference docs for common patterns/feature flags/testing, and evals. Updated test command to use `npx jest` directly (fixes --testPathPattern deprecation in newer Jest versions). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR upgrades the Klaviyo destination’s API revision handling to support a 2026-01-15 canary revision behind a feature flag, while keeping 2025-01-15 as the default stable revision. It also adds internal documentation (“skill” guides) describing a standardized workflow for API version upgrades with canary flags and testing.
Changes:
- Added stable/canary revision constants and a
getApiRevision(features)helper, then updated request header construction to be feature-flag aware. - Updated Klaviyo destination request extension to pass
featuresso the revision header can be toggled per-request. - Added unit tests validating stable vs canary revision behavior, plus new docs/skill references for version-upgrade workflows.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/destination-actions/src/destinations/klaviyo/versioning-info.ts | Introduces stable/canary Klaviyo API revision constants. |
| packages/destination-actions/src/destinations/klaviyo/functions.ts | Adds feature-flag helper and updates buildHeaders to select revision dynamically. |
| packages/destination-actions/src/destinations/klaviyo/index.ts | Threads features into extendRequest so header revision can be toggled. |
| packages/destination-actions/src/destinations/klaviyo/config.ts | Sources REVISION_DATE from the new versioning constants. |
| packages/destination-actions/src/destinations/klaviyo/breaking-changes-analysis.md | Documents changelog review for 2025-01-15 → 2026-01-15. |
| packages/destination-actions/src/destinations/klaviyo/tests/index.test.ts | Adds tests for default vs feature-flagged revision header behavior. |
| .claude/skills/api-version-upgrade/SKILL.md | Adds a procedural guide for performing canary-based API upgrades. |
| .claude/skills/api-version-upgrade/references/feature-flags.md | Adds reference guidance for feature flags (naming, examples, testing). |
| .claude/skills/api-version-upgrade/references/testing-guide.md | Adds reference guidance for running/structuring tests during upgrades. |
| .claude/skills/api-version-upgrade/references/common-patterns.md | Adds reference catalog of versioning patterns used across destinations. |
| .claude/skills/api-version-upgrade/evals/evals.json | Adds eval scenarios for validating the upgrade workflow. |
packages/destination-actions/src/destinations/klaviyo/functions.ts
Outdated
Show resolved
Hide resolved
| export function buildHeaders(authKey: string, features?: Features) { | ||
| return { | ||
| Authorization: `Klaviyo-API-Key ${authKey}`, | ||
| Accept: 'application/json', | ||
| revision: REVISION_DATE, | ||
| revision: getApiRevision(features), |
There was a problem hiding this comment.
buildHeaders now supports feature-flagged revisions, but several call sites still invoke it without passing features (e.g., within this file and in klaviyo/index.ts audience methods). Because request-client merges headers with the per-request headers taking precedence, those requests will always use the stable revision even when the canary flag is enabled. Thread features through those helper calls (or avoid overriding headers so extendRequest can supply them) to ensure the revision is consistent across all requests.
| extendRequest({ settings, features }) { | ||
| return { | ||
| headers: buildHeaders(settings.api_key) | ||
| headers: buildHeaders(settings.api_key, features) | ||
| } |
There was a problem hiding this comment.
extendRequest is feature-flag aware, but audienceConfig.createAudience/getAudience override headers via headers: buildHeaders(apiKey) and don’t pass createAudienceInput.features/getAudienceInput.features. Since per-request headers override the extended headers, canary users will still send the stable revision for these audience calls. Pass the features from the input into buildHeaders (or rely on extendRequest headers) so the feature flag applies consistently.
| // Pattern: {DESTINATION}_API_VERSION | ||
| export const KLAVIYO_API_VERSION = '2025-01-15' | ||
| export const KLAVIYO_CANARY_API_VERSION = '2026-01-15' | ||
|
|
There was a problem hiding this comment.
The constant-name examples use KLAVIYO_API_VERSION / KLAVIYO_CANARY_API_VERSION, but this PR introduces KLAVIYO_API_REVISION / KLAVIYO_CANARY_API_REVISION for Klaviyo. Update the examples (or generalize them) so the guide doesn’t point contributors to non-existent identifiers.
| // Pattern: {DESTINATION}_API_VERSION | |
| export const KLAVIYO_API_VERSION = '2025-01-15' | |
| export const KLAVIYO_CANARY_API_VERSION = '2026-01-15' | |
| // Pattern: {DESTINATION}_API_REVISION (for date-based APIs like Klaviyo) | |
| export const KLAVIYO_API_REVISION = '2025-01-15' | |
| export const KLAVIYO_CANARY_API_REVISION = '2026-01-15' | |
| // Pattern: {DESTINATION}_API_VERSION (for versioned APIs like Google CM360) |
…ntion - Move FLAGON_NAME/getApiRevision exports after all import statements (fixes import/first lint violation flagged in code review) - Rename feature flag from 'klaviyo-canary-api-revision' to 'klaviyo-canary-version' to match repo convention used by google-enhanced, first-party-dv360, facebook-capi, etc. - Update skill docs to use consistent '-canary-version' suffix with real in-repo examples, add import-order warning to SKILL.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a __validation__/ suite that makes real HTTP calls against both
the stable (2025-01-15) and canary (2026-01-15) revisions and
structurally diffs the responses — catching breaking changes that
mocked unit tests cannot detect.
Files:
- fixtures.ts — one fixture per API endpoint; write fixtures use
revision-scoped emails to prevent 409 conflicts
- normalizer.ts — strips non-deterministic fields (IDs, timestamps)
before diffing so structural changes are signal
- differ.ts — deep structural diff with human-readable output
- validate.ts — runner script, sequential calls per fixture, writes
validation-report.md
Result: 9/9 endpoints structurally identical across both revisions.
validation-report.md committed as evidence.
Also:
- gitignore __validation__/validation-report.md by default; force-add
to upgrade PRs only, delete at canary promotion cleanup
- Add Step 5.5 to api-version-upgrade skill documenting the workflow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| @@ -0,0 +1,238 @@ | |||
| #!/usr/bin/env npx ts-node | |||
There was a problem hiding this comment.
The shebang #!/usr/bin/env npx ts-node is not a valid/portable shebang on most systems because the kernel only passes a single optional argument to the interpreter; /usr/bin/env will try to execute a literal command named "npx ts-node" and fail if someone runs this script directly. Consider removing the shebang entirely (since the documented usage is npx ts-node ...) or switching to a single-command shebang like #!/usr/bin/env ts-node (and ensure ts-node is resolvable).
| #!/usr/bin/env npx ts-node |
| resolve({ | ||
| status: res.statusCode ?? 0, | ||
| headers: res.headers as Record<string, string>, | ||
| body: parsed | ||
| }) |
There was a problem hiding this comment.
res.headers is IncomingHttpHeaders (string | string[] | undefined values). Casting it to Record<string, string> can produce arrays/undefined at runtime and may cause the normalizer/differ to report false diffs or throw in edge cases. Prefer normalizing headers into a string map (e.g., join string arrays and drop undefined) before returning HttpResponse.headers.
| } | ||
|
|
||
| if (Array.isArray(stable) !== Array.isArray(canary)) { | ||
| changes.push({ type: 'changed', path, stable: 'array', canary: typeof canary }) |
There was a problem hiding this comment.
In the array-vs-non-array mismatch branch, the Change details are incorrect when the canary value is the array (it always sets stable: 'array' and canary: typeof canary, which would be 'object' for arrays). To keep the report accurate, compute both sides (e.g., stable: Array.isArray(stable) ? 'array' : typeof stable, canary: Array.isArray(canary) ? 'array' : typeof canary).
| changes.push({ type: 'changed', path, stable: 'array', canary: typeof canary }) | |
| changes.push({ | |
| type: 'changed', | |
| path, | |
| stable: Array.isArray(stable) ? 'array' : typeof stable, | |
| canary: Array.isArray(canary) ? 'array' : typeof canary | |
| }) |
Summary
Upgrades Klaviyo API from 2025-01-15 to 2026-01-15 behind feature flag `klaviyo-canary-version`, validated against the real Klaviyo API.
Changes
Version Management
Real API Validation
Unit Tests
Skill
Known Limitation
`buildHeaders()` calls in `getList`, `createList`, `createAudience`, `getAudience` use stable revision unconditionally — these audience-management functions don't have `features` in their call signatures. Follow-up PR if needed.
Breaking Changes
Risk Level: LOW — All changes between `2025-01-15` and `2026-01-15` are additive. Confirmed by real API validation. See `breaking-changes-analysis.md`.
Validation Report
See `packages/destination-actions/src/destinations/klaviyo/validation/validation-report.md`
Rollout Plan
🤖 Generated with Claude Code