Repository navigation
Conversation
One page for sending email from code: the template format, posthog-node template files and the content hash, upload by key, the send route, templates managed by code, adoption, and one anchored section per error code, so every docs_url the API returns opens its fix. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Say which errors carry why, fix, and docs_url, and which routes the beta flag gates. Split the paused and deleted workflow cases, name the 100-hash window, the default sender button, the personal API key fallback, two more permission messages, when templateFile() throws, and how the rate limits count. Correct the example upload response hash. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Scope the automatic upload guarantee to the last 100 publishes, point a keyless template with a deleted workflow at the make_transactional route, and split the project access fix by key type. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
… comes from Add the section on changing a code-managed template: the agent prompt, Run with PostHog Code and its request_change route, what PostHog AI and the Slack bot do, and Copy HTML file. Add how posthog-node detects the repository, path and ref, and anchors for the seven request-change error codes. Update the immutable fix to the server's new text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Scope the source detection order to the repository and the ref, and name the absolute path fallback. Tell an agent that gets the sandbox refusal where the template link is. Name the file after the key on Copy HTML file, add the missing disabled reason, the starter advice, the upload by key after a merge, and the change request route in the beta callout and the key requirements. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Quote the server's new refusal texts: the fixes now point at change_prompt_context, and the sandbox fix names the page steps. Add hog_flow:read next to task:write, the workflow editor access and length reasons on the button, change_prompt_variables, and the new immutable fix with its PostHog Code step. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Name the first missing scope as the server does, add the editor access denial a change request gets, scope the permission fix per route, and say what PostHog puts in front of an instruction without the starter. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…editor denial Co-Authored-By: Claude Opus 5.5 <[email protected]>
3 of 5 tasks
|
Vale prose linter → found 0 errors, 14 warnings, 1 suggestions in your markdown Full report → Copy the linter results into an LLM to batch-fix issues. Linter being weird? Update the rules!
|
| Line | Severity | Message | Rule |
|---|---|---|---|
| 140:91 | warning | 'Bundlers' is a possible misspelling. | PostHogBase.Spelling |
| 148:8 | warning | 'bundler' is a possible misspelling. | PostHogBase.Spelling |
| 261:60 | warning | 'preheader' is a possible misspelling. | PostHogBase.Spelling |
| 266:42 | warning | 'preheader' is a possible misspelling. | PostHogBase.Spelling |
| 269:131 | warning | 'preheader' is a possible misspelling. | PostHogBase.Spelling |
| 293:55 | warning | 'preheader' is a possible misspelling. | PostHogBase.Spelling |
| 380:124 | warning | 'preheader' is a possible misspelling. | PostHogBase.Spelling |
| 390:4 | warning | 'upload's' is a possible misspelling. | PostHogBase.Spelling |
| 407:208 | warning | 'worktree's' is a possible misspelling. | PostHogBase.Spelling |
| 408:131 | suggestion | Address the reader directly. Use 'you' instead of 'The user'. | PostHogDocs.DirectAddress |
| 528:190 | warning | Use 'ID' instead of 'id'. | Vale.Terms |
| 536:63 | warning | Use 'PostHog' instead of 'posthog'. | Vale.Terms |
| 563:30 | warning | Capitalize 'Workflows' for PostHog's product. Use 'workflows' for the general industry concept. | PostHogBase.ProductNames |
| 564:30 | warning | Capitalize 'Workflows' for PostHog's product. Use 'workflows' for the general industry concept. | PostHogBase.ProductNames |
| 647:97 | warning | Use 'PostHog' instead of 'posthog'. | Vale.Terms |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moved here from PostHog#21306, closed on 2026-10-25 so this fork stack is the only copy. It opens upstream again after review.
Note
Restacked onto fork
masterat473432f3fwith no conflicts.git range-diffshows all nine commits unchanged (=), so the page is the same as on PostHog#21306 at2b0a7a224. The body below is the body of PostHog#21306.Changes
Engineers and coding agents get one page that teaches the whole transactional email API: write an HTML template, upload it by key, send it from code, change a code-managed template, and fix every error the API returns. Each error code has its own section, so every
docs_urlin an API error opens the fix./docs/workflows/transactional-email-api, marked beta, with a sidebar entry under Workflows › Transactional email › Send email from code.posthog-node, upload by key, the send route, the content hash, templates managed by code, adoption, and anchored error sections.6aa5dd523and3f9db72ad(Silthus/posthog#507):POST …/messaging_templates/:id/request_change/and the MCP toolworkflows-request-email-template-change), what PostHog AI and the Slack bot do (they hand you the template link), Copy HTML file, and when the change goes live: copying a prompt or a file, or starting a task, never changes live email.sourceoption ofuploadTemplate(), the GitHub Actions, GitLab CI, Vercel and Railway variables and their order, the git checkout fallback, and what happens when nothing is found.instruction_missing,template_not_managed_by_code,template_repository_missing,template_repository_unsupported,github_repository_not_connected,posthog_code_not_available,posthog_code_run_failed. Each quotes the server'sdetail,why, andfixverbatim.immutablefix now quotes the server's new text, which puts editing the file first.invalid_request,not_found,permission_denied, the beta note, and the key requirements name the change request route.c1380a99d,b805f1be6, and2b0a7a224: the page follows stack B at its reviewed head0c3c8b87b51(PostHog/posthog#119032).hog_flow:readnext totask:write, and editor access to Workflows.permission_deniednames the first missing scope and the editor access denial.template_repository_unsupported.change_prompt_contextdescribes", the sandbox fix names the page steps, and theimmutablefix adds a step for PostHog AI and the Slack bot.change_prompt_variables.Note
🔵 Merge risk: low · two-way door (merge-risk rubric)
spec/code-managed-templates(PostHog/posthog#118924) and PostHog/posthog-js#5312, for upload, send, and source detection;0c3c8b87b51(Run with PostHog Code, the change request route, the seven new codes). A later change to its refusal texts needs this page updated, and the anchor check catches it.Screenshots: changing a code-managed template
Local dev server (
GATSBY_MINIMAL=true pnpm start) at2b0a7a224. Example data only:example.com-style repositories and invented keys.posthog_code_not_available, opened by plain navigation: the four reasons with the server's new fixespermission_denied: the scope and editor access messagesdocs_urlfortemplate_repository_missing, opened by plain navigationScreenshots at 3f9db72, before the server sync
Screenshots at 3f9db72
Local dev server (
GATSBY_MINIMAL=true pnpm start) at3f9db72ad. Example data only:example.com-style repositories and invented keys.docs_urlfortemplate_repository_missing, opened by plain navigationEvidence
idand that its section quotes the server's strings.immutablecome from the server code: a Python AST pass overtemplate_change_requests.py,template_ownership.py, andmessage_templates.pyat0c3c8b87b51pulls every refusal'sdetail,why, andfix. f-strings give their fixed text around each placeholder, and conditional texts give both branches.3f9db72ad(the page before the server sync) against the strings at0c3c8b87b51:30/34.immutable,template_repository_unsupported,github_repository_not_connected, andposthog_code_not_availablemiss the server's new text.2b0a7a224:34/34. All 63 in-page#links resolve. A text probe confirmed the served page carries the final-read fixes.gatsby build, so the markdown twin wasn't generated locally. The changed text uses only markdown, tables, and code blocks.Anchor check output (green, 2b0a7a2)
Anchor check output (red, 3f9db72 against 0c3c8b87b51)
Evidence at 3f9db72, before the server sync
Evidence at 3f9db72
idand that its section quotes the server's strings. Extended for this change:template_change_requests.py,template_ownership.py, andmessage_templates.pyat60fb98f06a5onspec/template-request-changepulls every refusal'sdetail,why, andfix. f-strings give their fixed text around each placeholder.immutablefix, which the server replaced.c86c7a6a9(the page before this change):25/34. The seven new codes have no anchor, and theimmutableandinvalid_requestsections miss the server's new fix text.3f9db72ad:34/34, every section quoting its strings. All 59 in-page#links resolve.immutablesection, one sentence off the server's text, fails.gatsby build, so the markdown twin wasn't generated locally. The new sections use only markdown, tables, and code blocks.Anchor check output (green, 3f9db72)
Anchor check output (red, c86c7a6)
Where the facts come from
Server code on
spec/template-request-changeat0c3c8b87b51(PostHog/posthog#119032) andspec/template-agent-edit(0960e3de116, PostHog/posthog#118980), andposthog-nodeon PostHog/posthog-js#5312. Where the spec (Silthus/posthog#502) and the code differ, the page follows the code:posthog_code_not_available. They hand you the template link instead (decision)sourceuploadTemplate()takes it. The upload after a send uses detection onlyinvalid_requestfor aninstructionover 2,000 characters.posthog_code_not_availableis403with fourwhy/fixpairs, the rest400task:writeand read access to the templatehog_flow:readandtask:writefor tokens (hog_flow:writecovers the read), and editor access to WorkflowsReview
Opus 5.5 at high effort, read-only, as a fresh agent. Recorded with
fleet proof review-startandreview-finish.6aa5dd523: no high findings, 1 medium and 13 low, all held and fixed in3f9db72ad. The medium one: an agent that gets the sandbox refusal wasn't told where the template link is. Among the low ones: the detection order didn't hold forpath, the absolute path fallback, Copy HTML file must name the file after the key, the missing "Checking the GitHub connection" reason, and an app that sends by key needs an upload after the merge.3f9db72ad: all resolved, and the five new claims in the fix lines hold against the code. PASS.c1380a99d(the server sync), a fresh reviewer: all 38 quoted server strings match0c3c8b87b51. 3 low findings, all fixed inb805f1be6: the server names only the first missing scope, the permission fix advised a project secret API key for routes that refuse it, and the instruction prefix includeswhat this request asks for:.b805f1be6: those resolved. 2 new low findings in the fix lines, fixed in2b0a7a224: the per-route fix pointed at scopes some sections don't name, and the editor access denial applies to every write route, not only a change request.2b0a7a224: PASS.fleet proof gatepasses on this HEAD.Earlier scope: the page itself (Silthus/posthog#475, up to c86c7a6)
Screenshots
Local dev server (
GATSBY_MINIMAL=true pnpm start). Example data only:example.comaddresses, invented keys and hashes.docs_urlfortemplate_not_foundThe anchor shots open
/docs/workflows/transactional-email-api#template_not_foundby plain navigation. The browser scrolls to the section with no script.Sidebar (narrow windows hide the sidebar, so only wide):
Evidence
Red: before the page existed, the
docs_urlfrom a realtemplate_not_foundresponse (https://posthog.com/docs/workflows/transactional-email-api#template_not_found, opened on the local dev server) answered404, the Gatsby development 404 page. The anchor check found0/27codes.Red: the docs_url before the page
Green on
c86c7a6a9: after the page, the same URL answers200and lands on thetemplate_not_foundsection. The anchor check finds27/27codes, each with the server's message and fix text.Mutation: changing one quoted fix sentence on the page (
key_in_use) made the check fail with26/27.Anchor check: a scratch Playwright script, kept out of this PR. It opens the page and asserts that every catalog code has an element with that
id, and that its section quotes the API'sdetailandfixstrings verbatim. The strings come from the server code at7845707ba33onspec/code-managed-templates.Lint: Vale 3.13.1 with the repo config: no errors. Left: dictionary gaps (
bundler,preheader) and two verbatim API quotes (id,posthog-node). markdownlint-cli2 with the repo config: 0 errors. The pre-commit hook (Prettier, ESLint, markdownlint) passed.Console: the page adds no console errors. A
404resource error and SVGwidth="auto"warnings show on existing pages too, such as/docs/workflows/broadcasts.Gap: I didn't run a production
gatsby build, so the markdown twin wasn't generated locally. The page uses plain markdown, code blocks, tables, and oneCalloutBox, as the existing workflows pages do.Anchor check output (green)
Where the facts come from
The routes, fields, codes, and messages come from the server code on the integration branch
spec/code-managed-templates(tip7845707ba33) and the SDK in PostHog/posthog-js#5312. Where the spec's error catalog and the code differ, the page follows the code:immutable403, and the UI shows a read-only preview with Stop managing in codeauthentication_failed/permission_deniednot_authenticatedsender_unavailable,template_not_sendable,marketing_template, send codes)why,fix, ordocs_urlin the body. The page gives the fixinvalid_requestkeyandidhashwithid, andkeysent with other fields on adoptiontemplate_supersededposthog-nodeit is{ code, message }, withoutfixapi_errorandunexpected_errorresultcreated,updated,unchangedsupersededwithif_not_superseded(Silthus/posthog#499, landed on the integration branch)Review
Opus 5.5 at high effort, read-only, as a fresh agent. Recorded with
fleet proof review-startandreview-finish.26083a1c3: 10 findings, 2 medium and 8 low. All held and are fixed incedcc00a3. The two medium ones: the error envelope (only seven codes carrywhy,fix, anddocs_url), and the deleted-workflow case oftransactional_email_paused(an upload makes a new workflow with the default sender). The low ones: the beta flag gates only upload and send, the example response hash, the 100-hash window, how to set a default sender,marketing_templateon a code-managed template,templateFile()throws, the personal API key fallback and two permission messages, and how the rate limits count.cedcc00a3: all 10 resolved. It found 3 new low problems in the fix lines, all fixed in12c38f1fc.12c38f1fc: all 3 resolved. One new low finding: name the accessmake_transactionalneeds, and its 403 message. Fixed inc86c7a6a9.c86c7a6a9: PASS, no findings.fleet proof gatepasses on this HEAD.Decisions
/docs/workflows/transactional-email-api, with one anchored section per error code and warningerror.codefromposthog-nodehas a fixenableLocalEvaluation: false, becausesecretKeystarts flag polling, which needsfeature_flag:readcontents/and the navdetail,why, andfixas a list per code, andposthog_code_not_available's four reasons as a tableInvolvement: one decision answered by Michael; for this change one review round and four final reads (Opus 5.5, high); proof captured (red, green, screenshots). CodeRabbit not run on this repository.
Checklist
vercel.json(no page moved)🤖 Generated with Claude Code