CLI command
email newsletter
The newsletter: a draft of a blog surface's most-read posts of a window, with a product's announcements of it, sent to a CRM list only once a reviewer approves it.
Invocation#
echo-cli email newsletter draft --surface <slug> --days <n> --top <n> --list <list-id> --subject <text> [--product <id>] --by <name>
echo-cli email newsletter list
echo-cli email newsletter show --id <newsletter-id>
echo-cli email newsletter queue --id <newsletter-id> --by <name>
echo-cli email newsletter remove --id <newsletter-id>Inputs and output#
draft, queue and remove write the newsletter: id, surface_slug, product_id (or null), list_id, subject, body, period_start, period_end, posts (post_id, slug, title, url, sessions, most read first), status (draft, queued or sent), approval_request_id, created_by, created_at and sent_at. list writes every newsletter, newest first; show writes newsletter and deliveries, one per list member emailed: id, newsletter_id, email, error (null when sent) and attempted_at.
State effect#
Every verb calls Echo Web's authenticated /api/newsletters with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the /campaigns/newsletter screen and the Newsletter section of Echo Desktop's Contact frequency screen call the same operations, and echo-mcp reads them as echo_newsletters. draft reads the surface's posts published in the last --days days and ranks them by the distinct sessions whose web events opened the post's page (the surface's canonical host and /blog/<slug>) in that window, keeping the --top most read; with --product it adds that product's announcements published in the window. The body lists each post's title and link, then each announcement's title and text. queue puts the draft in the approval queue as send_newsletter; when a reviewer approves it (echo-cli approvals approve), every list member with an email is sent the newsletter once from ECHO_NEWSLETTER_FROM through Echo's Resend integration, ending with their preference link, unless their address is suppressed, withdrew its consent to the newsletter or is at the contact frequency cap; each member's delivery is stored with its error, or none when sent. A newsletter is sent only once. A newsletter whose approval was rejected stays queued until removed.
Refusals#
- A wrong invocation is refused before anything is sent: "email newsletter takes <every newsletter usage>; got <word>", "email newsletter <verb> does not take <flag>; it takes …", "<flag> needs a value", "email newsletter <verb> needs <flag>", "--days must be a whole number of days; got <value>" and "--top must be a whole number of posts; got <value>".
- Echo Web answers a bad request with "surface is required: …", "days must be a positive whole number: the window of days the posts were published and read in; got <value>", "top must be a positive whole number: how many of the most-read posts the newsletter carries; got <value>", "list_id is required: …", "subject is required: …" or "newsletter_id is required: …"; not found with "no blog surface is named <slug>; echo-cli blogs lists the surfaces posts belong to", "no CRM list has id <id>", "<slug> published no post since <instant>; a newsletter needs at least one" or "no newsletter has id <id>; echo-cli email newsletter list shows them"; and a conflict with "newsletter <id> is <status>, not a draft; only a draft is queued" or "newsletter <id> is <status>; only a draft or a newsletter whose approval was rejected or failed before sending is removed". An approved newsletter without ECHO_NEWSLETTER_FROM fails with "ECHO_NEWSLETTER_FROM is required" before anything is sent and stays queued, so it can be removed and drafted again. The command prints Echo Web's sentence and exits 1.