From 17d7e4b7689492391beaf41f48f0a5ddeca8630b Mon Sep 17 00:00:00 2001 From: Nic Sequenzy Date: Thu, 4 Jun 2026 02:13:30 +0000 Subject: [PATCH] docs: add Sequenzy email marketing skill --- README.md | 1 + skills/sequenzy-email-marketing/README.md | 15 + skills/sequenzy-email-marketing/SKILL.md | 77 +++ .../agents/openai.yaml | 4 + .../references/command-reference.md | 478 +++++++++++++++++ .../references/use-cases.md | 492 ++++++++++++++++++ 6 files changed, 1067 insertions(+) create mode 100644 skills/sequenzy-email-marketing/README.md create mode 100644 skills/sequenzy-email-marketing/SKILL.md create mode 100644 skills/sequenzy-email-marketing/agents/openai.yaml create mode 100644 skills/sequenzy-email-marketing/references/command-reference.md create mode 100644 skills/sequenzy-email-marketing/references/use-cases.md diff --git a/README.md b/README.md index 18ab938..a74cd0b 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Skills work seamlessly with **Command Code** providing consistent, high-quality - **[Competitive Ads Extractor](skills/competitive-ads-extractor/)** - Extracts and analyzes competitors' ads from ad libraries to understand messaging and creative approaches that resonate. - **[Domain Name Brainstormer](skills/domain-name-brainstormer/)** - Generates creative domain name ideas and checks availability across multiple TLDs including .com, .io, .dev, and .ai extensions. - **[Lead Research Assistant](skills/lead-research-assistant/)** - Identifies and qualifies high-quality leads by analyzing your product, searching for target companies, and providing actionable outreach strategies. +- **[Sequenzy Email Marketing](skills/sequenzy-email-marketing/)** - Operates Sequenzy lifecycle email marketing and transactional email workflows: subscribers, segments, campaigns, sequences, templates, and stats. ### Document Management diff --git a/skills/sequenzy-email-marketing/README.md b/skills/sequenzy-email-marketing/README.md new file mode 100644 index 0000000..a8d2685 --- /dev/null +++ b/skills/sequenzy-email-marketing/README.md @@ -0,0 +1,15 @@ +# sequenzy-email-marketing + +Hermes-compatible Agent Skill for operating Sequenzy lifecycle email marketing and transactional email workflows. + +## Source + +- Canonical skill: https://github.com/Sequenzy/skills/tree/main/skills/sequenzy-email-marketing +- ClawHub listing: https://clawhub.ai/polnikale/sequenzy-email-marketing + +## Use cases + +- Manage subscribers, lists, tags, and segments. +- Create and update campaigns, sequences, and templates. +- Draft lifecycle email content and subject lines. +- Send transactional email and inspect delivery stats. diff --git a/skills/sequenzy-email-marketing/SKILL.md b/skills/sequenzy-email-marketing/SKILL.md new file mode 100644 index 0000000..8eb1ecc --- /dev/null +++ b/skills/sequenzy-email-marketing/SKILL.md @@ -0,0 +1,77 @@ +--- +name: sequenzy-email-marketing +description: Agent guide for operating Sequenzy. Use when Codex needs to authenticate, inspect identity, manage subscribers, create or edit campaigns/sequences/templates, generate draft email content, send a transactional email, read delivery stats, or decide whether a requested Sequenzy workflow is currently supported. Prefer the CLI when it is implemented, and fall back to the dashboard or direct API use when the current CLI surface is only partial. +--- + +# Sequenzy Email Marketing + +## Overview + +Use this skill when the task is to operate Sequenzy, not to change Sequenzy's source code. Prefer the `sequenzy` CLI for supported workflows, treat `packages/mcp/src/tools/index.ts` as the MCP source of truth when the task goes through MCP tools, and explicitly call out when a requested workflow is not wired in the current implementation. + +## Ground Rules + +1. Treat `packages/cli/src/index.tsx` as the source of truth for which commands are actually wired. +2. Treat `packages/cli/src/commands/` and `packages/cli/src/api.ts` as the source of truth for CLI behavior, payload shape, and API routes. +3. Treat `packages/mcp/src/tools/index.ts` as the source of truth for MCP tool names, arguments, and preflight validation. +4. Do not promise support for commands or tools that only appear in docs or `--help` text without an attached implementation. +5. Prefer `sequenzy login` for interactive auth and `SEQUENZY_API_KEY` for automation. +6. Prefer inspection before mutation whenever the workflow allows it. + +## Supported Workflows + +Read [references/use-cases.md](references/use-cases.md) before executing anything non-trivial. The currently implemented CLI flows are: + +- login and logout +- local auth/session check with `whoami` +- account inspection with `account` +- company inspection or creation with `companies list|get|create` +- stats overview or stats by campaign/sequence ID +- subscribers `list`, `add`, `get`, and `remove`, with `list` fetching every page by default and supporting tag, segment, and list filters +- lists `list`, `create`, `add-subscribers`, and `import` alias for bulk list population from emails, JSON, CSV, or newline files +- tags `list` +- segments `list`, `create`, and `count`, including `--match any`, nested filter roots, custom event filters, and saved-segment composition filters +- templates `list`, `get`, `create`, `update`, and `delete`, with `list` supporting label filters and `create`/`update` accepting labels, raw HTML, or Sequenzy block JSON +- campaigns `list`, `get`, `create`, `update` including label and reply-to updates, `schedule`, and `test`, with `list` supporting label filters, `create` accepting labels plus raw HTML, Sequenzy block JSON, or prompt-generated content, `update` accepting labels plus raw HTML or Sequenzy block JSON, and `schedule` returning a review preview link +- MCP template and campaign tools support labels on list/create/update; MCP `update_campaign` also supports `replyTo` and `replyProfileId`, and MCP `schedule_campaign` schedules draft or already scheduled campaigns +- MCP `search_subscribers` supports list filters through `list`, `listId`, or `listName`; MCP `add_subscribers_to_list` accepts up to 500 emails per call +- sequences `list`, `get`, `create`, `update`, `enable`, `disable`, `delete`, and `cancel-enrollments`, including explicit discount action steps, cancellation by subscriber ID or event-property field values, and `update` branch insertion with tag, list, segment, event, clicked-link, and field conditions; event and clicked-link branch checks can use `activityScope` (`this_sequence`, `previous_email`, `ever`) +- AI generation with `generate email`, `generate sequence`, and `generate subjects` +- dashboard URL generation with CLI `urls`, MCP `get_app_urls`, and `appUrls`/`url` fields on campaign, sequence, template, and company results +- websites `list`, `add`, `check`, and `guide` +- API key creation with `api-keys create` +- send one transactional email by template or raw HTML + +## Unsupported Or Placeholder Workflows + +Treat missing subcommands as unsupported even when the noun exists. For example: campaign immediate send, pause/cancel flows, list deletion, and tag mutation are not available through the current CLI handlers. Bulk list population is supported through `sequenzy lists add-subscribers` and its `sequenzy lists import` alias, not through `subscribers add`. + +## Execution Pattern + +1. Check auth first with `sequenzy whoami` or by verifying `SEQUENZY_API_KEY` is set. +2. Pick the narrowest command that matches the use case. +3. Validate IDs, recipient email, subject, template, or content input before issuing a mutation. +4. Surface CLI limitations directly instead of inventing a workaround. +5. If the workflow is unsupported in the CLI, say whether the next-best path is the Sequenzy dashboard or direct API use. +6. When you create, inspect, or schedule a campaign, sequence, template, or company and the user may want to review/edit it, surface the dashboard URL from `url`, `previewUrl`, or `appUrls` in the tool/CLI output. If needed, generate it with `sequenzy urls` or MCP `get_app_urls`. +7. Call out implementation caveats that matter operationally, such as `whoami` using cached local auth state, sequence creation supporting both `--goal` and explicit step modes, explicit discount steps requiring Stripe before activation, generated sequences being capped at 10 emails, `campaigns test` being a stubbed success path in the current backend, and conditional email content requiring block JSON rather than raw HTML. + +## Dashboard URLs + +Use `SEQUENZY_APP_URL` as the dashboard base when it is set; otherwise default to `https://sequenzy.com`. + +Prefer actual URLs returned by the CLI/MCP result: + +- sequence editor: `/dashboard/company/{companyId}/sequences/{sequenceId}` +- campaign editor: `/dashboard/company/{companyId}/campaign/{campaignId}` +- campaign preview/review: `/dashboard/company/{companyId}/campaign/{campaignId}?step=review` +- template/email editor: `/dashboard/company/{companyId}/emails/{emailId}` +- settings: `/dashboard/company/{companyId}/settings` +- settings tab: `/dashboard/company/{companyId}/settings?tab={tab}` + +Useful settings tabs include `domain`, `tracking`, `localization`, `integrations`, `events`, `tags`, `goals`, `sync-rules`, `api-keys`, `widgets`, and `team`. + +## References + +- [references/command-reference.md](references/command-reference.md): exact command shapes, env vars, behavior, and caveats. +- [references/use-cases.md](references/use-cases.md): decision trees and examples for the most common agent tasks. diff --git a/skills/sequenzy-email-marketing/agents/openai.yaml b/skills/sequenzy-email-marketing/agents/openai.yaml new file mode 100644 index 0000000..ff4d94e --- /dev/null +++ b/skills/sequenzy-email-marketing/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Sequenzy Email Marketing" + short_description: "Agent guide for using Sequenzy safely" + default_prompt: "Use $sequenzy-email-marketing to choose the right Sequenzy workflow and complete the task safely." diff --git a/skills/sequenzy-email-marketing/references/command-reference.md b/skills/sequenzy-email-marketing/references/command-reference.md new file mode 100644 index 0000000..e2fb848 --- /dev/null +++ b/skills/sequenzy-email-marketing/references/command-reference.md @@ -0,0 +1,478 @@ +# Command Reference + +## Source Of Truth + +- Command registration: `packages/cli/src/index.tsx` +- Auth storage and config: `packages/cli/src/config.ts` +- HTTP requests: `packages/cli/src/api.ts` +- Implemented handlers: `packages/cli/src/commands/` + +If docs and code disagree, trust the code. + +## Authentication + +### Interactive login + +```bash +sequenzy login +``` + +- starts device auth against `POST /api/device-auth/initiate` +- polls `POST /api/device-auth/poll` +- opens `${SEQUENZY_APP_URL}/setup/auth?code=...` in the browser +- stores the API key in `Bun.secrets` when available, otherwise in local config + +### Non-interactive auth + +Set `SEQUENZY_API_KEY` in the environment. `packages/cli/src/config.ts` checks this before local storage, so it is the safest path for automation. + +### Identity and logout + +```bash +sequenzy whoami +sequenzy account +sequenzy logout +``` + +Behavior: + +- `whoami` prints cached local config only +- `account`: `GET /api/v1/account` +- `logout` removes locally stored auth + +Caveat: + +- treat `whoami` as "is this machine authenticated?" rather than authoritative server-side account discovery + +## Environment Variables + +```bash +SEQUENZY_API_KEY=... +SEQUENZY_API_URL=https://api.sequenzy.com +SEQUENZY_APP_URL=https://sequenzy.com +``` + +Notes: + +- `SEQUENZY_API_KEY` overrides local keychain/config state +- the current CLI code defaults `SEQUENZY_APP_URL` to `https://sequenzy.com` +- many company-scoped commands accept `--company`, which sends `x-company-id` for personal API keys + +## Dashboard URLs + +```bash +sequenzy urls --company comp_123 +sequenzy urls --company comp_123 --sequence seq_123 +sequenzy urls --company comp_123 --campaign camp_123 +sequenzy urls --company comp_123 --template tmpl_123 +sequenzy urls --company comp_123 --settings-tab integrations +sequenzy urls --company comp_123 --json +``` + +Behavior: + +- uses `SEQUENZY_APP_URL` as the base URL, defaulting to `https://sequenzy.com` +- if `--company` is omitted, tries the current company from `GET /api/v1/account` +- returns route templates, settings tab values, and concrete URLs when a company ID is known +- campaign, sequence, template, company, and account outputs include `url` or `appUrls` fields when the company can be resolved + +Common route patterns: + +- sequence editor: `/dashboard/company/{companyId}/sequences/{sequenceId}` +- campaign editor: `/dashboard/company/{companyId}/campaign/{campaignId}` +- template/email editor: `/dashboard/company/{companyId}/emails/{emailId}` +- settings: `/dashboard/company/{companyId}/settings` +- settings tab: `/dashboard/company/{companyId}/settings?tab={tab}` + +## Stats + +```bash +sequenzy stats +sequenzy stats --period 30d +sequenzy stats --campaign camp_123 +sequenzy stats --sequence seq_123 +``` + +Behavior: + +- no ID: `GET /api/v1/metrics?period=7d|30d|90d` +- `--campaign`: `GET /api/v1/metrics/campaigns/:id` +- `--sequence`: `GET /api/v1/metrics/sequences/:id` + +Output includes: + +- `sent` +- `delivered` +- `opened` +- `clicked` +- `unsubscribed` +- `openRate` +- `clickRate` + +## Subscribers + +### List + +```bash +sequenzy subscribers list +sequenzy subscribers list --tag vip +sequenzy subscribers list --list "Master List" --json +sequenzy subscribers list --segment seg_123 +sequenzy subscribers list --limit 100 +sequenzy subscribers list --tag vip --company comp_123 --json +``` + +Behavior: + +- sends `GET /api/v1/subscribers` +- maps `--segment` to `segmentId` +- maps `--tag` to `tags` +- maps `--list` to `list`; the API resolves list ID first, then exact list name +- maps `--limit` to `limit` +- fetches every result page by default when `--limit` is omitted +- supports `--company` and `--json` + +### Add + +```bash +sequenzy subscribers add user@example.com +sequenzy subscribers add user@example.com --tag premium --attr name=John --attr plan=pro +sequenzy subscribers add user@example.com --tag premium --tag beta --company comp_123 --json +``` + +Behavior: + +- sends `POST /api/v1/subscribers` +- body shape is `{ email, tags, customAttributes }` +- supports repeated `--tag` values +- supports `--company` and `--json` + +### Get + +```bash +sequenzy subscribers get user@example.com +sequenzy subscribers get user@example.com --company comp_123 --json +``` + +Behavior: + +- sends `GET /api/v1/subscribers/:email` +- returns the full subscriber profile, including list memberships, sequence enrollments, email stats, and recent activity +- supports `--company` and `--json` + +### Remove + +```bash +sequenzy subscribers remove user@example.com +sequenzy subscribers remove user@example.com --hard +sequenzy subscribers remove user@example.com --company comp_123 --json +``` + +Behavior: + +- without `--hard`, sends `PATCH /api/v1/subscribers/:email` with `{ status: "unsubscribed" }` +- with `--hard`, sends `DELETE /api/v1/subscribers/:email` +- supports `--company` and `--json` + +## Transactional Send + +### Template-based + +```bash +sequenzy send user@example.com --template tmpl_123 --var name=John +``` + +### Raw HTML + +```bash +sequenzy send user@example.com --subject "Hello" --html "

