You are on page 1of 12

1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

How NOT to design APIs


Rob Konarski Follow
Jan 2 · 10 min read

Learning from bad examples

I was helping out a friend who needed to integrate housing availability


from a property management system with his client’s website. Luckily,
the property management system had an API. Unfortunately,
everything about it was wrong.

The goal of this story is not to give a bad advertisement for a used
system, but to share how things should NOT be developed, as well as
learn the right approaches when it comes to designing APIs.

Assignment
My friend’s client is using Beds24 system to manage their property
listings and keep availability in sync across various booking systems
(Booking, AirBnB, etc.). They are building a website and would like the
search mechanism to only show properties that are available for the
selected dates and number of guests. Sounds like a trivial task, since
Beds24 provides an API for integrations with other systems.
Unfortunately, the developer has managed to make a lot of mistakes

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 1/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

when designing it. Let’s walk through these mistakes, see what exactly
went wrong and how it should have been done.

Sin 1: Request body format


Since were are only interested in getting availabilities for properties of
the client, only /getAvailabilities call was of interest to us. Even
though this is a call to get availabilities, in fact this is a POST request
since the author decided to accept lters as a JSON body. Below is a list
of all possible parameters:

{
"checkIn": "20151001",
"lastNight": "20151002",
"checkOut": "20151003",
"roomId": "12345",
"propId": "1234",
"ownerId": "123",
"numAdult": "2",
"numChild": "0",
"offerId": "1",
"voucherCode": "",
"referer": "",
"agent": "",
"ignoreAvail": false,
"propIds": [
1235,
1236
],
"roomIds": [
12347,
12348,
12349
]
}

Let me go through the JSON object and explain what is wrong with its
parameters.

1. Dates checkIn  , lastNight and checkOut are formatted using


YYYYMMDD scheme. There is absolutely no reason not to use the
standard ISO 8601 format (YYYY-MM-DD) when encoding dates
as strings, since this is a widely adopted standard understood and
expected by most developers and JSON parsers. In addition to
that, the lastNight eld seems to be redundant because
checkOut is provided and it would always be one day ahead of

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 2/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

the last night. Please, always use standard date encoding formats
and do not ask the user of the API to supply redundant data.

2. All Ids, as well as numAdult and numChild elds are numeric, but
are encoded as strings. There seems to be no reason to encode
them as strings in this particular situation.

3. We have the following eld pairs: roomId and roomIds  , as well


as propId and propIds . Not only it is redundant to have the
roomId and propId properties since roomIds and propIds can
be used to pass Ids, but there is also a type issue here. Notice that
roomId expects a string, while roomIds requires a numeric array.
This can cause confusion, parsing issues, and would mean that the
back-end itself performs some operations on strings and some on
numbers, even though we are talking about the same data.

Please, do not confuse developers with such silly mistakes and try to
use standard formatting as well as pay attention to redundancy and
eld types. Do not just wrap everything in a string.

Sin 2: Response body format


As explained in the previous part about request body format, we are
only focusing on the /getAvailabilities call. This time let us have a
look at the response body format and see what is so wrong with it. Keep
in mind that we are interested in getting the Ids of properties that are
available for the given dates and a number of guests. Below are the
corresponding request and response bodies:

Request:

{
"checkIn": "20190501",
"checkOut": "20190503",
"ownerId": "25748",
"numAdult": "2",
"numChild": "0"
}

Response:

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 3/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

{
"10328": {
"roomId": "10328",
"propId": "4478",
"roomsavail": "0"
},
"13219": {
"roomId": "13219",
"propId": "5729",
"roomsavail": "0"
},
"14900": {
"roomId": "14900",
"propId": "6779",
"roomsavail": 1
},
"checkIn": "20190501",
"lastNight": "20190502",
"checkOut": "20190503",
"ownerId": 25748,
"numAdult": 2
}

1. ownerId and numAdult suddenly become numbers in the


response as opposed to them being strings in the request body.

2. There is no list of properties. Instead, properties are top-level


objects with roomId as keys. This means that in order to get a list
of available properties, we would need to iterate over all objects,
check if certain parameters like roomsavail are present, discard
others like checkIn  , lastNight  , etc. to get a list of properties.
Then, we would need to check the value of roomsavail property
and if it is more than 0, treat the property as available. But wait a
second, have a closer look here: "roomsavail": “0” and here
"roomsavail": 1 . See the pattern? If there are no available
rooms, the value is a string, while if there is a room free, it turns
into a number! This would cause a lot of problems in languages
enforcing type safety such as Java, since the same property should
not be of di erent types. Please, use proper JSON lists for
displaying a collection of data instead of coming up with weird
key-value constructs as the one above, and make sure that you
don’t change eld types from object to object. A correctly
formatted response would look like below (note that this format
would allow to also get information about rooms without
duplicating anything):

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 4/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

{
"properties": [
{
"id": 4478,
"rooms": [
{
"id": 12328,
"available": false
}
]
},
{
"id": 5729,
"rooms": [
{
"id": 13219,
"available": false
}
]
},
{
"id": 6779,
"rooms": [
{
"id": 14900,
"available": true
}
]
}
],
"checkIn": "2019-05-01",
"lastNight": "2019-05-02",
"checkOut": "2019-05-03",
"ownerId": 25748,
"numAdult": 2
}

Sin 3: Error handling


Error handling in this API is implemented in the following way: all
requests return a response code of 200  , even in case of an error. This
means that there is no way to distinguish between a successful and
unsuccessful response other than parsing the body and checking for
presence of error or errorCode elds. The API only has 6 error
codes, as seen below:

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 5/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

Error codes of Beds24 API

Please, consider not using this approach of returning a response code


