Our services
If you can think it, we can make it brainsoft.
If you can think it, we can make it brainsoft.
Written By: BrainSoft In Backend
Most API changelogs read like a commit log someone pasted into a wiki. The team knows what happened, the client does not. We have watched integration partners lose an afternoon to a field that quietly changed type, and that afternoon is the reason we rewrote how we publish changes.
A good changelog tells the client three things per entry: what changed, whether their existing calls still work, and what they must do before a given date. If an entry cannot answer those, it is a note for the team, not for the client.
Version numbers matter, but they are not the headline. A client integrating our payments API does not care that we shipped 2.14.0. They care that the status field on a refund now returns pending_review in some cases where it used to return pending, and that their switch statement will fall through to a default branch it has never hit.
So the first line of an entry is the impact sentence, written in the client's vocabulary. Then the technical detail. That order matters because most people skim the first line and only read on if it concerns them.
## 2024-06-11
Refund status can now be `pending_review`.
Action needed: add the new value to your enum before 2024-07-01.
Breaking: yes, for strict enum validation.
That is four lines. It answers what, when, and whether the client has work to do. Everything else — the ticket number, the internal reviewer, the release train — goes below the fold or nowhere.
A changelog where every entry looks the same trains people to ignore all of them. We label entries explicitly and keep the labels small and consistent:
The fix category is the one teams forget. If we spent six months returning a 200 where the docs promised a 404, someone wrote code around that 200. Telling them is not optional.
Prose about a changed response shape is slower to read than the shape itself. We paste the old and new payloads side by side, trimmed to the fields that moved. No screenshots, no links to a dashboard the client may not have access to.
// before
{ "id": "rf_123", "status": "pending" }
// after
{ "id": "rf_123", "status": "pending_review", "review_by": "2024-06-18" }
If the change is behavioural rather than structural — a rate limit tightening, a retry no longer being honoured — we show the request and the response instead. A short curl call that a client can paste into a terminal beats three paragraphs of explanation. When we handle this kind of work for clients, the changelog is part of the deliverable, not an afterthought; you can see the shape of that in our services.
Dates are the part clients actually plan around. Every breaking or deprecation entry carries a sunset date and, where possible, a support window where both versions work. "We will remove v1 at some point" is not a date.
We also put a named contact on the entry. Not a generic support inbox — a person or a team the client can reply to. Most of the friction we see is not the change itself, it is a client who read the entry, did not understand it, and had no obvious place to ask. If you are building this for your own product and want a second opinion on the format, get in touch.
Every time a client-visible behaviour changes, not on a fixed schedule. Batching entries monthly means a client can be broken for three weeks before they read about it. Additions can wait, breaking changes cannot.
Only if they change something a client can observe: response time, error codes, header casing, ordering of list results. If a refactor is invisible from outside the API, it belongs in your release notes, not the client changelog.
Say so and give the earliest possible date, then update the entry when you know. A vague date with a follow-up is better than silence, because silence forces clients to assume the change is imminent and plan around the worst case.