Hi

" +sequenzy send user@example.com --subject "Hello" --html-file ./email.html +``` + +Behavior: + +- sends `POST /api/v1/transactional/send` +- body shape is `{ to, templateId, subject, html, variables }` + +Validation enforced by the CLI: + +- require either `--template` or `--html`/`--html-file` +- require `--subject` when sending raw HTML + +## Companies, Lists, Tags, And Segments + +### Companies + +```bash +sequenzy companies list +sequenzy companies get comp_123 +sequenzy companies create example.com --name Example +``` + +Behavior: + +- `companies list`: `GET /api/v1/companies` +- `companies get`: `GET /api/v1/companies/:id` +- `companies create`: `POST /api/v1/companies` + +### Lists + +```bash +sequenzy lists list +sequenzy lists create Newsletter --description "Public newsletter list" +sequenzy lists create VIP --private --company comp_123 +sequenzy lists add-subscribers list_123 --email one@example.com two@example.com +sequenzy lists add-subscribers list_123 --emails-json '["one@example.com","two@example.com"]' +sequenzy lists add-subscribers list_123 --emails-file ./batch-001.csv +sequenzy lists import list_123 --emails-file ./batch-001.csv +``` + +Behavior: + +- `lists list`: `GET /api/v1/lists` +- `lists create`: `POST /api/v1/lists` +- create body shape is `{ name, description, isPrivate }` +- `lists add-subscribers` and `lists import`: `POST /api/v1/lists/:listId/subscribers` +- add-subscribers body shape is `{ emails, duplicateStrategy, enrollInSequences, optInMode }` +- the CLI splits large files into API-safe batches of up to 500 emails +- files may be newline-separated, CSV with an email column, a JSON email array, or a JSON object with `emails` or `subscribers` +- CSV headers named `email`, `e-mail`, `email address`, or `mail` are detected; otherwise the first column is used + +### Tags + +```bash +sequenzy tags +sequenzy tags --company comp_123 --json +``` + +Behavior: + +- sends `GET /api/v1/tags` +- this is list-only; there are no tag mutation commands in the current CLI + +### Segments + +```bash +sequenzy segments list +sequenzy segments count seg_123 +sequenzy segments create --name "Bought Pro" --stripe-product prod_pro +sequenzy segments create --name "3+ Pro Payments" --stripe-product prod_pro --purchase-operator at-least --payments 3 +sequenzy segments create --name "VIP or Churn Risk" --match any --filter-json '[{"field":"tag","operator":"contains","value":"vip"},{"field":"emailOpened","operator":"is_not","value":"30d"}]' +sequenzy segments create --name "Active non-paying" --filter-json '{"kind":"group","id":"root","joinOperator":"and","children":[{"kind":"filter","id":"f1","field":"attribute","operator":"gte","value":"last_login_days_ago:0"},{"kind":"group","id":"g1","joinOperator":"or","children":[{"kind":"filter","id":"f2","field":"attribute","operator":"is_empty","value":"plan_end"},{"kind":"filter","id":"f3","field":"attribute","operator":"lt","value":"plan_end:2026-04-21"}]}]}' +``` + +Behavior: + +- `segments list`: `GET /api/v1/segments` +- `segments count`: `GET /api/v1/segments/:id/count` +- `segments create`: `POST /api/v1/segments` +- `--filter-json` accepts either the legacy raw segment filter array or a nested filter `root` object +- `--match all|any` controls whether top-level filters are combined with `and` or `or` +- MCP/API use `filterJoinOperator: "and" | "or"` for the same behavior +- nested segment logic uses `{ "kind": "group", "joinOperator": "and" | "or", "children": [...] }` +- custom event filters use `field: "event"` with values like `saas.purchase:30d`, `saas.purchase:all`, or `saas.purchase:5:30d` +- saved segment composition uses `field: "segment"` with `operator: "is" | "is_not"` and the referenced segment id as `value` +- Stripe product filters use `field: "stripeProduct"` and product IDs, not product names +- threshold operators encode the count as `productId:count`, for example `prod_pro:3` + +## Templates + +```bash +sequenzy templates list +sequenzy templates list --label edm +sequenzy templates get tmpl_123 +sequenzy templates create welcome --subject "Welcome" --label edm --html-file ./welcome.html +sequenzy templates create welcome --subject "Welcome" --blocks-file ./welcome-blocks.json +sequenzy templates update tmpl_123 --subject "Updated" --label edm --html-file ./welcome-v2.html +sequenzy templates update tmpl_123 --blocks-file ./welcome-v2-blocks.json +sequenzy templates delete tmpl_123 +``` + +Behavior: + +- `templates list`: `GET /api/v1/templates`, optionally with `?label=...` +- `templates get`: `GET /api/v1/templates/:id` +- `templates create`: `POST /api/v1/templates` +- `templates update`: `PUT /api/v1/templates/:id` +- `templates delete`: `DELETE /api/v1/templates/:id` + +Caveats: + +- list accepts `--label ` to filter by template label name +- create requires `name`, `subject`, and either `html` or `blocks`; it can also assign labels with `--label ` +- update accepts `name`, `subject`, `html`, `blocks`, and replacement labels with `--label ` +- `--blocks-json` and `--blocks-file` pass Sequenzy block arrays through directly +- conditional email content is only available through block JSON, using a block-level `condition` object +- raw HTML is still stored as a single text block by the current API path +- deletion can fail if the template is still referenced by a campaign or sequence + +## Campaigns + +```bash +sequenzy campaigns list +sequenzy campaigns list --status draft --label edm --company comp_123 +sequenzy campaigns get camp_123 +sequenzy campaigns create "April Launch" --prompt "Announce our new dashboard" +sequenzy campaigns create "April Launch" --subject "We shipped" --label edm --html-file ./campaign.html +sequenzy campaigns create "April Launch" --subject "We shipped" --blocks-file ./campaign-blocks.json +sequenzy campaigns update camp_123 --subject "Updated subject" --label edm +sequenzy campaigns update camp_123 --blocks-file ./campaign-v2-blocks.json +sequenzy campaigns update camp_123 --reply-to support@example.com +sequenzy campaigns update camp_123 --reply-profile reply_123 +sequenzy campaigns schedule camp_123 --at "2026-06-01T14:00:00Z" +sequenzy campaigns schedule camp_123 --at "2026-06-01T14:00:00Z" --target-lists-json '{"type":"all"}' +sequenzy campaigns test camp_123 --to you@example.com +``` + +Behavior: + +- `campaigns list`: `GET /api/v1/campaigns`, optionally with `?status=...` and `?label=...` +- `campaigns get`: `GET /api/v1/campaigns/:id` +- `campaigns create`: `POST /api/v1/campaigns` +- `campaigns update`: `PUT /api/v1/campaigns/:id` +- `campaigns schedule`: `POST /api/v1/campaigns/:id/schedule` +- `campaigns test`: `POST /api/v1/campaigns/:id/test` +- dashboard-aware responses include `url`, campaign review `previewUrl`, and `appUrls` when the company can be resolved + +Caveats: + +- list accepts `--status` and `--label ` filters +- create supports `name`, optional `subject` when `--prompt` is used, `html`, `blocks`, `--prompt`, `--style`, `--tone`, and labels with `--label ` +- update supports `name`, `subject`, `html`, `blocks`, replacement labels with `--label `, `--reply-to`, and `--reply-profile` +- schedule requires `--at ` with a future ISO timestamp and a verified sending domain +- schedule can pass targeting with `--target-lists-json` or `--target-lists-file`; omit it to reuse saved targeting or default to all active subscribers +- `--spread-over-hours` accepts integers from 1 to 72 and takes precedence over send-time optimization +- `--prompt` generates draft campaign content through `POST /api/v1/generate/email`; do not combine it with HTML or block flags +- `--blocks-json` and `--blocks-file` pass Sequenzy block arrays through directly +- conditional email content is only available through block JSON, using block-level `condition` rules +- `--reply-to` resolves an existing reply profile by email and `--reply-profile` sets it directly by ID +- `--reply-to` and `--reply-profile` are mutually exclusive +- `campaigns get` now includes saved reply-to details when the campaign has a reply profile +- only draft campaigns can be updated through this API path +- there is no CLI command for immediate send, pausing, or cancelling campaigns +- in the current backend checkout, `campaigns test` returns a success message path rather than a confirmed email send + +MCP parity: + +- `list_templates` and `list_campaigns` accept `label` +- `create_template`, `update_template`, `create_campaign`, and `update_campaign` accept `labels` +- `update_campaign` accepts `name`, `subject`, `html`, `blocks`, `labels`, `replyTo`, and `replyProfileId` +- `schedule_campaign` accepts `campaignId`, `scheduledAt`, optional `targetLists`, `sendTimeOptimization`, and `spreadOverHours` +- `replyTo` and `replyProfileId` are mutually exclusive +- MCP rejects calls that omit all update fields before hitting the API +- MCP rejects unsupported extra update fields before hitting the API + +## Sequences + +```bash +sequenzy sequences list +sequenzy sequences get seq_123 +sequenzy sequences create onboarding --trigger event_received --event-name signup.completed --goal "Guide new users to activation" --email-count 4 +sequenzy sequences create onboarding --trigger contact_added --list-id list_123 --steps-file ./steps.json +sequenzy sequences create winback --trigger tag_added --tag-name cancelled --steps-file ./discount-steps.json +sequenzy sequences update seq_123 --steps-file ./sequence-updates.json +sequenzy sequences update seq_123 --branch-file ./branch.json +sequenzy sequences enable seq_123 +sequenzy sequences disable seq_123 +sequenzy sequences delete seq_123 +sequenzy sequences cancel-enrollments seq_123 --subscriber-id sub_123 --reason "Converted" +sequenzy sequences cancel-enrollments seq_123 --field-path order.id --field-values ord_123,ord_456 +sequenzy sequences cancel-enrollments seq_123 --field-values price_123 --apply +``` + +Behavior: + +- `sequences list`: `GET /api/v1/sequences` +- `sequences get`: `GET /api/v1/sequences/:id` +- `sequences create`: `POST /api/v1/sequences` +- `sequences update`: `PUT /api/v1/sequences/:id` +- `sequences enable`: `POST /api/v1/sequences/:id/enable` +- `sequences disable`: `POST /api/v1/sequences/:id/disable` +- `sequences delete`: `DELETE /api/v1/sequences/:id` +- `sequences cancel-enrollments`: `POST /api/v1/sequences/:id/enrollments/cancel` +- dashboard-aware responses include `url` on sequence records and `appUrls` on the top-level JSON when the company can be resolved + +Caveats: + +- CLI sequence creation supports either AI `--goal` mode or explicit `--steps-json` / `--steps-file` mode +- explicit create steps can include `{ "type": "create_discount" }`; emails after that action can reference `{{discount.code}}`, `{{discount.percentOff}}`, and related `discount.*` merge tags +- discount action sequences require a connected Stripe integration before activation +- `--email-count` is only meaningful with `--goal` +- `--email-count` accepts 1 to 10 generated emails +- trigger-specific options depend on `--trigger` +- updates accept either step payloads or email payloads via `--steps-*` or `--emails-*` +- branch insertion uses `--branch-json` or `--branch-file` with condition types `has_tag`, `in_list`, `in_segment`, `event_received`, `link_clicked`, and `field_*` +- branch condition fields are `tagId`/`tagName`, `listId`, `segmentId`/`segmentName`, `eventName`, `linkUrl`, `activityScope`, or `fieldName`/`fieldValue`; omit `linkUrl` to match any clicked link +- for `event_received` and `link_clicked`, set `activityScope` to `this_sequence`, `previous_email`, or `ever`; omitting it checks the contact's full history +- `cancel-enrollments` requires a sequence ID and exactly one target: `--subscriber-id` or `--field-values` +- `--field-values` matches active/waiting enrollments by the stored entry event property at `--field-path`, or the sequence's configured `enrollmentFieldPath` when `--field-path` is omitted +- CLI cancellation is a dry run unless `--apply` is passed; use dry runs for field-value/bulk checks before mutating enrollments +- MCP uses `cancel_sequence_enrollments` with the same target rule; set `dryRun: false` to apply field-value cancellation + +## AI Generation + +```bash +sequenzy generate email "Welcome a new user to our analytics product" +sequenzy generate email "Product launch announcement" --style branded --tone friendly +sequenzy generate sequence "Onboard a new workspace admin" --count 4 --days 14 +sequenzy generate subjects "April product launch" --count 8 +``` + +Behavior: + +- `generate email`: `POST /api/v1/generate/email` +- `generate sequence`: `POST /api/v1/generate/sequence` +- `generate subjects`: `POST /api/v1/generate/subjects` +- `--json` returns the raw API response for agent/tool parsing + +Caveats: + +- generated content is draft content and should be reviewed before sending +- `generate sequence --count` accepts 1 to 10 emails +- `generate email` supports optional `--style` and `--tone` + +## API Keys + +```bash +sequenzy api-keys create +sequenzy api-keys create --name "CI deploy key" --company comp_123 +``` + +Behavior: + +- sends `POST /api/v1/api-keys` +- body shape is `{ name }` + +Caveat: + +- the plain API key is returned only at creation time; save it immediately + +## Websites + +```bash +sequenzy websites list --company comp_123 +sequenzy websites add example.com --company comp_123 +sequenzy websites check example.com --company comp_123 +sequenzy websites guide --framework nextjs --use-case transactional +``` + +Behavior: + +- `websites list`: `GET /api/v1/websites` +- `websites add`: `POST /api/v1/websites` +- `websites check`: `GET /api/v1/websites/:domain` +- `websites guide`: `POST /api/v1/integration-guide` + +## Commands To Treat As Unsupported + +Treat these requested workflows as unsupported in the CLI even though related nouns exist: + +- campaign immediate send, pause, cancel, or resume flows +- tag creation, update, or deletion +- list update or deletion + +## Operational Caveats + +- prefer `SEQUENZY_API_KEY` for automation instead of interactive login +- use `--json` when another tool or agent needs structured output; dashboard-aware commands add `url`/`appUrls` fields when possible +- when the user asks for a workflow outside the current CLI surface, say so directly and choose between dashboard or direct API use instead of inventing commands diff --git a/skills/sequenzy-email-marketing/references/use-cases.md b/skills/sequenzy-email-marketing/references/use-cases.md new file mode 100644 index 0000000..70eda85 --- /dev/null +++ b/skills/sequenzy-email-marketing/references/use-cases.md @@ -0,0 +1,492 @@ +# Use Cases + +## Pick The Right Flow + +### "Log into Sequenzy on this machine" + +Use: + +```bash +sequenzy login +``` + +Then verify: + +```bash +sequenzy whoami +``` + +Prefer `SEQUENZY_API_KEY` instead when the task is fully non-interactive or running in CI. + +## "Check whether I am authenticated" + +Use: + +```bash +sequenzy whoami +``` + +Interpretation: + +- success means a local API key is available +- failure means the agent should ask for login or a `SEQUENZY_API_KEY` + +Remember that this is local-state validation, not a fresh server-side account lookup. + +## "Show me account or company info" + +Use: + +```bash +sequenzy account +sequenzy companies list +sequenzy companies get comp_123 +sequenzy urls --company comp_123 +``` + +Choose: + +- `account` for user ID, current company, and accessible companies +- `companies list` for a compact list with localization info +- `companies get` when the user already has a company ID +- `urls` when the user needs a dashboard/settings link + +## "Open, review, or edit something I just created" + +Prefer the `url` or `appUrls` fields returned by recent CLI/MCP calls. If you need to generate links from IDs: + +```bash +sequenzy urls --company comp_123 --sequence seq_123 +sequenzy urls --company comp_123 --campaign camp_123 +sequenzy urls --company comp_123 --settings-tab integrations +``` + +MCP equivalent: call `get_app_urls` with: + +```json +{ + "companyId": "comp_123", + "sequenceId": "seq_123", + "settingsTab": "integrations" +} +``` + +URL patterns: + +- sequence editor: `/dashboard/company/{companyId}/sequences/{sequenceId}` +- campaign editor: `/dashboard/company/{companyId}/campaign/{campaignId}` +- template/email editor: `/dashboard/company/{companyId}/emails/{emailId}` +- settings: `/dashboard/company/{companyId}/settings` +- settings tab: `/dashboard/company/{companyId}/settings?tab={tab}` + +After generating a sequence or campaign, give the user the relevant review/edit URL instead of only returning the ID. + +## "Show me delivery performance" + +Use: + +```bash +sequenzy stats +sequenzy stats --period 30d +sequenzy stats --campaign camp_123 +sequenzy stats --sequence seq_123 +``` + +Choose: + +- plain `stats` for account-level overview +- `--campaign` when the user gives a campaign ID +- `--sequence` when the user gives a sequence ID + +Ask for the missing ID instead of guessing. + +## "Add or update a subscriber" + +What works today: + +```bash +sequenzy subscribers add user@example.com --tag premium --attr name=John +sequenzy subscribers add user@example.com --tag premium --tag beta --company comp_123 +sequenzy subscribers get user@example.com +sequenzy subscribers list --list "Master List" --json +``` + +Guidance: + +- use `add` for single-recipient creation or upsert +- use repeated `--attr key=value` pairs for metadata +- repeated `--tag` values are supported +- use `--company` when the API key can access multiple companies +- use `subscribers get` when you need the full profile, list memberships, sequence enrollments, email stats, or recent activity +- use `subscribers list --list --json` to export subscribers from one list; omit `--limit` to fetch every page + +What does not work well today: + +- advanced subscriber workflows across many records + +For bulk list population, do not loop over `subscribers add`. Use: + +```bash +sequenzy lists add-subscribers list_123 --emails-file ./batch-001.csv +sequenzy lists import list_123 --emails-file ./batch-001.csv +``` + +Guidance: + +- `lists import` is an alias for `lists add-subscribers` +- accepted input formats are repeated `--email`, `--emails-json`, or `--emails-file` +- files may be newline-separated, CSV with an email column, a JSON email array, or a JSON object with `emails` or `subscribers` +- CSV headers named `email`, `e-mail`, `email address`, or `mail` are detected; otherwise the first column is used +- the CLI splits files into API-safe batches of up to 500 emails +- use this path instead of one API call per subscriber + +## "Remove a subscriber" + +Use: + +```bash +sequenzy subscribers list --tag vip +sequenzy subscribers get user@example.com +sequenzy subscribers remove user@example.com +``` + +Use `--hard` only when the task explicitly requires permanent deletion: + +```bash +sequenzy subscribers remove user@example.com --hard +``` + +Notes: + +- plain `remove` performs a full unsubscribe workflow rather than a hard delete +- use `--company` when operating with a personal API key across multiple companies + +## "Send one transactional email" + +Template flow: + +```bash +sequenzy send user@example.com --template tmpl_123 --var name=John +``` + +Raw HTML flow: + +```bash +sequenzy send user@example.com --subject "Status update" --html-file ./email.html --var orderId=123 +``` + +Checklist: + +1. Confirm recipient email. +2. Confirm template ID or HTML source. +3. Confirm subject when sending raw HTML. +4. Confirm merge variables as `key=value`. + +This command is for one-off transactional send behavior, not bulk campaign sends. + +## "Create a list, tag view, or saved segment" + +What works today: + +```bash +sequenzy lists create Newsletter --description "Public newsletter list" +sequenzy tags +sequenzy segments list +sequenzy segments count seg_123 +sequenzy segments create --name "Bought Pro" --stripe-product prod_pro +sequenzy segments create --name "VIP or Churn Risk" --match any --filter-json '[{"field":"tag","operator":"contains","value":"vip"},{"field":"emailOpened","operator":"is_not","value":"30d"}]' +sequenzy segments create --name "Active non-paying" --filter-json '{"kind":"group","id":"root","joinOperator":"and","children":[{"kind":"filter","id":"f1","field":"attribute","operator":"gte","value":"last_login_days_ago:0"},{"kind":"group","id":"g1","joinOperator":"or","children":[{"kind":"filter","id":"f2","field":"attribute","operator":"is_empty","value":"plan_end"},{"kind":"filter","id":"f3","field":"attribute","operator":"lt","value":"plan_end:2026-04-21"}]}]}' +``` + +For Stripe purchase thresholds: + +```bash +sequenzy segments create --name "3+ Pro Payments" --stripe-product prod_pro --purchase-operator at-least --payments 3 +``` + +Guidance: + +- use `tags` for inspection only; there are no CLI tag mutations +- use Stripe product IDs, not product names +- use `--filter-json` when the user needs a non-Stripe, mixed, nested, custom event, or saved-segment payload +- use `--match any` when the segment should match any top-level filter instead of all filters +- `segments count` is the quickest way to preview impact before using a segment in a campaign + +For MCP-driven workflows, `create_segment` supports the same legacy filter array with `filterJoinOperator: "or"` for match-any segments: + +```json +{ + "filterJoinOperator": "or", + "filters": [ + { + "id": "filter-1", + "field": "stripeProduct", + "operator": "at_least", + "value": "prod_pro:3" + } + ] +} +``` + +For nested AND/OR logic, send a `root` instead of `filters`. Event filters use `field: "event"` and values like `saas.purchase:30d` or `saas.purchase:5:30d`; segment-of-segment filters use `field: "segment"` with the referenced segment id as `value`. + +```json +{ + "root": { + "kind": "group", + "id": "root", + "joinOperator": "and", + "children": [ + { + "kind": "filter", + "id": "filter-1", + "field": "event", + "operator": "at_least", + "value": "saas.purchase:2:30d" + }, + { + "kind": "filter", + "id": "filter-2", + "field": "segment", + "operator": "is_not", + "value": "seg_churned" + } + ] + } +} +``` + +## "Create or manage a template" + +What works today: + +```bash +sequenzy templates list +sequenzy templates list --label edm +sequenzy templates get tmpl_123 +sequenzy templates create welcome --subject "Welcome" --label edm --html-file ./welcome.html +sequenzy templates create welcome --subject "Welcome" --blocks-file ./welcome-blocks.json +sequenzy templates update tmpl_123 --subject "Updated" --label edm --html-file ./welcome-v2.html +sequenzy templates update tmpl_123 --blocks-file ./welcome-v2-blocks.json +``` + +Guidance: + +- use block JSON when the user needs conditional content or an exact editor-compatible structure +- use HTML input for simpler one-off content; this API path stores raw HTML as a single text block +- use `--label` on `list` to filter by label, and on `create` or `update` to assign replacement labels +- a conditional block uses a block-level `condition` object with merge-tag variable names and no `{{ }}` braces +- use `get` before `update` or `delete` when the user is uncertain about the target ID +- warn that delete can fail when the template is still referenced by a campaign or sequence + +## "Create or manage a campaign" + +What works today: + +```bash +sequenzy campaigns list --status draft --label edm +sequenzy campaigns get camp_123 +sequenzy campaigns create "April Launch" --prompt "Announce our new dashboard" +sequenzy campaigns create "April Launch" --subject "We shipped" --label edm --html-file ./campaign.html +sequenzy campaigns create "April Launch" --subject "We shipped" --blocks-file ./campaign-blocks.json +sequenzy campaigns update camp_123 --subject "Updated subject" --label edm +sequenzy campaigns update camp_123 --blocks-file ./campaign-v2-blocks.json +sequenzy campaigns update camp_123 --reply-to support@example.com +sequenzy campaigns update camp_123 --reply-profile reply_123 +sequenzy campaigns schedule camp_123 --at "2026-06-01T14:00:00Z" +sequenzy campaigns test camp_123 --to you@example.com +``` + +Guidance: + +- the CLI handles draft creation, draft updates, inspection, scheduling, and test requests +- create, get, update, schedule, list, and test outputs include dashboard URLs when the company can be resolved; campaign outputs include a review `previewUrl` +- use `--prompt` for AI-generated draft content; do not combine it with HTML or block flags +- use `--label` on `list` to filter by campaign label, and on `create` or `update` to assign replacement labels +- use block JSON when the user needs conditional content or an exact editor-compatible structure +- use `--reply-to` when the user knows the reply profile email and it already exists for the company +- use `--reply-profile` when the user already has the reply profile ID +- do not pass `--reply-to` and `--reply-profile` together +- use `campaigns get` after an update when you want to confirm the saved reply-to details +- use `campaigns schedule --at ` when the user asks to schedule a campaign; it requires a verified sending domain +- use `--target-lists-json` or `--target-lists-file` only when the user explicitly needs new targeting at schedule time +- there is no CLI command for immediately sending, pausing, or cancelling a campaign +- in the current backend checkout, `campaigns test` returns a success message path rather than confirmed delivery + +For MCP-driven campaign updates, `update_campaign` supports labels and the same reply-to behavior: + +```json +{ + "campaignId": "camp_123", + "labels": ["edm"], + "replyTo": "support@example.com" +} +``` + +For MCP-driven scheduling, call `schedule_campaign`: + +```json +{ + "campaignId": "camp_123", + "scheduledAt": "2026-06-01T14:00:00Z", + "targetLists": { "type": "all" } +} +``` + +Use `replyProfileId` instead when the caller already has the reply profile ID, and never send both fields together. + +Preferred fallback for unsupported campaign workflows: + +- use the dashboard +- use direct API calls only if the task explicitly allows it and the relevant API is available + +## "Create or manage a sequence" + +What works today: + +```bash +sequenzy sequences list +sequenzy sequences get seq_123 +sequenzy sequences create onboarding --trigger event_received --event-name signup.completed --goal "Guide new users to activation" --email-count 4 +sequenzy sequences create onboarding --trigger contact_added --list-id list_123 --steps-file ./steps.json +sequenzy sequences create winback --trigger tag_added --tag-name cancelled --steps-file ./discount-steps.json +sequenzy sequences update seq_123 --steps-file ./sequence-updates.json +sequenzy sequences enable seq_123 +sequenzy sequences disable seq_123 +sequenzy sequences cancel-enrollments seq_123 --subscriber-id sub_123 +sequenzy sequences cancel-enrollments seq_123 --field-path order.id --field-values ord_123,ord_456 +sequenzy sequences cancel-enrollments seq_123 --field-values price_123 --apply +``` + +Minimal `steps.json` shape: + +```json +[ + { + "subject": "Welcome to Acme", + "html": "

