gentic

Gentic Email Marketing — Documentation

Connect any AI agent to your Klaviyo account. Pull campaign performance — opens, clicks, conversions and revenue — in numbers that match your Klaviyo dashboard exactly. Sync the shape of your account into your organization's Brain, then search what your emails actually SAID, in natural language, including the words printed inside the images. Read-only throughout.

1. Getting Started

Sign Up & Get Your API Key

Before you can use Gentic Email Marketing, you need an API key to authenticate your requests.

  1. Go to gentic.co/email-marketing and create an account.
  2. Create an organization from your dashboard. API keys and billing are scoped to the organization.
  3. Generate an API key and use it as a Bearer token in your MCP client.

2. Connecting to the MCP Server

The server is available at https://mcp.gentic.co/email-marketing. For Claude Code:

claude mcp add gentic-email-marketing \
  --transport http \
  https://mcp.gentic.co/email-marketing \
  --header "Authorization: Bearer YOUR_API_KEY"

For Claude Web and ChatGPT you can also connect via OAuth — no API key needed. See the connect section on the landing page for other MCP clients (n8n, OpenClaw).

3. Agent Skill

For the best results, pair the MCP server with the Gentic Email Marketing agent skill. The MCP server gives your agent tool access; the skill teaches it the optimal workflow order. Both the raw SKILL.md and a ready-to-upload .skill bundle are generated on demand from the live manifest, so they always reflect the current tools and pricing.

Add the skill directly via URL:

https://gentic.co/email-marketing/SKILL.md

Or upload a .skill bundle to Claude Managed Agents:

https://gentic.co/email-marketing/gentic-email-marketing.skill

Download this file and upload it wherever Claude Managed Agents asks for a .skill file. It's a zip bundle generated on demand from the latest SKILL.md.

4. When to Apply

  • User wants campaign performance from Klaviyo — opens, clicks, conversions, revenue — for a timeframe.
  • User wants to know which campaigns drove the most revenue, or how open and click rates are trending.
  • User wants to find emails by what they SAID — a product, an offer, a promotion — rather than by name or date.
  • User wants to know what an email's creative actually showed, including text inside images.
  • User wants their Klaviyo campaigns, flows, lists, segments or metrics synced into their Brain for analysis.
  • User wants to join email engagement against orders, subscriptions, loyalty or SMS data.
  • User asks about SMS campaign performance — Klaviyo campaigns carry a send_channel, so SMS sends report here too.

5. Workflow

  1. 1. Connect Klaviyo once, then work without credentials

    The Email Marketing server sources the Klaviyo connection (the Private API key) from the org's connected integration (Gentic dashboard → Integrations → Klaviyo). You never pass credentials to the tools. Call `klaviyo_connection_status` first — it's free and returns `{ connected, account_id, updated_at }`, and never returns the API key. Pass `check_live: true` to actually verify the stored key against Klaviyo with a single one-row read. Do that once after a new connection: a key that is PRESENT is not the same as a key that WORKS, and the cheapest time to learn the difference is before a sync.

  2. 2. Reporting needs no sync — but it does need a conversion metric

    `klaviyo_report` is **free** and READ-ONLY, and you can call it before syncing anything. It returns one row per campaign message with its `send_channel`, `campaign_id` and the requested statistics. It requires a conversion metric, and there is deliberately **no default** — which metric counts as a conversion changes every number in the report, so it is always an explicit choice. Pass `conversion_metric_name: 'Placed Order'` (usually the right one) and it resolves against the org's own synced `klaviyo_metrics` table; you don't need to look up an id. That resolution needs a prior `klaviyo_sync` of the `metrics` resource — if none has run, the error tells you exactly that. An ambiguous or unknown name comes back with the real candidate list, so read the error rather than guessing again.

  3. 3. ⚠️ Why these numbers match the customer's Klaviyo dashboard

    `klaviyo_report` uses Klaviyo's **Reporting API**, which groups by **attributed send time** — the same basis the Klaviyo UI uses. Klaviyo also has a Metric Aggregates endpoint that groups by **event time** and produces DIFFERENT figures for the same window. We deliberately expose only the one surface, so a number you quote can be compared to the customer's own dashboard without reconciling two definitions. If a figure doesn't match what someone sees in Klaviyo, the cause is the timeframe or the conversion metric — not two competing definitions of the same statistic.

  4. 4. Sync the SHAPE of the account with `klaviyo_sync`

    `klaviyo_sync` is **free** and READ-ONLY. It warehouses five resources verbatim into per-org tables: `klaviyo_campaigns` (both email AND SMS), `klaviyo_flows`, `klaviyo_lists`, `klaviyo_segments` and `klaviyo_metrics`, upserted on their id so re-syncs refresh rows in place. Be precise about what this is: it syncs the **shape** of the account — campaigns, flows, lists, segments and metric definitions — **not** per-recipient events or profiles. There is no per-person event stream here. For performance figures use `klaviyo_report`; for the campaign list and its configuration use `query_data` over `klaviyo_campaigns`.

  5. 5. Walk it with bounded, resumable pagination

    Each `klaviyo_sync` call is BOUNDED: it pages until `max_pages_per_run` pages OR `max_seconds_per_run` seconds, then returns `has_more` and `next_cursor: { step, cursor }`. Call again passing that back as `cursor` until `has_more` is false. It returns `{ synced: { <resource>: count }, has_more, next_cursor, persisted, pages_fetched }` — report `persisted` per resource and whether `has_more` is still true, because a partial walk that looks complete is the failure mode worth catching. Use `resources` to sync only what you need; syncing just `metrics` is enough to unblock `klaviyo_report`.

  6. 6. Indexing email content is the one tool that costs money

    `klaviyo_sync_email_content` pulls the ACTUAL CONTENT of campaigns — subject lines, preview text, the visible body copy, and the alt text of every image — then embeds it so it can be searched. Run `klaviyo_sync` with `resources: ["campaigns"]` FIRST: this tool reads the campaign list from the warehouse and fetches content only for campaigns that don't have it yet. **Cost: 5¢ per email campaign, 1¢ per SMS campaign.** A campaign whose content is already stored and unchanged costs **nothing**, so re-running is safe and a nightly schedule only pays for new sends. It's BOUNDED and RESUMABLE via `max_campaigns_per_run` / `max_seconds_per_run` and returns `has_more` — but there is **no cursor to pass back**, because each run simply picks up campaigns that still have no content. On a large back catalogue, say what a full backfill will cost before starting one.

  7. 7. Most marketing emails hide their message inside images

    Set `describe_images: true` and the images are read by a vision model, so the text printed on the creative becomes searchable too — which for a lot of email programs is where the actual offer lives. The descriptions are **included in the 5¢**, capped at 10 images per campaign. The response reports `alt_coverage` and warns when an account's emails are too image-heavy for text-only search to work well. Treat that warning as the signal to turn `describe_images` on rather than concluding the search is broken.

  8. 8. Search the content with `klaviyo_search_emails`

    `klaviyo_search_emails` is **free** and searches the indexed content semantically — 'which emails talked about the iGel mask?', 'find the sends that mentioned free shipping'. It returns the campaign, its subject line, send time and a snippet, with `filters`, `include_body` and `limit` to narrow the result. It only READS the index; if it comes back empty, the likely cause is that `klaviyo_sync_email_content` hasn't been run for those campaigns — check that before telling the user the emails don't mention the thing.

  9. 9. Route the three question types to the right tool

    These are easy to confuse and the wrong choice produces a confidently wrong answer. Performance numbers (opens, clicks, revenue) → `klaviyo_report`. What an email SAID → `klaviyo_search_emails`. The list of campaigns and their configuration → `query_data` over `klaviyo_campaigns`. And note that `klaviyo_campaigns` and `klaviyo_report` both cover **SMS as well as email** — each row carries a `send_channel` — so SMS campaign performance is answered here, not on `/sms-marketing`, whose Postscript data has no message-performance in it at all.

  10. 10. Present results clearly

    Don't dump raw JSON. Summarize the numbers, name the timeframe and say which conversion metric was used — a report is not interpretable without it. After a sync, report `persisted` per resource and whether `has_more` is true. After a content index run, say how many campaigns were processed and what it cost. If you're about to backfill a large catalogue, give the estimate before you spend it, not after.

6. Tool Reference

5 tools, rendered live from the Gentic MCP manifest. Parameter tables come directly from each tool's JSON Schema.

klaviyo_connection_status

Free

Check whether the calling organization has connected Klaviyo (the email and SMS marketing platform). Returns `{ connected, account_id, updated_at }` when connected, or `{ connected: false }` with a hint otherwise. Free. Call before klaviyo_sync or klaviyo_report so a missing integration produces actionable guidance rather than a failed run. Never returns the API key. Set check_live to true to also VERIFY the stored key against Klaviyo with a single one-row read. Worth doing once after connecting a new Klaviyo account: a key that is present is not the same as a key that works, and the cheapest time to learn the difference is before a sync.

ParameterTypeDescription
check_liveboolean

When true, make one minimal read against Klaviyo to verify the stored key actually works. Adds a round-trip; still free.

klaviyo_report

Free

