Skip to main content
A Klaviyo account over the API a lifecycle marketing integration actually uses: profiles with real upsert semantics, lists and membership as relationships, consent per channel with the bulk jobs that move it, event ingestion that creates its metric and its profile on first use, segments whose membership is computed from their definition, and campaigns that queue a send job and go out when the sandbox is advanced. Klaviyo has no sandbox at all — no test mode, no mock server, and no way to try a campaign send without a real account and real profiles. Anyone building an agent that touches Klaviyo today is testing against production or not testing. Slug: klaviyo

Segment membership is derived, never stored

This is the behaviour the twin exists for. What agents do with Klaviyo more than anything else is write a segment definition and then check who is in it, and a segment whose membership were frozen at creation would answer that with yesterday’s answer forever — while the caller believed its segment logic worked. So GET /api/segments/{id}/profiles evaluates the definition against the profiles the account holds now, every time it is read. Change a profile so it no longer qualifies, read again, and it is gone. A set_segment_lag directive makes membership lag by a number of advances, because Klaviyo’s own is eventually consistent in production and a twin that is instantly exact teaches the wrong thing.

The SDK version is the API revision

Klaviyo versions its API by a dated revision header on every request — never a path segment, never optional — and it generates its client per revision, pinning the header inside the release. So the revision this image serves was not chosen: it is KlaviyoAPI._REVISION out of the pinned klaviyo-api 24.0.0, which is 2026-07-15, and Klaviyo’s published specification reports the same string. A missing revision is refused rather than quietly served, because this image serves exactly one and a fallback would be a claim it cannot honour.

What it models

Advancing the sandbox steps the asynchronous half: bulk jobs move one state, a campaign send job performs its send, a scheduled campaign whose time has passed queues one, and lagging segment membership catches up. Nothing else ages — profiles do not decay and segments do not expire.

Scenarios

stocked-account, suppressed-profiles, pending-bulk-job, campaign-scheduled, narrow-scopes, rate-limited, empty-account.

Not modelled

Flow creation and flow logic — flows are read-only, because a flow definition is a visual builder’s document — the client-side tracking endpoints and the public site id beyond refusing it, Coupons, Reviews, Forms, Data Privacy deletion requests, Webhooks and their delivery, Reporting and Predictive Analytics as computed values, Catalog and CDP objects, A/B test campaign variations, SMS and push campaigns, and OAuth app install — the twin is handed a private key. Two things the twin is deliberately careful about. A route Klaviyo has and this twin has not built is refused with a code Klaviyo never sends, never not_found: revisions genuinely remove endpoints, so a caller reading not_found could reasonably conclude the endpoint was retired. And predictive_analytics is null on a free plan rather than a set of invented numbers — on a paid one the twin reports the figures it can derive from the events it holds and omits the model outputs it cannot compute. The twin’s own README explains every such decision and where each number came from.