200 (success) when something went wrong, unless it is the standard
way to go in your API framework. It makes life easier if the API client
could know upfront whether to parse the body or not, and how to parse
it (as a data object or error object). This can be achieved in two ways:
either have a HTTP code for each of the 6 possible errors above in the
range of 400–499 (preferred), or return a 500 in case of an error so that
the clients would at least know about an error before starting to parse
the body.

Sin 4: “Guidelines”
Below are the API use “guidelines” from the documentation:

Please observe the following guidelines when using the API

1. Calls should be designed to send and receive only the minimum required
data.

2. Only one API call at a time is allowed, You must wait for the rst call to
complete before starting the next API call.

3. Multiple calls should be spaced with a few seconds delay between each
call.

4. API calls should be used sparingly and kept to the minimum required for
reasonable business usage.

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 6/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

5. Excessive usage within a 5 minute period will cause your account to be


blocked without warning.

6. We reserve the right to disable any access we consider to be making


excessive use of the API functions at our complete discretion and without
warning.

While points 1, 4 make sense, I can’t agree that others do. Let me
explain why.

2. In case you are building a REST API, it is supposed to be stateless,


there should be no state present at any point in time. This is one of the
reasons why REST is useful in cloud applications. Stateless components
can be freely redeployed if something fails, and they can scale
according to load changes. Please make sure that when designing a
RESTful API, it is really stateless and developers do not need to care
about such things as “one request at a time”.

3. This is an ambiguous and very weird guideline. Unfortunately, I


could not gure out a reason the author has created this “guideline”,
but it gives a feeling that there is some processing done outside of the
request itself, therefore making calls right after each other could put
the system in some incorrect state. Also, the fact that the author says “a
few seconds” provides no speci c information about the actual time
between the requests.

5 & 6. Again, it is not explained what is “excessive” in this case. Is it 10


requests per second or 1? Also, certain websites would have a huge
amount of tra c, and blocking them from using the API just because of
that without any warning might make developers move away from
such a system. Please, be speci c when making such guidelines and
think about the users when coming up with rules like these.

Sin 5: Documentation
This is how the API documentation looks like:

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 7/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

Beds24 API documentation look&feel

The only problems here are readability and overall feel. The same
documentation could have looked way better if the author would have
used markdown instead of custom non-styled HTML. For the sake of
this post, I created a better version with the help of Dilliger in under 2
minutes. Here is the result:

Styled version of the documentation

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 8/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

Please, use tools to create API documentation. For simple docs, a


markdown le like the one above can be enough, while for larger and
more feature-rich documentation, tools like Swagger or Apiary are
better to be used.

Here is a link to the Beds24 API docs for those who want to have a look
at it themselves.

Sin 6: Security
The API documentation states the following about all of the endpoints:

To use these functions, API access must be allowed in the menu SETTINGS
>> ACCOUNT >> ACCOUNT ACCESS.

However, in reality anyone can make a request to fetch data without


passing any credentials for certain calls, like get availability of a certain
property. This is stated in a di erent part of the documentation:

Most JSON methods require an API key to access an account. The API code
can be set at the menu SETTINGS >> ACCOUNT >> ACCOUNT ACCESS.

In addition to the miscommunication about authentication above, the


API key is actually something that the user needs to create themselves
(actually type the key manually, no autogeneration whatsoever) and it
should be between 16 and 64 characters long. Allowing the user to
create the key themselves could potentially lead to very insecure keys
that can be easily guessed, or certain formatting issues since any string
can be entered in that eld in account settings. In worst cases, it could
also become an open door for SQL injection or other types of attacks.
Please, never let the user create API keys. Always provide them with
immutable autogenerated keys instead, with an ability to invalidate it
when needed.

For those requests that are actually authenticated, we have a di erent


problem: authentication token has to be sent as part of the request
body as seen below (from documentation):

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 9/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

Beds24 API authentication example

Having authentication token inside request body means that the server
would need to rst parse the request body, extract the key, perform
authentication, and then decide what to do with the request: execute it
or not. In case of a successful authentication, there is no overhead
involved as the body would have been parsed anyway. In case
authentication failed, the server did all the work described above just to
extract the token, spending precious processing time. A better approach
instead would be to send an authentication token as a request header,
using Bearer authentication scheme or similar. This way, the server
would only need to parse the request body in case of a successful
authentication. Another reason to use a standard authentication
scheme like a Bearer token is simply because most developers are
familiar with it.

Sin 7: Performance
Last but not least, it would take on average a little over 1 second for a
request to complete. With modern applications, such delays may not be
acceptable. Therefore, take performance into account when designing
APIs.

. . .

Despite all of the issues with the API explained above, it does the job.
However, it takes several times longer for developers to understand and
implement it, as well as forces to write more complex solutions to trivial
problems. Therefore, please think about developers implementing your

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 10/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

API before releasing it. Make sure the documentation is complete, clear
and well-formatted. Check if your resource names follow conventions,
that your data is well structured, easy to understand and use. Also, pay
attention to security and performance, do not forget to implement error
handling correctly. If all of the above is taken into account when
designing an API, then there would be no need for weird “guidelines”,
like in the example earlier.

As already mentioned, the goal of this post was not to make you never
use Beds24 or any similar system because their API is not implemented
correctly. The target was to increase the quality of software products by
sharing a poor example and explaining how it could have been done
better. Hopefully, this post would make someone pay more attention to
software development best practices and make software systems better.
Till next time!

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 11/12
1/18/2019 How NOT to design RESTful APIs – Rob Konarski – Medium

https://medium.com/@robertas.konarskis/how-not-to-design-restful-apis-fb4892d9057a 12/12

You might also like