Get campaign performance from Klaviyo — opens, clicks, conversions and revenue per campaign, for a chosen timeframe. Uses the org's connected Klaviyo integration (dashboard → Integrations; no API key is passed here). Returns one row per campaign message with its `send_channel`, `campaign_id` and the requested statistics. READ-ONLY: this reads reporting figures and changes nothing in Klaviyo. NUMBERS MATCH THE KLAVIYO DASHBOARD. This uses Klaviyo's Reporting API, which groups by attributed send time — the same basis the Klaviyo UI uses. Klaviyo's Metric Aggregates endpoint groups by event time instead and produces DIFFERENT numbers for the same window; we deliberately expose only the one surface, so a figure here can be compared to the customer's Klaviyo dashboard without reconciling two definitions. Requires a conversion metric — the Klaviyo metric that counts as a conversion, usually 'Placed Order'. PASS `conversion_metric_name: 'Placed Order'` and it is resolved against this organization's own synced `klaviyo_metrics` table; you do not need to look up an id. That resolution needs a prior klaviyo_sync (the `metrics` resource) — if none has run, the error says so and tells you what to run. There is deliberately NO default metric: which metric counts as a conversion changes every number in the report, so it is always an explicit choice. FREE.

ParameterTypeDescription
conversion_metric_namestring

Name of the Klaviyo metric that counts as a conversion — usually "Placed Order". PREFER THIS over conversion_metric_id: the name is resolved against the org's own synced `klaviyo_metrics` table, so you never need to look an id up by hand. Requires a prior klaviyo_sync (metrics resource). Matching is case-insensitive, exact first, then substring; an ambiguous or unknown name comes back with the real candidate list.

conversion_metric_idstring

Klaviyo metric id, if you already have it. Usually unnecessary — pass conversion_metric_name instead and it will be resolved for you.

timeframestring

Reporting window. Defaults to last_30_days.

enum: last_7_days, last_30_days, last_90_days, last_12_months, this_month, last_month, this_year, last_year

statisticsstring[]

Which statistics to return. Omit for a standard set (delivered, open/click/conversion rates, conversion value).

klaviyo_search_emails

Free

Search the CONTENT of this organization's Klaviyo campaigns by natural language — 'which emails talked about the iGel mask?', 'find the sends that mentioned free shipping', 'what did we say about the Black Friday sale?'. Searches subject lines, preview text, body copy, image alt text and (where they were generated) AI descriptions of what the images show, ranked semantically. Returns the campaign, its subject line, send time and a snippet. Requires `klaviyo_sync_email_content` to have been run first — that is the tool that fetches and indexes the content; this one only reads it. For campaign PERFORMANCE numbers (opens, clicks, revenue) use `klaviyo_report`; for the list of campaigns and their configuration use `query_data` over `klaviyo_campaigns`. FREE.

ParameterTypeDescription
query
required
string

Natural-language search query, e.g. 'emails about the winter sale' or 'anything mentioning a clinical study'.

filtersstring

Optional SQL filter over the structured columns: channel, campaign_name, subject, send_time (TIMESTAMP), template_name. Example: "channel = 'email' AND send_time > '2026-01-01'". Read-only expressions only.

include_bodyboolean

Return the FULL content of each match — body text, every image URL, every alt text and every image description (default false). By default each result carries a ~400-character `content_excerpt` of the matched content instead, which is enough to say what an email was about; the full arrays run to thousands of tokens per result and are mostly image URLs. Turn this on when you need to quote the copy exactly or walk the images.

limitinteger

Maximum matches to return (default 10, max 50).

1 – 50

klaviyo_sync

Free

Sync email-marketing configuration from Klaviyo into this organization's data backend — READ-ONLY, verbatim, one BOUNDED chunk per call. Uses the org's connected Klaviyo integration (dashboard → Integrations; no API key is passed here). Warehouses five resources into per-org tables: `klaviyo_campaigns` (both email and SMS), `klaviyo_flows`, `klaviyo_lists`, `klaviyo_segments`, `klaviyo_metrics`, upserted on their id so re-syncs refresh rows in place. This syncs the SHAPE of the account — campaigns, flows, lists, segments and metric definitions — not per-recipient events or profiles. For campaign performance numbers use klaviyo_report. BOUNDED + RESUMABLE: each call pages only until `max_pages_per_run` pages OR `max_seconds_per_run` seconds are reached, then returns `has_more` + `next_cursor: { step, cursor }`. Call again passing that back as `cursor` until `has_more` is false. Returns `{ synced: { <resource>: count }, has_more, next_cursor, persisted, pages_fetched }`. FREE.

ParameterTypeDescription
resourcesstring[]

Subset of resources to sync this run, in order. Any of: campaigns, flows, lists, segments, metrics. Omit to sync all five. `campaigns` always walks both the email and SMS channels.

max_pages_per_runinteger

Cap on pages fetched this call (default 20, hard max 60). Page more via next_cursor, never via a bigger run.

1 – 60

max_seconds_per_runinteger

Wall-clock budget in seconds (default 60, hard max 120). The walk stops after the current page once exceeded; resume with next_cursor.

