 for coming. I'm super excited to be here to talk to you about design the APIs for an internal set of services. My name is Albert. That's my Twitter and my GitHub account and my email address if you want to follow me on those. And if you can have any questions, you can reach me out on that email. I work at global.com. Global.com is the internet branch of global organizations, which is the largest media conglomerate in Latin America. And we aggregate the greatest vertical portals in Brazil for news, soap operas, entertainment, videos, and so on. And we release a lot of open source projects as well. Sorry. And one of them is called Tissue, which is our cloud application platform. And if you want to check this project out and some others, you can see all of them in our GitHub page, slash global.com. During this talk, I'd like to cover two main topics. The first one is about designing the APIs. And the second one is about the microservices environment. So we're starting with the API itself. What is an API? The acronym stands for application programming interface. But here I'm more interested in the interface part. Because when we are developing an application or a library, so that other developers can integrate to that is through the API that it may be feasible, right? So what about the microservices environment? Here is a little definition of what it is. It's a concept where an application is decomposed into small and loosely coupled services where each service has a single responsibility running in its own process. So let's see an example so it may become clear. Let's imagine a simple page where we have a few lines of text. And there is some videos and some ads as well. And all of this together produces our content page, right? If we start thinking of microservice architecture, we can observe that we can extract some services here. And decomposing our services this way, we can involve them independently of the others. And maybe we can have different teams working on each of them. For instance, I can have one team working on the tasks related to the video, such as compression, encoding, and so on. And the other one taking care of just the images, caching, whatever. And decoupling an application into those small services offers us another great opportunity, which is we can use the right tool for the job. Now it's possible to use the Node.js to write a simple API. I can use Java for the back end. I'm not stuck on a simple stack or platform. And this architecture leads to a more maintainable and stable application. How it happens, for instance, it's pretty easy to replace any service to another one due to performance issues or any other problem that you may have with that. Just replacing that piece of code, the entire service. You don't need to replace the entire application, right? You just need to replace that piece that is not working pretty well. But you just need to keep in mind that interface should be the same. So other servers can continue using your new services, right? And the concept behind the micro-services environment is not particularly difficult, but it raises a lot of questions, such as how to define services, contract, so that those services can communicate to each other. How do we manage the deployment? And how can I test these tests? So let's go back for a moment to our first main topic, which is API. And how do we get started building our API? Everything starts during the API modeling phase, right? Where we need to gather all the stakeholders, the software engineers, the designers, everyone involved in the development of the API at the same room, trying to create the conceptual model, trying to understand the purpose of the API. What is the main goal of the API that I'm building? Is it to save money or is it to make money, right? Maybe neither. The main goal is just to help other developers to save time and effort. And then we need to understand our audience. Who is going to use my API? Is it going to be used by Ruby developers, Java developers? The main audience of the API is the developers. So we need to keep in mind that the developer experience means a lot. We need to make sure to put an extra effort so that our API is enjoyable to use. So when we are building a product or application, we always keep in mind that it should be enjoyable to the final user to use that, right? So we need to keep the same thing when we are creating an API. We need to see our developer as our customer. At the same way, we need to see the API as our product. Because in fact it is. And it's pretty much important to create a common language, an ubiquitous language. We need to create a vocabulary of terms that will be used during all the API cycle time, cycle life. We need to, when we are going to talk to business people, they must understand the same thing that the software engineers when you are talking about API application, services. And we need to make sure that all of those terms are being used all over the place in the resource names, the documentation, data fields, and so on. And after that, we can start modeling our resource, trying to identify the data fields, the relationship between them, and check if all the resource available through the API is going to be public or some of them must be required authentication. And maybe this time here is a good moment to define the format, the error format. I'm not going to talk about the error format right now. Let's move on. I'm going to talk about error format in a few minutes. And probably you are going to create hypermed APIs. And if so, there is no need to reinvent the wheel trying to create another awesome way to describe your data format and describing the links. There are some great libraries out there that may help you a lot such as Hall, JSON API, and JSON schema. The examples that I'm going to show you here use JSON schema, which is the tool that we are using at work. So what makes a great API? Let's see some examples. A great API is flexible and simple to use. Every developer has its own preference regarding the data format. Some love JSON, some others love XML. And when we are designing an API, we know that. But we need to decide which format we are going to support. If we decide to support both formats, we need to have in mind that it's going to take time and effort to test if everything works on both formats. And an API should be simple to use. It should be intuitive so the developer doesn't have to spend much time trying to figure out how the API works. For example, sometimes it's useful to retrieve all the fields related to the resource cars. But sometimes it isn't. So adding support to partial response by adding optional attributes, it's a good idea. It helps the developer to retrieve only the data that they need to use. And the API URLs matter a lot. Prefer to use nouns instead of verbs and put them in a logical groups whenever possible. For example, here I have my collection followed by my resource and after that I have filters. Those filters there can be partial response or pagination. You can use those filters for whatever you want to do. Let's check these URLs, those paths that we have here. All of those, all of them do the same thing. Get all cars, get all new cars or get just one specific car. And which one of these do you think is more intuitive? The left side, right? If we start mixing up verbs with nouns, maybe we can end up with a big ball of mud in our hands. The maintenance becomes hard. So let's leave the HTTP verbs to perform operations in the elements. Search post to create, get to read, put to replace, patch to update, and delete if you want to delete. And a great API returns a meaningful warehouse. And we need to make sure that the error should and the errors are clear enough to help the developers. Errors are so important to the developers because when they are starting to using that, they don't know what happens on the other side. Everything on the other side becomes a black box. They only know the interface part. So the error message should provide visibility. What happens when something goes wrong on the other side? No matter if the error is from an invalid request or if the error is from the service side of the error. And developers learn a lot how to integrate two APIs through errors. I have seen some providers return only 200 stats code and for everything, no matter what happens, if it's a success or if there is an error. And using the HTTP payloads to indicate what is wrong. But there are other providers aligning the HTTP stats code with the payload. Particularly, I prefer this approach. But we know that there are more than 50 stats codes out there. And it's not a good idea. It's not so easy to memorize all of them and forces our customers to do so. So basically what I have been using is all of those five stats codes. 400 for a bad request when indicating when the service side could not fulfill the request. 401 for an authorized, 403 for bidding, 404 not found and 500 for an internal server error. And that great API provides a great support. Here, when I talk about support, an API support, I like to talk about three items. The first one is about documentation. Designing and developing an API takes us a lot of time and effort to do that. So we need to put the same effort when we are writing the documentation. Because here I have an example. When we buy an iPhone or an iPad, we don't, where's the manual? Where's the documentation? We just unbox it and start playing touchy. But in the API, if it doesn't happen like that, we need to indicate to the developer how to use the API. So let's make sure to create guidelines, quick starts, and some samples so the developers can see how easy is to integrate the API. And the other, and the other element here is the communication. We need to keep an open communication channel to our customers so they can send questions and feedback. It can be RERC channel, mail list, or GitHub, whatever works for us. And the last one is community. When the API starts getting more users, it's not so difficult to see great user margins around that. So we need to keep those developers close to the API team, creating a community around that. And another element is security. A great API security. A key point here is to use SSL to encrypt the communication between your API and your clients, your customers. And besides that, make sure that only the resource, only protected resource is accessible with proper permissions. What about versioning? An API is never completed, right? There's always a new version, there's always an improvement there, and changes may occur. But that's not the problem. The problem is how we deal with those changes. How many versions should the API support, right? I would say that an API, sorry, I would say that an API should support at least one version back. Because when we start dealing with multiple versions, things may get complicated. And whenever we plan to release a new version of the API, let's communicate to the existing users. And let's give the existing users at least one cycle to migrate to the new one before deprecating. And a good practice is to use the header to indicate which version you are trying to use. Here I have two examples, both for HTTP accept, or I can put the version as a new parameter there, or I can just append that in my vendor, my type. Okay, so now that we have discussed about our APIs, how can they communicate to each other? How to define services contracts? So one service can understand which operations can be performed on the other side. And for this, let's go back for a moment to our previous example, where we had a web content page with those three components, and see how they communicate. And a service, everything starts with a contract. A service must expose its functionality through a contract. And it should be done through a schema document. And that's the way other services, in this case all our customers, may discover which operations, which functionalities they can consume for the other side, and which data they need to send on that operation. And I said that previously that services can be involved independently, right? And the contracts enable that. But previously I said as well that loosely coupled, and here we are seeing that contracts can also couple service provider and customers. How is it happening? Let's see. I have one service exposing the functionality through a contract, and there are already two other services consuming them. And now there is another service who wants to use the same contract, the same service, right? But he has special needs. He asks the provider, oh, can you please add one more required field for me? Oh, okay. I'm going to add it, no matter. And even a simple change like that may have implications on the existing customers. For example, here, by adding a new required field, we are breaking the other two clients. And I'm going to cover two approaches to solve this. The first one is we can distribute the cost of the change between the provider and the customers. From the provider perspective, the provider just needs to apply the change requested by the new customer and communicate and change the contract. And from the customer perspective, they just need to update the contract. So here it's, when we are starting getting our, when we are on the initial phase of our API, it's pretty common to use this approach because we don't have many existing customers. So, oh, it's pretty formal. Can you change it here? And the other way is to leave the cost of the change just for the provider. The provider must create another contract with the change requested by the new customer and leave the other, the older one as it is. So the existing customers don't do, to do anything, don't need to do anything. Here's an example of it on JSON schema, where I can describe my app with two properties, name as a string and the URIs as an array of strings. And I can indicate which fields are required, in that case, just the name. And I can say as well which operations can be performed. Here I have an operation called create. And to create an item, you must use the method post. And the schema which represents these data is this one, apps slash new app. It's this guy here. So when I'm going to post a new application, I need to agree with this contract. In this case, it's pretty simple. A contract is about commitment, right? It's, we can involve our services, but we need to make sure that I'm not breaking any contract that I have made to other parts. And it's not a new thing. It's a pattern called customer-driven contracts, a survey evolution partner pattern. Okay, so now moving to the next question, how to manage deployment? Speaking in general, the deployment in the microservice environment is easier because we don't have to move all the parts, all the entire application. We just need to move the services that have been changed, right? But things may get complicated when there is a dependency between two or more services. So in this case, I need to make sure to move those services in the specific order. Otherwise, I'm moving services which relies on another contract, but on another service, sorry. And the other service has not been moved into production already. It's quite common to see as well that each service has its own server. So each service doesn't impact on another one. For example, if the server is responsible to deal with video tasks goes down, the other service, the services regarding the images, for example, continue living without any issues. And what about tests? How can I test those services? We have seen that a service exposed, it's functioned through a contract, right? Indicating which operations can be performed using which ATTTP verb. So we can take advantage of that and use a contract test where the customer can get the contract and mock it to write some tests. Or we can use an integration test, sorry, and we can do integration tests where there is no mock here and we are hitting the services. But here, the test is a little slow because there is an ATTP connection happening and there is more room for failure because the internet may not work pretty well or the service out for maintenance. And there are a lot of things to do and sometimes things don't go as planned, but don't worry, you can always release a new version of your API. Thank you very much.