Your API will change. New fields appear, old ones get renamed, a response shape that made sense at launch stops making sense at scale. The question is not whether you will change it, but whether you can do so without breaking every client that depends on you. That is what API versioning is for, and getting it right early saves enormous pain later.
Why you need versioning at all
Once someone integrates with your API, their code makes assumptions about your responses. Rename a field from name to full_name and their app breaks the moment you deploy. Versioning lets you introduce breaking changes behind a new version while old clients keep hitting the old one, on their own timeline instead of yours.
The common strategies
There are three widely used approaches, and each has a fair claim:
URL path: GET /v1/users
Query param: GET /users?version=1
Header: GET /users
Accept: application/vnd.myapi.v1+json
URL path versioning is the most popular for a reason: it is obvious, easy to test in a browser, and trivial to route. Header versioning is arguably “purer” — the URL points at a resource, and the version is negotiated separately — but it is invisible and harder to debug. Query-param versioning is simple but muddies the line between a version and a filter. For most teams, the path wins on practicality.
What actually counts as a breaking change
This is the nuance people miss. Adding a new optional field is usually safe — well-behaved clients ignore fields they do not recognize. Removing or renaming a field, changing a type, or altering the meaning of a value is breaking. If you only ever add, you can often avoid cutting a new version at all. Design your clients to tolerate additions and you buy yourself a lot of freedom.
Have a deprecation plan
Versioning without a sunset plan just multiplies the number of APIs you maintain forever. When you ship v2, announce a timeline for retiring v1, signal it in responses (a Deprecation or Sunset header is ideal), and give integrators real time to migrate. Communicate loudly and repeatedly — nobody reads the changelog until their app breaks.
Keep it boring
The best API versioning strategy is the one your team applies consistently. Pick path-based /v1/ versioning, add fields without bumping when you can, cut a new version only for genuinely breaking changes, and always publish a deprecation timeline. Boring, predictable versioning is exactly what your integrators are quietly hoping you will give them.