1 – 120

cursorany

Resume point from a prior call's `next_cursor` — { step, cursor }. `step` is a resource name, or `campaigns:email` / `campaigns:sms`. Omit or null to start from the beginning.

klaviyo_sync_email_content

Variable

Pull the ACTUAL CONTENT of this organization's Klaviyo campaigns — subject lines, preview text, the visible body copy of the email template, the alt text of every image, and (optionally) an AI description of what each image shows — then embed it so `klaviyo_search_emails` can search it semantically. Uses the org's connected Klaviyo integration; no API key is passed here. Run `klaviyo_sync` with `resources: ["campaigns"]` FIRST — this tool reads the campaign list from the warehouse and fetches content for campaigns that don't have it yet. BOUNDED + RESUMABLE: each call processes at most `max_campaigns_per_run` campaigns (or until `max_seconds_per_run`), then returns `has_more`. Call again until `has_more` is false — no cursor to pass back, because each run only picks up campaigns that still have no content. COST: 5¢ per email campaign, 1¢ per SMS campaign. A campaign whose content is already stored and unchanged costs NOTHING, so re-running is safe and a nightly schedule only pays for new sends. Most marketing emails carry their message inside images. Set `describe_images: true` to have the images read by a vision model so the text printed on the creative becomes searchable too; the descriptions are included in the 5¢, capped at 10 images per campaign. The response reports `alt_coverage` and warns when an account's emails are too image-heavy for text-only search to work well.

ParameterTypeDescription
campaign_idsstring[]

Specific campaign ids to (re-)fetch, e.g. to pick up an edited send. Omit to process campaigns that have no content stored yet. Content that is byte-identical to what is already stored is not charged.

describe_imagesboolean

Describe each image with a vision model so on-image copy becomes searchable (default false). Included in the per-campaign price, capped at 10 images per campaign. Adds noticeable time per campaign.

max_campaigns_per_runinteger

Cap on campaigns processed this call (default 25, hard max 100). Process more by calling again, never by raising this past the ceiling.

1 – 100

max_seconds_per_runinteger

Wall-clock budget for this call (default 60s, hard max 240s).

5 – 240

7. Pricing

Pricing is pulled live from the Gentic MCP manifest. All prices are per call and deducted from your Gentic credits.

ToolCost
klaviyo_connection_statusFree
klaviyo_reportFree
klaviyo_search_emailsFree
klaviyo_syncFree
klaviyo_sync_email_contentVariable

8. Notes

  • Organization-scoped: the Klaviyo connection comes from the org's connected integration (dashboard → Integrations → Klaviyo). No credential is ever passed to the tools, and `klaviyo_connection_status` never returns the API key.
  • Cost: `klaviyo_connection_status`, `klaviyo_report`, `klaviyo_sync` and `klaviyo_search_emails` are all **free**. Only `klaviyo_sync_email_content` costs money — **5¢ per email campaign, 1¢ per SMS campaign** — and a campaign already stored unchanged costs nothing, so re-running is safe. Pricing is pulled live from the Gentic MCP manifest.
  • Everything here is READ-ONLY: nothing sends, schedules, edits or archives anything in Klaviyo.
  • `klaviyo_report` matches the customer's Klaviyo dashboard because it uses the Reporting API, which groups by attributed send time — the same basis as the Klaviyo UI. Klaviyo's Metric Aggregates endpoint groups by event time and gives different numbers for the same window; only the one surface is exposed, deliberately.
  • `klaviyo_report` has **no default conversion metric**. Pass `conversion_metric_name` (usually 'Placed Order'); it resolves against the org's synced `klaviyo_metrics` table, which requires a prior `klaviyo_sync` of the `metrics` resource.
  • `klaviyo_sync` warehouses the **shape** of the account — `klaviyo_campaigns`, `klaviyo_flows`, `klaviyo_lists`, `klaviyo_segments`, `klaviyo_metrics` — not per-recipient events or profiles.
  • `klaviyo_campaigns` and `klaviyo_report` cover **both email and SMS**; each row carries a `send_channel`. SMS campaign performance is answered here.
  • Content search is two-stage: `klaviyo_sync_email_content` fetches and indexes, `klaviyo_search_emails` only reads the index. An empty search usually means the content wasn't indexed, not that it isn't there.
  • `describe_images: true` has images read by a vision model so text printed on the creative is searchable; included in the 5¢, capped at 10 images per campaign. The response reports `alt_coverage` and warns when an account is too image-heavy for text-only search.
  • Syncs are bounded and resumable. `klaviyo_sync` returns `has_more` + `next_cursor: { step, cursor }` to pass back as `cursor`; `klaviyo_sync_email_content` returns `has_more` with **no cursor**, because each run picks up whatever still has no content.