API versioning is one of a small number of decisions that become effectively permanent the moment someone outside your team depends on it. You can migrate a database. You cannot easily migrate other people's integrations.

Version in the path

URL path versioning (/v1/orders) is unfashionable and correct for most business APIs. It is visible in logs, trivial to route, and obvious to whoever is debugging at the other end. Header-based negotiation is more elegant and considerably harder to support over the phone.

Additive changes only, within a version

Inside a published version you may add optional fields and new endpoints. You may not rename a field, narrow a type, add a required parameter, or change what an error code means.

Clients parse your responses in ways you did not anticipate. Assume any field you emit is load-bearing for someone.

Decide the deprecation policy before you need it

Write down how long a version is supported after its successor ships, how consumers are notified, and what happens at end of life. Publishing this on day one is a routine technical detail. Introducing it on day four hundred, when a customer is depending on v1, is a commercial negotiation.

Nulls are part of your contract

Whether an absent value is null, an empty string, or an omitted key is something consumers will code against. Pick one, document it, and never vary it within a version.