๐จ WDYBTW: Check for hardcoded /users/1/ calls, now rejected
What did you break this week, week of 2026-10-01
Useful? Time will tell. Feedback welcome. Don't blame me or the AI if something breaks and we didn't tell you, or something didn't break and we told you. It's an experiment. ๐
The most consequential change this week is merged: Ghost's API input validator no longer accepts the legacy numeric ID 1, so calls like GET /ghost/api/admin/users/1/ now fail with a validation error instead of resolving to the owner; use the real ObjectID or me instead. Several other merged changes also deserve a look. Stripe Checkout sessions created by Ghost no longer carry metadata.ghostTierId, and sending comped: false on a member edit now really cancels their Complimentary subscription. Newsletter retries can now return 400 errors with the new codes EMAIL_RETRY_UNKNOWN_OUTCOME and BULK_EMAIL_RETRY_NOT_FAILED. The authReact field is gone from the /site/ endpoints. The rest is mostly additive or behind private labs flags, including new automations, app installations and checkout design endpoints, while four open PRs touch internal date handling and app manifests.
Contents
Cathy says...
The thing I'm most excited about this week is obvious movement on support for apps. 3rd party integrations as panels in the admin api? OMG, yes please! It's not here yet, but it's been fun GitHub gazing to see what's coming. I'm watching closely, because I would love to be able to move the toolbox into Ghost admin. ๐
Member fields and Stripe branding options are also going to be nice to have, once they ship. ๐คฉ
Right, ok, back to the AI...
Merged
Permissions & endpoint behaviour
Removed legacy numeric API IDs ยท Merged 2026-10-02 ยท ErisDS
Impact: high ยท Confidence: high ยท ๐จ Breaking
The shared API input validator no longer accepts the legacy numeric ID `1` for `id` params. Requests such as /users/1/ that used to pass validation now fail with a validation error. ObjectIDs and `me` still work.
- What changed: GLOBAL_VALIDATORS.id regex in api-framework changed from /^(?:[a-f\d]{24}|1|me)$/i to /^(?:[a-f\d]{24}|me)$/i. Applies to any Admin/Content API endpoint taking an `id` option, e.g. GET /ghost/api/admin/users/1/.
- Who is affected: Admin API clients and scripts that hardcode id `1` to reference the owner user (or any resource) in paths or query options, often in older integrations written against pre-ObjectID Ghost.
- What to check: Search your code for API calls using `/1/` or `id: 1` / `id=1` (string or number). Replace them with the real 24-char ObjectID, or use `me` for the authenticated staff user. Expect a 422 validation error (likely ValidationError) where these calls previously succeeded.
Medium Impact Changes
- Removed per-tier Stripe Checkout configuration ยท Merged 2026-10-07 ยท Permissions & endpoint behaviour, Other, Endpoint response shapes ยท The Admin API sub-resource for per-tier Stripe Checkout configuration is gone. Requests to it no longer reach a checkout_config controller. The GET routes were not labs-gated, but the data was only meaningful under the private stripeCheckoutCollection flag.
- Added verified newsletter recipient preparation ยท Merged 2026-10-06 ยท Permissions & endpoint behaviour, Endpoint response shapes ยท Retrying a failed newsletter email now claims the retry with a row-locked status update. A concurrent or stale retry request now gets a 400 with a machine-readable code instead of scheduling the email twice.
- Fixed 500 on newsletter verification with a non-newsletter token ยท Merged 2026-10-02 ยท Permissions & endpoint behaviour ยท Newsletter email verification now rejects tokens that lack an id or whose property is not sender_email or sender_reply_to. These requests return a 400 BadRequestError instead of a raw 500. Valid newsletter verification tokens behave as before.
- Removed the authReact flag ยท Merged 2026-10-08 ยท Endpoint response shapes ยท The site object returned by the public Admin and Members /site/ endpoints no longer contains the authReact boolean. The field was a Labs flag indicator that was only recently added.
- Added newsletter retry eligibility to Core ยท Merged 2026-10-07 (flagged open 2026-10-03) ยท Endpoint response shapes, Permissions & endpoint behaviour ยท The Admin API email sending-status response now includes a boolean retryable field when a send has failed. It is false when any batch is still in the submitting state.
- Fixed uncomping a member not cancelling their complimentary subscription ยท Merged 2026-10-07 ยท Other ยท On sites with Stripe connected, editing a member through the Admin API with comped: false now cancels their active Complimentary Stripe subscription. Before this fix the request did nothing because the subscription relation was never loaded.
- ๐ Fixed member deletions not showing in History ยท Merged 2026-10-06 ยท Permissions & endpoint behaviour, Endpoint response shapes ยท Admin API member deletes now run inside the caller's transaction with require: false actually applied. On SQLite, deletes no longer hang until a connection timeout, and concurrent deletes of the same member no longer fail with a "No Rows Deleted" error.
- Fixed custom field values collected at checkout never reaching webhooks ยท Merged 2026-10-01 ยท Webhook payloads ยท Custom field values collected at Stripe Checkout now trigger a member.edited webhook that shows the new values and the previous ones. Before, these writes sent no webhook. Custom fields are behind a private labs flag, so only sites with it enabled see this.
Low Impact Changes
- Added Preview in Stripe to the checkout design settings ยท Merged 2026-10-08 ยท Permissions & endpoint behaviour ยท Adds a private-flagged Admin API endpoint that creates a real Stripe Checkout session for a paid tier using an unsaved checkout design. Integrations are refused; it returns 404 while the stripeCheckoutDesign labs flag is off.
- Added a site-wide design for Stripe Checkout ยท Merged 2026-10-08 ยท Permissions & endpoint behaviour, Endpoint response shapes, Other ยท Adds two Admin API endpoints for a site-wide Stripe Checkout design. Both sit behind the private labs flag stripeCheckoutDesign and return 404-style 'not enabled' responses while it is off.
- Added endpoints to preview, install and approve apps from a manifest URL ยท Merged 2026-10-08 ยท Permissions & endpoint behaviour, Endpoint response shapes, Other ยท Three Admin API endpoints are added under /apps/: preview, install and approve app installations from a manifest URL. All three need the app_installations add permission, so staff integration API keys and non-admin staff roles get 403.
- Added endpoint for creating automations ยท Merged 2026-10-06 ยท Permissions & endpoint behaviour ยท POST /ghost/api/admin/automations previously always returned 501 NOT_IMPLEMENTED. It now creates an automation from the first element of the automations array. The existing permission check and the MAX_AUTOMATIONS limit of 20 still apply.
- โจ Released self-serve site exports ยท Merged 2026-10-07 (flagged open 2026-10-03) ยท Permissions & endpoint behaviour ยท The Admin API export endpoints are now always available. Before this change they returned 404 unless the selfServeArchives labs flag was on, and that flag is now GA.
- Added member search to the automation runs API ยท Merged 2026-10-01 ยท Permissions & endpoint behaviour, Endpoint response shapes ยท The Admin API automation runs browse endpoint now accepts a 'search' query option for finding runs by a member's current name or email. Permissions are unchanged: it still requires automations read.
- Required labs flags for "add automation" endpoint ยท Merged 2026-10-01 ยท Permissions & endpoint behaviour ยท The unimplemented Admin API add-automation endpoint now returns 404 NotFoundError unless the automations and automationsPerTier labs flags are both enabled. Previously it hit the automation limit check and then returned 501.
- Added the app installations table and Admin API ยท Merged 2026-10-07 (flagged open 2026-10-03) ยท Permissions & endpoint behaviour, Endpoint response shapes ยท New Admin API routes for app installations, gated by the private `apps` labs flag. They also require tables that only exist in development and testing databases, so production sites answer 404. A migration grants the new app_installation permissions to Administrators only.
- Added automation run history API ยท Merged 2026-10-01 ยท Permissions & endpoint behaviour, Endpoint response shapes ยท A new read-only Admin API endpoint returns the step history for a single automation run. It uses the existing automations read permission and Admin API authentication.
- Returned trigger settings from automation read/edit responses ยท Merged 2026-10-05 ยท Endpoint response shapes ยท Admin API automation read and edit responses now include two new fields describing which tiers trigger the automation. The change is purely additive.
- ๐ Fixed member attribution and offer redemptions sometimes missing right after a change ยท Merged 2026-10-01 ยท Endpoint response shapes, Other ยท Attribution and offer-redemption rows are now written inside member create and subscription linking. Reads made straight after a change, including the Admin API POST /members/ response, now consistently include attribution. Browser-supplied attribution strings are cut to their column lengths before saving.
- ๐ Fixed email excerpts dropping their last character on desktop ยท Merged 2026-10-07 ยท Web & email rendering ยท Newsletter email truncation no longer drops the last character in the desktop-only span when text length is exactly maxLength. Visible output of newsletter emails changes slightly; no template, helper or class names changed.
- Removed the unreachable array branch from theme i18n's t() ยท Merged 2026-10-05 ยท Web & email rendering ยท Dead array-handling code was removed from the theme i18n t() method that backs the {{t}} helper. Translation keys that resolve to arrays already returned the fallback message, so rendered output does not change.
- Added concurrent newsletter preparation from an upfront recipient sweep ยท Merged 2026-10-06 (flagged open 2026-10-03) ยท Other ยท Newsletter batch preparation now selects the whole audience in one UNION ALL query and writes batches with concurrent workers. A new config key, bulkEmail:batchCreationConcurrency (default 2), controls the worker limit. No API, webhook or template surface changed.
- Update dependency cookies to v0.9.2 ยท Merged 2026-10-06 ยท Sessions & cookies ยท Patch bump of the cookies library (0.9.1 to 0.9.2), which fixes a CVE and tightens validation of the path and domain cookie attributes. The diff was not available, so this is assessed from the release notes only. Nothing indicates that cookie names, values or how a session resolves to a member or staff user have changed.
- Made automation slug nullable ยท Merged 2026-10-01 ยท Endpoint response shapes ยท The automations.slug column is now nullable in the schema, with a migration in 6.68. Existing rows keep their slugs, so nothing changes yet, but future automations may be created without a slug.
- Added nullable newsletter recipient accounting columns ยท Merged 2026-10-06 (flagged open 2026-10-03) ยท Endpoint response shapes ยท A migration adds nullable recipient-accounting columns to the emails and email_batches tables. The four new emails columns are removed by the serializers from Admin API email, post and activity-feed output. The three email_batches columns are not stripped in this diff and may appear in batch responses.
- Changed self-serve exports to email the staff user who requested them ยท Merged 2026-10-05 ยท Other ยท The self-serve export request handler in the Admin API exports endpoint now passes the signed-in staff user's id to the export requests service, so the hosting platform can email the download link to the requester instead of the site owner. The request and response shape are unchanged.
- Changed the member custom field types package to be published to npm ยท Merged 2026-10-01 ยท Other ยท @tryghost/metafield-types is becoming a public npm package (0.1.0), so integrations can share Ghost's member custom field type definitions instead of keeping their own copy. The core diff only repoints CSV helpers to a new private package; the members CSV column format is unchanged.
Open
Low Impact Changes
- Added app details and uninstalling to Apps in Admin ยท Open ยท Endpoint response shapes ยท The Admin API app installation read endpoint now accepts include=manifests and can return the installation's manifest rows. The default response is unchanged, and the whole feature sits behind the private apps flag.
- Improved date handling cost when fetching rows on large sites ยท Open (flagged open 2026-10-03) ยท Endpoint response shapes ยท Internal performance refactor of how dateTime columns are normalised on read and write. API date fields such as published_at, updated_at and created_at should come out identical, still truncated to whole seconds.
Run stats
| Measure | Value |
|---|---|
| Window | 2026-10-01 to 2026-10-08 |
| PRs scanned | 565 |
| Candidates | 167 |
| Triaged | 167 |
| Deep reads | 38 |
| Previously flagged, still open and unchanged | 12 |
| Triage tokens | 167 calls, 239,973 in / 9,691 out, 0 cache read / 0 cache write |
| Deep-read tokens | 38 calls, 119,109 in / 23,458 out, 64,980 cache read / 3,610 cache write |
| Intro tokens | 1 calls, 16,298 in / 346 out, 0 cache read / 0 cache write |
| Estimated cost | $1.06 |
Hey, before you go... If your finances allow you to keep this tea-drinking ghost and the freelancer behind her supplied with our hot beverage of choice, we'd both appreciate it!