Skip to content

Spec the email send API and slice it into PRs #464

Closed

Description

@Silthus

Question

What exactly does slice 1 of the email send API build, and how does it split into implementation tickets?

Write the spec from the map's charting decisions, the architecture brief, and the sender-verification research: the endpoint, scope and flag; the CDP invocation through the hidden workflow; the agent-friendly error catalog; posthog-node emails.send; and the agent skill. Then slice it into implementation tickets and one ship ticket.

Activity

  1. self-assigned this
    on Oct 14, 2026
  2. Silthus commented on Oct 14, 2026

    @Silthus
    OwnerAuthor

    Runtime: T3 Code
    Thread: thread:project:f66f06fc-0bc1-4bfe-b00a-4aab7f54eb13:9328b4bd-7bf9-4057-8917-d0927e5c1d58
    Title: spec #464: Spec the email send API and slice it into PRs
    Cast: Opus 5.5, high. AFK stretch cap: 75 minutes, then park.
    Note: dispatched as its own T3 thread, like the prototype, so Michael answers the spec park there directly.

  3. Silthus commented on Oct 14, 2026

    @Silthus
    OwnerAuthor

    Parked: the spec and its implementation tickets are ready for review.

    Spec: Spec: email send API #467. It is closed on purpose so it stays off the frontier, like #229.

    Locked (from the map, #463 and #466)

    • POST /api/projects/@current/emails/, phs_ keys only, email_send:write, flag workflows-email-api (fails closed, 403 when off), email-sized throttles as settings, 24 h cache idempotency storing the Django-minted id.
    • One hidden api_sends workflow per team with the api_send trigger, kept single by a partial unique index; Django → CDP over a scoped service JWT, quota and pause checked in the new route.
    • 200 { id, url }, one error catalog (code, status, what/why/fix, attr, docs_url), posthog-node emails.send returns { data, error }, the /workflows/api-sends redirect route, and one agent skill that verifies a sender through the PostHog MCP before the first send and covers both flags.

    Implementation tickets (build order, native blocking edges)

    # Ticket Repo Blocked by
    #468 API sends origin and the one-flow-per-team index (migration PR) PostHog/posthog none
    #469 Django creates and owns the hidden API sends workflow PostHog/posthog #468
    #470 CDP api_sends route and the Django client PostHog/posthog (Django + nodejs/) #469
    #471 POST /emails behind the flag, with the error catalog PostHog/posthog #470
    #472 Idempotency keys and throttles PostHog/posthog #471
    #473 /workflows/api-sends redirect route PostHog/posthog (frontend) #469
    #474 posthog-node emails.send PostHog/posthog-js #472
    #475 Email API reference page with an anchor per error code PostHog/posthog.com #472, #474
    #476 Agent skill: send transactional email PostHog/context-mill (+ one-line name reservation in PostHog/posthog) #474, #475, #466

    The instrument-* skills are authored in PostHog/context-mill (context/skills/omnibus/), built into its release, and served through the PostHog MCP; PostHog/posthog keeps a list of their names so no product skill can shadow them.

    Merge-risk danger areas

    Pending: spec decisions (recommendation in bold)

    1. Seams and slicing. Keep the six seams in the spec and the nine tickets as cut / merge Email API: Django creates and owns the hidden API sends workflow #469 into Email API: CDP api_sends route and the Django client that calls it #470 (fewer PRs, one larger session) / split Email API: POST /emails behind workflows-email-api, with the error catalog #471 further (scope change on its own).
    2. Skill home and name. PostHog/context-mill, send-transactional-email / context-mill as instrument-email to match its siblings / a product skill in PostHog/posthog products/workflows/skills/.
    3. Docs page in this map. Yes, a plain reference page with error anchors (Docs: transactional email API page for code-managed templates, an anchor per error code #475); agent prompt and llms.txt stay deferred / no page yet, and docs_url points at the GitHub-hosted catalog until docs land.
    4. requestJson from posthog-js#5173. posthog-node: emails.send from a key or an HTML file, synced by content hash, returning { data, error } #474 carries the same helper; whichever PR merges second drops its copy / stack posthog-node: emails.send from a key or an HTML file, synced by content hash, returning { data, error } #474 on Filter for people with session recordings on persons modal PostHog/posthog#5173 / split the helper into its own small core PR first.
    5. Idempotency key in the SDK. Second options argument, like Resend / a field in the payload.
    6. SDK retries. Retry a send only when it carries an idempotency key / always retry through fetchWithRetry defaults.
    7. cc plus bcc limit. The provider's per-message recipient limit minus the one to, as a setting / a smaller fixed limit for the beta.
    8. Skill fallback when workflows-email-domain-agent-setup is off. Tell the person to verify in the PostHog UI and wait / stop and ask the person to enable the flag.

    Also noted in the spec: when #350 moves upstream, its transactional recipe should point at emails.send and the new skill instead of a hand-built workflow. #349 stays independent.

  4. Silthus commented on Oct 14, 2026

    @Silthus
    OwnerAuthor
    No description provided.
  5. Silthus commented on Oct 14, 2026

    @Silthus
    OwnerAuthor

    Resolved: Michael accepted the spec and the ticket breakdown on 2026-10-14.

    Spec: Spec: email send API #467 (closed on purpose, the reference document for the tickets below).

    Implementation tickets in build order

    # Ticket Repo Blocked by
    #468 API sends origin and the one-flow-per-team index (migration PR) PostHog/posthog none
    #469 Django creates and owns the hidden API sends workflow PostHog/posthog #468
    #470 CDP api_sends route and the Django client PostHog/posthog (Django + nodejs/) #469
    #471 POST /emails behind the flag, with the error catalog PostHog/posthog #470
    #472 Idempotency keys and throttles PostHog/posthog #471
    #473 /workflows/api-sends redirect route PostHog/posthog (frontend) #469
    #474 posthog-node emails.send PostHog/posthog-js #472
    #475 Email API reference page with an anchor per error code PostHog/posthog.com #472, #474
    #476 Agent skill: send transactional email PostHog/context-mill (+ name reservation in PostHog/posthog) #474, #475, #466

    Decisions (all as recommended)

    1. Six test seams and nine tickets, as cut.
    2. The skill lives in PostHog/context-mill as send-transactional-email.
    3. A plain docs reference page with error anchors is in this map (Docs: transactional email API page for code-managed templates, an anchor per error code #475); the agent prompt and the llms.txt line stay deferred.
    4. posthog-node: emails.send from a key or an HTML file, synced by content hash, returning { data, error } #474 carries the requestJson helper from posthog-js#5173; whichever PR merges second drops its copy.
    5. The SDK takes the idempotency key as a second options argument.
    6. The SDK retries a send only when it carries an idempotency key.
    7. The cc plus bcc limit is the provider's per-message recipient limit minus the one to, as a setting.
    8. With workflows-email-domain-agent-setup off, the skill sends the person to the PostHog UI to verify, then waits.

    Merge-risk danger areas: auth and API scopes (#471), service-to-service auth and secrets (#470), the migration (#468), real sends and billing quota (#470), concurrency (#469, #472), public API contracts (#471, #474).

    Outside the code, before the flag turns on: the new JWT signing secrets setting needs a value in every environment, and the workflows-email-api flag needs to exist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions