As a Mobile Developer, I’ve come to realize how fragile most APIs really are. While something like making a slight change in the date format could be a non-issue on the web, that same change will crash the entire iPhone app, making it completely unusable.
Knowing the best practices behind mobile-friendly APIs is more important than ever for mobile developers as we work closely with back-end API developers to create the best experience for the user.
This is why I was excited to attend Michele Titolo’s APIs talk at CocoaConf last weekend. Michele has been an iOS Engineer and consultant for the past four years, and has worked with countless APIs. Here are some of the best practices for APIs that Michele brought up in her talk:
As a Rails developer, I would have been pretty annoyed if I had to write and maintain documentation, but as an iOS engineer, I can’t live without it for the most part. While I can get the payload back from an endpoint, I wouldn’t necessarily know what each field means and which fields are required for the business.
The ideal documentation is something interactive. Michele gave an example from Mashery, which does a great job at this by providing an interactive interface and description for each parameter:
If your team doesn’t have documentation, speak up and ASK FOR IT says Michele. There are tools that make documentation easy to keep and maintain. Any documentation is better than no documentation 🙂
Apparently some APIs have inconsistent URLs. As I’ve worked primarily with REST API’s, I’m lucky to have never experienced this inconsistency (so far), but Michele has some crazy horror stories. Here’s one API she’s worked with:
However, I have worked with an API recently that required a POST request for every single call – yes, even for GET, PUT, and DELETE! At least it is consistent, but it’s definitely also very confusing!
Sticking to the REST conventions is a good starting point, although REST is not always best for mobile. When you get outside of REST, make sure you’re still consistent and your URLs make sense. You know your URLs work well when a developer can guess the URL for a resource they’ve never worked with based on a resource they have worked with.
For mobile, it’s ideal to have 1 API call per screen. This means that a good API Payload needs to include all the data that the client needs.
While including more information than less is a good starting point, having every single data point (needed or not) in the payload might significantly slow load times on mobile, since all that data needs to be downloaded over a potentially slow network connection (yes, I’ve seen MASSIVE and slow payloads). The best APIs I’ve worked with are actually just very flexible, with the ability to include and exclude fields and nested objects as needed.
The payload also needs to be consistent. Things like name of a field (product_id vs productID), date format and url format (e.g. an image url with http:// in front of it) should remain consistent across different objects in the payload.
User authentication should be done with HTTP Basc Auth over SSL (when SSL is secure of course :). Of course Auth is a double-edged sword, especially since it requires two API calls and is pretty painful to implement from my experience.
In addition to authenticating the user, your app also needs to be Authorized – aka request specific permission to become a trusted API consumer. Since all your http requests can be tracked very easily (check out Charles), having just a single App Key is for authorization is not enough, since others can very easily discover and use it.
Instead, consider implementing SSL pinning. I personally haven’t used SSL pinning before, so a quick Google search led me to this article explaining what SSL pinning is:
SSL Pinning is making sure the client checks the server’s certificate against a known copy of that certificate. Simply bundle your server’s SSL certificate inside your application, and make sure any SSL request first validates that the server’s certificate exactly matches the bundle’s certificate.
Just last week, I was working with a 3rd-party API that always returned a 200 HTTP status with errors in the results! Ideal error handling includes returning the correct HTTP status code with a human-readable error message in the response, as Michele points out.
I cannot agree enough with keeping error messages managed on the server to be passed in the response. I’ve worked on an app that hard-coded the error messages based on the response code. That means that when marketing wants to re-word the messages in the future, all the previous versions of that app will not get that same update. Worse yet, in this scenario, web, android, and iOS will all have to manually handle all error messages. Having these error messages centralized and handled on the server is a must!
Yes, the server can cache the data! The current standards include:
- Cache-Control – the server specifies how to cache the data
- If-Modified-Since – a header that asks if there is any new data since a specific time
- etags – combine data and ids of objects
As mobile developers, we have to know about these standards and ask the API team to implement them to make the API work faster for our users.
It is up to the team to decide what defines stale data for your app. An e-commerce site, for example, might only be updated once per day, while a social networking site is updated every few seconds!
Neutral API Testing
To make sure the API is working as expected by the clients, it’s best practice to do Neutral API testing as part of your team’s continuous integration process. The API testing would compare the latest build’s API to the agreed-upon JSON API and make sure everything is in the correct format.
Michele recommended using RunScope as a tool to do the neutral API testing.
When you have a table view of multiple objects where a user can also edit multiple objects at once, it’s important for the API to have batching capability. Once the user is done editing, the changes for all the objects edited should be passed to the server at the same time (instead of making a separate API call for each object at a time with a high probably of failure due to mobile networking issues).
Here are the Michele’s original slides, which I highly recommend looking at!
Do you have any additional best practices that you’ve learned about on your team? Let me know in the comments!