Tips for writing APIs
5 min read
I'd like to leave a few tips that I think are adamant in writing good APIs. I've come across all of these mistakes, and they are a pain to deal with. Some more than others, but all decrease the enjoyability of working with them.
- First and foremost, be consistent. This might be the most important tip I would give, and will be the most detailed one:
- some cases are more broadly used, but, ultimately, it doesn't matter if you use
camelCase,PascalCase, orsnake_case, just use the same kind everywhere; - the above point goes for naming endpoints too; don't have one endpoint
reference-dataand anotherpublic_posts; - when two endpoints return the same kind of object(s), it's a good idea for the key of said object(s) to be the same (the same goes for all of its keys). For example, if an endpoint has a user under the key
user, other endpoints that contain a user should not have them under the keyperson; - if you have a kind of object under a key, and there's a possibility of it not existing, do not return any other kind of object under that key - either
nil,null, or empty object (at the worst case). For example, do not return an empty array where you'd usually find a dictionary; - if most of your endpoints have one kind of structure, use it everywhere. For example, if three endpoints have a root dictionary, don't make your other two endpoints have a root array;
- if you have some endpoints making use of
RESTmethods, for exampleDELETE /users/1, don't have other endpoints use a path component for the same functionality, for exampleGET /posts/1/delete; - if you have several endpoints that can be queried with the same parameters, use the same names in all places. If one endpoint expects
queryandpageSize, don't have other endpoints expectqandps; - for the same problem, always return the same
HTTPcode, for all endpoints. For example, if a resource can not be found, don't return400for one endpoint and404for another.
- some cases are more broadly used, but, ultimately, it doesn't matter if you use
- If you're writing
RESTAPIs, use its methods instead of path components:GETto get a resource;POSTto create, instead ofGET /users/create;PUTto update, instead ofGET /users/1/update;DELETEto delete, instead ofGET /users/1/delete;
- Use versioning:
/v1/users/1. Even if you're absolutely sure you won't need it, it's still good practice. Never say never. - Always have a container dictionary at the root level. This leaves room for adding new data in the future, while keeping the endpoint backwards-compatible. You might say that we can just create a new version for this endpoint, and you'd be right most of the time; but there are cases where you do not want to/can not create a new version yet:
{
"id": 1234,
"name": "Roland Leth"
}
// vs
{
"user": {
"id": 1234,
"name": "Roland Leth"
},
// Room for new data here
}