Your changelog is part of your API
Every integrator eventually asks the same question: did something change? If the answer lives in a release-notes page nobody subscribes to, they ask your support queue instead.

Something in production started failing at 14:00. It worked at 13:00. The developer whose integration it is has exactly one question, and it is not a question about your API's design.
Did you change something?
Where they find the answer decides the next hour. If your changelog is current, they read it, find the entry, and fix their code. If it is a marketing page last updated two quarters ago, they open a support ticket, and now the question is yours to answer with your own git log.
That is what a changelog is for. It is not release notes and it is not a newsletter. It is a debugging tool you publish in advance.
What belongs in it
Every change to the surface a consumer can observe. That is a wider set than most teams publish.
New endpoints and new fields. The safe additions. They belong in the log even though they break nothing, because "when did this become available" is a real question with a real answer, and because a developer on an older assumption needs to know the thing they wanted now exists.
Removed or renamed anything. Endpoints, fields, enum values, error codes. These are the entries people are actually looking for at 14:00.
Changed requirements. A parameter that became required. A field that became nullable. A default that changed. These break integrations without changing a single name, which makes them the hardest for a consumer to diagnose from the outside, and therefore the most valuable to write down.
Behavioural changes that touch no schema at all. A rate limit that tightened. A list that now returns twenty-five by default instead of fifty. A webhook that started retrying differently. None of this shows up in a spec diff, and all of it will surface as somebody's bug report.
That last category is the one teams skip, and it is the one that costs the most, because it is invisible in every automated comparison. If your spec diff is your changelog, you are publishing only the changes that were already easy to detect.
Mark the breaking ones, and mean it
A changelog where every entry looks alike is a changelog people skim. The only property a reader needs at a glance is whether an entry requires them to do something.
Mark breaking changes explicitly, and be strict about what earns the label. A new optional field is not breaking. A new required parameter is. A renamed field is breaking in every typed language you publish to and silent in the untyped ones, which makes it worse rather than better.
Being strict is what makes the label useful. If you mark everything, nobody filters. If you mark nothing, nobody trusts it and everybody reads everything, which is the same as nobody reading anything.
Dates, not just versions
Version numbers are how you think about your API. Timestamps are how your consumers debug it.
"Broke in 2.4.0" is useless to someone who does not know when they upgraded, and completely useless to someone consuming your API over HTTP with no version pin at all, which is most people. Every entry should carry the date it took effect in production. If a change rolled out gradually, say that, because "it worked for us until Thursday" is a real report and a staged rollout is the explanation.
Deprecate in the changelog before you remove in the code
The changelog is where a deprecation becomes real. Announcing a removal on the day you remove it is not a deprecation, it is an outage with a note attached.
The sequence that works: mark it deprecated in the spec so it surfaces in generated clients and reference pages, write the changelog entry that says what to use instead and when it goes, then remove it on that date. Consumers get the warning at compile time from their SDK and the reasoning from your changelog, which is both halves of what they need to plan.
Removing an operation breaks callers at compile time on their schedule, not yours. They upgrade for an unrelated reason, everything stops building, and your tidy-up becomes their incident.
Agents read it too, which raises the stakes
This is new, and it changes the value of keeping a changelog current.
A coding agent asked to integrate or upgrade an API now has a way to read your documentation directly, and the changelog is one of the things it reads. Asked why a call that used to work now fails, an agent with access to your changelog can find the entry and fix the code. Without it, the agent does what it does with any missing information: it reasons from what it saw during training, which is your API as it existed at some point in the past.
A stale changelog was previously a documentation gap. It is now a source of confidently wrong code, generated at scale, by tools your consumers are already using.
The practical implication is that a changelog should be structured enough to query, not just readable enough to skim. Dated entries, explicit breaking flags, and the affected operation named rather than described. That is also what makes it useful to a human in a hurry, so there is no tension between the two audiences.
Make it a URL, not a PDF and not a Slack message
It needs to be a page, on your docs host, at a stable address, with each entry addressable. Support answers link to it. Agents fetch it. Search indexes it, and "did change its API" is a query people type.
If you are publishing docs from a spec already, the changelog belongs in the same place, on the same domain, with the same navigation. A changelog on a different host is a changelog nobody finds during an incident.
The short version
Write down every observable change, date it, mark the breaking ones honestly, and put it somewhere permanent. It costs a few minutes per release and it is the page that answers the question your consumers ask most often and most urgently.
If you want the parts of this a spec can enforce, our spec audit checks whether your operations declare the things a changelog entry usually has to explain, and what counts as a breaking change covers which spec edits earn the label.



