Rebuilding the Capital One iOS app was an effort that required coordination across many different teams throughout Capital One. Not only was the new app built natively with a completely new design, but it also used a single sign-in for all of a customer’s accounts which required all new backend APIs. Throughout this effort, we learned a lot, we tried many different practices and philosophies. However, out of these changes and challenges we developed some general best practices for integrating with internal APIs.
A quick search of Google for “API Integration Best Practices” returns over 26 million results, but most of those results focus on technical API consumption practices such as caching, threading, and error handling. All of these are important to successful API integration, but with this post I decided to focus on the communication required for successful API integration instead. Below are five key lessons relating to API integration.
1. Communication is Key
This may sound obvious, but communication is critical. It should start well before integration with the API actually begins, and it serves multiple purposes.
*The first is forewarning. Just because the API exists does not mean that it is ready for an unlimited amount of traffic. If you’re working on a high volume application, load needs to be considered when selecting an API. Through early communication, client teams can work with API teams to determine the best course forward for both their project and their APIs.
In some cases, APIs may need to make changes to support traffic requirements. While this may impact timelines — and it does — it is much better than the alternative. No one wants to develop a new feature, release it into production thinking everything will work great (because your testing showed no issues), and then have the API go down because suddenly millions of people are trying to access it when it was designed for much less traffic.
In other cases, the APIs you selected may already be able to handle the load. Does that mean the communication was unimportant? No, because it opens up the communication channel and lets the API teams plan for additional monitoring around release dates.
*Beyond forewarning, early communication allows you to begin asking questions early. This opens the line of communication for questions that arise later during integration. This allows the API teams to learn and influence how you are planning on using their APIs. It also allows the front-end development team to determine the idiosyncrasies of the APIs they are planning to use. This is a communication pattern that should continue throughout the development process and even after release; helping to avoid unwanted surprises for both teams and helping to get questions and concerns resolved quickly.
*Communication will also help to debug any unexpected behavior that the client team is facing. However, for this communication to be most effective, both teams need to be honest about any issues or limitations in their code and open to potential solutions.
2. Document, Document, Document
This goes along with communication, but documentation is critical for both API and development teams.
*Having up to date and accurate documentation for an API allows the client-side team to easily integrate with the API. They have a document to refer back to for questions related to the API, which reduces the amount of time the API team has to spend answering questions.
The more information in this documentation the better, but at a minimum it should contain all of the request fields, specifying their data types and acceptable values, in order to properly call the API, the basic structure of the response, and a point of contact for questions. Better documentation will also include information about error scenarios, sample requests, and sample responses, including those for error scenarios. Again, the more information here the better. If the API team feels that there is any other relevant information to the API it should be included.
*It is just as important though for the client-side team to have documentation around what they expect from an API. This documentation should be consistent and applied to all APIs that they integrate with. (Obviously, exceptions will arise, but these should be rare.) This documentation will allow the API teams to quickly gain an understanding of what you are asking of them and their API.
For example, for the Capital One Mobile iOS app, we require that any API we integrate with have proper error handling with customer-friendly error messages and a specific response format. This allows us to handle all errors in the same way. This requirement is communicated in our documentation, so API teams understand our expectations.
3. Be Good Stewards
Every API and every organization will have their own requirements and expectations for what good stewardship means. Consider this another reason why communication, honesty, and documentation are key to successfully integrating with your organization’s internal APIs. For example, you may want to work with each API to determine the proper caching behavior. Constantly calling an API can have serious implications to your customers, such as spiking their data usage and draining their battery. Furthermore, these additional, often unnecessary, API calls can prove to be very costly for your organization since they increase the traffic to your backend.
Therefore, it is important to work with your API teams to determine what being a good steward for each API means. This may include expected caching behavior, call frequency, and/or determining the proper API to call. In one instance during development of the iOS app, through discussions with the API teams, it was determined that not only was the app calling an API too often, but there was an API better suited for our use case. The resulting changes led to a better customer experience and a more reliable overall feature.
4. Test Everything
No matter how much communication exists between the client team and the API team, there is always the chance that something will be missed. Proper testing can help to fill these gaps. This testing should include happy path scenarios, HTTP error scenarios, and edge cases.
When integrating with a new API in the Capital One mobile app, this testing actually takes place at multiple levels:
*The API integration code is fully unit tested using mocked responses that we have either directly received from the API or have worked closely with the API team to develop.
*Each API integration contains at least one integration test. These tests cover the happy paths and some of the more common error scenarios.
*After the UI is built, we run end to end tests of all scenarios. These tests will cover all happy paths, error scenarios, and edge cases.
This level of testing serves two purposes. The first and most important purpose is to reduce the risk of introducing a bug into the app. The second is it makes it easier to pinpoint where the problem lies when a test begins failing. If the end to end test of the UI is failing, but the unit test and integration tests at the API layer are succeeding, then the issue is likely to fall in the UI code, etc.
Writing these tests can feel tedious, but they will prevent bugs in your code, lead to a better user experience, and a more stable app. This makes them worth the effort.
5. We Are All One Team
When it comes down to it, API teams and client teams are all working toward the same goal, to deliver the best experience possible. Additionally, the client teams and the API teams need each other to accomplish that goal. Most apps are not very useful without integrating with backend APIs. Likewise, APIs are only useful if someone is actually using them. Remembering that we’re all in this together can go a long way in developing beneficial relationships between teams.
These five key points represent things we worked to achieve, support, and expand on every day and have led to great partnerships between the API and client teams, improved app features, improved APIs, and more. They’re applicable to a wide variety of enterprises and applications where internal API integrations are a part of the development process. Hopefully some of these takeaways will help with your use case too.