When you already have an app in production or a public API, you can't make changes to this API without a big cost. If you change the input or the output of a url, every client using your API has a chance to crash. The only solution you have would be to create a new version of your API.
The first thing you have to do is to accept a version number from the clients. There are three ways to do it:
The first solution allows you to easily change the url name from a version to another. As one url will always return the same result, it is also more respectful of the REST standard. Nevertheless, it's often more complex to implement (you have more entry points in your application).The second solution creates fewer entry points in your application. It is also retro-compatible if you forgot to handle versioning in your first version of your API. I do not recommend the third solution which has the same advantages as the second one in a less standard way.
Often, the input and output of your API are similar to your database model. When you create a new version of your API, you have two options:
If you choose to create several versions of your model (like a user and an user_v2 table) you will have trouble keeping them in sync. A user must be able to sign up in an application using both the v1 API and the v2 one. You create duplication of your data.
The best thing to do is to be able to return v1 and v2 outputs from the same entity. The following diagram shows the architecture I recommend!
Every entity has an associated representation for each API version. The representation is simply another class for the same domain concept. The properties of this class are the ones exposed in the API.
We use transformers to make the link between the Model entity and your representation. If you have to change your model, just adapt your transformers without changing your representation and the API outputs won't change.
If you want to see an implementation of this architecture for symfony2, you can read my article on the subject.
It is quite painful to maintain a lot of versions of the same API for a while. At some point, you should be able to mark old versions as deprecated and delete them.
One way to do it, is to have a special endpoint with the list of available versions. The endpoint can return something like:
++pre>{
"availableVersions": [4, 5],
"deprecatedVersions": [3]
}++/pre>
In this example, the versions 1 and 2 have been deleted and the version 3 is deprecated.
In the client, you should check the API version you use. If it is a deleted or deprecated version, you should show a blocking message to force an update. You can also signal that a new version is available.