Build1 distinct publisher2 min readUpdated
The obvious success check returns None on a live post, and the retry branch takes it from there. An unauthenticated 200 is the proof that does not depend on your key.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Two representations of the same article, and only one of them belongs to the author. The collections under /api/articles/me/* are author-scoped: they describe the post the way its owner sees it, and they echo back the published flag the owner sent on POST or PUT [8][7]. GET /api/articles/{id} hands over the article the way an anonymous reader receives it, and that view has no publication state to report, because anything fetchable there is public already [9].
The author did not leave that as an assumption. A draft created with published false, id 4449977, returned 404 to an unauthenticated request, and 404 again to the owner's own key [10][11]. The endpoint is not filtering fields by permission. It has nothing to say about non-public content at all, so the existence of a response is the state [2].
That reframes the problem from a missing field to a misread contract. The loud failure is survivable: article["published"] raises KeyError and the run stops [12]. The quiet one costs money. article.get("published") returns None because the key is absent rather than false [5], None is falsey, and the branch that handles "not yet published" is usually the branch that retries [12]. The publish has already worked. The script pushes again.
The write path offers no cover either. A PUT returned HTTP 200 and a body with no published key, even though published was a field that request had just set [6]. You cannot confirm your own write from the response to it.
There is a second difference worth knowing before you compare timestamps across the two views. me/published reported published_at as 2026-08-16T07:13:13.534Z, while the id endpoint reported 2026-08-16T07:13:13Z for the same article [2][3]. One carries milliseconds and the other truncates to whole seconds, so string equality between them fails and any ordering inside the same second is lost [1]. Cache the author-scoped value, assert against the public one, and the check breaks for reasons unrelated to publication.
Scope, which matters to anyone running their own Forem: one account on dev.to itself, API v1, three published posts and one draft, measured on 2026-08-21 [1]. The article under test had been live for five days by then, so a propagation lag is a thin explanation [3]. Self-hosted instances, organization articles and scheduled posts were not tested, and a self-hosted Forem can run several versions behind [15]. That is the case for probing reachability rather than reading a flag [13]: the probe does not care which version of the software is answering.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
GET /api/articles/me/published?per_page=1 with the api-key and vendor accept header returned article id 4408696 with published True and published_at 2026-08-16T07:13:13.534Z.
GET /api/articles/4408696 with the same api-key returned a body where 'published' in a was False, and published_at was 2026-08-16T07:13:13Z.
On that endpoint the published field is not false and not null; it is absent from the response, so article.get("published") hands back None.
GET /api/articles/{id} is a different representation: it serves the article the way an anonymous reader receives it, and in that view there is no publication state to report because an article fetchable there is by definition published.
Everything reported was measured on 2026-08-21 against dev.to with API v1, on the author's own account, with three published articles and one draft.
The single-article request was run three ways, with the api-key header, without it, and without the vendor accept header, and 'published' in a was False every time, so this is not a permissions difference and the key does not change it.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Reproducible first-party measurement, single observer
The central factual claims are backed by verbatim curl transcripts with concrete article ids, timestamps and status codes, plus two useful controls: three header variants ruling out a permissions explanation, and a deliberately created draft returning 404 even to the owner's own key. That is stronger than an anecdote. It is capped by being one account, one host, one date, with no Forem version recorded and no vendor documentation, changelog or independent replication cited.
One self-reported adopter of the recommended check
The only adoption datapoint in the supplied material is the author's own publishing script switching to the unauthenticated-200 gate. There is no evidence of other users, projects, libraries or platform-side change adopting or responding to this finding, and no data on how many scripts rely on the published flag today, so the measured level is deliberately near the floor rather than inferred upward.
Claims sit at or slightly below the evidence
Framing matches what was actually measured: the piece says the field is absent on one endpoint on hosted dev.to on one date, explicitly declines to generalize to self-hosted Forem, organization articles or scheduled posts, and notes its recommended check survives even if the field reappears. If anything the operational severity — a false negative feeding a retry branch in a publish pipeline — is stated more soberly than the consequence warrants, hence a small negative rather than zero.
Low commercial incentive, mild platform-visibility interest
The item is an individual developer post on dev.to about dev.to's own API, with no product, vendor, sponsor, pricing or funding interest visible in the supplied text. The residual incentive is reputational — publishing a debugging finding on the platform it concerns invites traffic and comments, and the closing request for reader results serves that too — which is enough to warrant a low nonzero score but not to suggest distortion of the transcripts.
Credible single-observer finding, uncorroborated
Confidence is held mid-range: the mechanism is well-instrumented and internally consistent, so the behavior on hosted dev.to on 2026-08-21 is likely real, but the cluster has exactly one publisher, one account and no vendor or third-party confirmation, and API response shapes can change without notice. Generality to other Forem deployments and article types is unverified, and adoption evidence is a single self-report.
build
Short Build Roots Do Not Fix MAX_PATH: Unreal Cook Failures Are a Windows Setting1 distinct publisher
build
Three manual interventions in a month, and every guard was working as designed1 distinct publisher
build
Six MariaDB versions, one real difference: the only reason to leave 10.6 is the July 2026 clock1 distinct publisher
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026