klaviyo
klaviyo.
The Klaviyo account the private key reaches (read only): `{id,
setup & usage
⚠ your klaviyo private API key
in Klaviyo: Settings → Account → API keys → Create Private API Key, then paste it into oto (format pk_…). Scopes are chosen at creation and cannot be added later — a missing scope means a new key:
:readGET /accounts): it checks the key and its accounts:read scope, nothing is written▸ profiles, lists and consent
klaviyo_profiles(filter='equals(email,"jane@example.com")', additional_fields=["subscriptions"]) — consent per channel includedklaviyo_profiles(op="get", profile_id="01H…", include=["lists","segments"])klaviyo_profiles(op="upsert", attributes={"email": "jane@example.com", "location": {"city": "Lyon"}}) — creates the profile when unknownklaviyo_lists(filter='equals(name,"Newsletter")') for the id, then klaviyo_lists(op="members", list_id="…", filter="greater-than(joined_group_at,2026-10-01T00:00:00Z)")klaviyo_consent(op="subscribe", profiles=[{"email": "…"}], list_id="…") — read the preview, then the same call with confirm=Trueall_pages=True (up to max_pages, 10 by default): complete says whether the walk reached the end; otherwise pass next_cursor back as page_cursor▸ campaigns, flows and performance
klaviyo_campaigns(filter="equals(status,'Sent'),greater-or-equal(scheduled_at,2026-09-01T00:00:00Z)", sort="-scheduled_at")klaviyo_metrics() for the id of Placed Order, then klaviyo_reports(op="campaigns", statistics=["recipients","open_rate","click_rate","conversions","conversion_value"], conversion_metric_id="…", timeframe="last_30_days")klaviyo_flows(filter="equals(status,'live')")klaviyo_reports(op="metric", metric_id="…", measurements=["count","sum_value"], since="2026-09-01T00:00:00", until="2026-10-01T00:00:00", timezone="Europe/Paris")klaviyo_events(filter='equals(profile_id,"01H…")', sort="-datetime", include=["metric"])· what reaches real people
the connector never sends a campaign and never creates or edits a campaign, flow or template. Four writes may still reach real people, and each returns a preview until called again with confirm=True:
klaviyo_lists(op="add")) starts the flows triggered by that list ("Added to List")klaviyo_events(op="create")) starts the flows triggered by its metric — unless backfill=Trueklaviyo_consent(op="subscribe")) changes consent; on a double opt-in list Klaviyo emails a confirmationklaviyo_consent(op="unsubscribe")) is global for a profile outside the given list, and for everyone when no list is given — the preview names them. To only leave a list: klaviyo_lists(op="remove"), which keeps consent· what is misleading
get take the 26-character id (01H…); find it with filter='equals(email,"…")'channel="sms" for the othersfull=True returns Klaviyo's raw JSON:API payload when the tightened view is not enough⚙ multiple comptes
this connector accepts multiple comptes: each stored credential becomes a named account (one name per compte), at your level, your team's or your org's.
_account="<name>" on the tool; list them: oto_identity(op='list', connector='klaviyo') (scope='org' or scope='group' for the org's or team's)oto_identity(op='set', connector='klaviyo', identity_id='<name>'); rename: op='rename' with new_name_account) and adding upoutils
chargement…
utilisation
claude code — installe le plugin oto —
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configurés.cli —
pipx install oto-cli puis oto klaviyo …