Hi there

", + "delay": { "days": 0 } + }, + { + "subject": "Day 3 follow-up", + "html": "

Here is the next step

", + "delay": { "days": 3 } + } +] +``` + +Discount step shape: + +```json +[ + { + "type": "create_discount", + "label": "Create win-back discount", + "discountType": "percent", + "percentOff": 20, + "duration": "once", + "appliesToAllPlans": true, + "maxRedemptions": 1, + "codePrefix": "WINBACK" + }, + { + "subject": "Come back with {{discount.code}}", + "html": "

Use {{discount.code}} for {{discount.percentOff}}% off.

", + "delay": { "days": 1 } + } +] +``` + +Branch insertion shape for "clicked invite, otherwise remind": + +```json +{ + "afterNodeId": "node_email", + "branches": [ + { + "conditionType": "link_clicked", + "linkUrl": "project-invites", + "activityScope": "previous_email", + "steps": [ + { + "subject": "Project invite accepted", + "html": "

Here is your next project step.

" + } + ] + } + ], + "elseSteps": [ + { + "subject": "Reminder: accept your invite", + "html": "

Please accept your project invite.

" + } + ] +} +``` + +Guidance: + +- CLI sequence creation supports either AI `--goal` mode or explicit step files +- create, get, update, and list outputs include dashboard URLs when the company can be resolved +- choose the correct trigger options for `--trigger` +- use `--goal` when you want AI-generated drafts, or `--steps-file` when you already know the exact step content +- discount action steps require Stripe to be connected before activation +- use either `--steps-file` or `--emails-file` for update +- use `--branch-file` for if/else insertion; branch conditions support tag, list, segment, event, clicked-link, and field checks +- for `link_clicked`, set `linkUrl` to part of the target URL or omit it to match any tracked click +- for `event_received` and `link_clicked`, set `activityScope` to `this_sequence`, `previous_email`, or `ever` +- enable/disable are real CLI actions + +## "Stop people in a sequence" + +Use: + +```bash +sequenzy sequences cancel-enrollments seq_123 --subscriber-id sub_123 --reason "Converted" +sequenzy sequences cancel-enrollments seq_123 --field-path order.id --field-values ord_123,ord_456 +sequenzy sequences cancel-enrollments seq_123 --field-values price_123 --apply +``` + +Guidance: + +- require the sequence ID; never attempt cross-sequence cancellation from only an event or field value +- use `--subscriber-id` when the caller knows the exact subscriber enrollment to stop +- use `--field-values` when the caller wants to stop all active/waiting enrollments whose stored entry event property matches specific IDs +- include `--field-path` unless the sequence already has the correct `enrollmentFieldPath` +- omit `--apply` for a dry run; pass `--apply` only after reviewing the matched count +- MCP equivalent is `cancel_sequence_enrollments` with exactly one of `subscriberId` or `fieldValues`; set `dryRun: false` to apply a field-value cancellation + +## "Create an API key or inspect website/domain setup" + +Use: + +```bash +sequenzy api-keys create --name "CI deploy key" --company comp_123 +sequenzy websites list --company comp_123 +sequenzy websites add example.com --company comp_123 +sequenzy websites check example.com --company comp_123 +sequenzy websites guide --framework nextjs --use-case transactional +``` + +Guidance: + +- save API keys immediately; the raw key is only returned on creation +- use `websites check` when the user needs DNS verification details +- use `websites guide` for integration code snippets rather than inventing framework examples + +## "Generate email content with AI" + +Use the CLI when the user wants draft copy or structured generated output: + +```bash +sequenzy generate email "Welcome email for new SaaS trial users" +sequenzy generate sequence "Onboarding for SaaS trial users" --count 4 --days 14 +sequenzy generate subjects "Black Friday sale" --count 5 +``` + +Guidance: + +- use `--json` when another agent or tool should parse the result +- generated content is draft content and should be reviewed before sending +- sequence generation accepts at most 10 emails +- use `sequenzy campaigns create "Name" --prompt "..."` when the user wants to create a draft campaign from generated content in one step