- Guides
- An introduction to APIs
- API design
Chapter 6: API design
By Bryan Cooksey • Published January 23, 2024
This chapter marks a turning point in our adventure with APIs. We are finished covering fundamentals and are now ready to see how the previous concepts combine to form an API. In this chapter, we discuss the components of an API by designing one.
REST vs. SOAP
When discussing APIs, you might hear talk of "soap" and "rest" and wonder whether the software developers are doing work or planning a spa day. The truth is that these are the names of the two most common architectures for web-based APIs. SOAP (formerly an acronym) is an XML-based design that has standardized structures for requests and responses.
SOAP once stood for Simple Object Access Protocol. It was originally used for a very specific type of API access. As developers found ways to apply it to more situations, the name no longer fit, so in SOAP version 1.2, the acronym was dropped.
What is API design?
API design refers to the way developers and architects craft the rules and protocols governing the way systems interact with each other. To do this, they have to define the various methods, data formats, authentication mechanisms, and endpoints that let separate software entities do all the things we've discussed in the last five chapters.
A well-designed API has a few key benefits:
- Gives developers a clean, intuitive interface for accessing resources
- Enables efficient, reliable, and predictable integration with low risk of coding errors
- Fosters interoperability between a diverse range of systems, software, and applications
So, what exactly goes into well-designed APIs? Like just about all complex processes, it starts with organization.
Think for a moment about your Google Drive. Are you one of those people who dumps everything into a single folder or one of those people who meticulously arranges their photos, docs, and spreadsheets into a logical hierarchy of clearly labeled folders?
Companies give similar thought to organization when building their APIs. As we mentioned in Chapter 1, the purpose of an API is to make it easy for computers to work with the company's data. With ease of use in mind, one company may decide to have a single URL for all the data and make it searchable (sort of like having one folder for all your photos). Another may decide to give each piece of data its own URL, organized in a hierarchy (like having folders and subfolders sorting photos by date, location, or event). Each company chooses the best way to structure its API for its particular situation, guided by existing industry best practices.
SOAP provides a very structured architecture. The structure provides system reliability and standard extensions for adding functionality to the protocol, and it makes it possible for tools to generate code, saving development time.
REST, which stands for Representational State Transfer, is a more open approach, providing lots of conventions but leaving many decisions to the person designing the API.
REST and SOAP don't necessarily compete, however, since they tend to apply to varying use cases. You're likely to see REST in scenarios where simplicity, efficiency, and scalability are prioritized, as well as public APIs like AI modules third-party developers can deploy on their own websites and apps. Meanwhile, SOAP, with its more rigid rules and standards, may be preferred for enterprise-level applications where standardized messaging, security, and transactions are essential, such as transferring sensitive customer data between separate financial institutions.
Throughout this course, you may have noticed we've had an inclination for REST APIs. The preference is largely due to REST's incredible rate of adoption. This is not to say that SOAP is evil; it has its strong points. However, the focus of our discussion will stay on REST as this will likely be the kind of API you encounter. In the remaining sections, we will walk through the components that make up a REST API.
How REST API works
Back in Chapter 2, we talked a little bit about resources. Recall that resources are the nouns of APIs (customers and pizzas). These are the things we want the world to be able to interact with through our API.
To get a feel for how a company would design an API, let's try our hand at it with our pizza parlor. We'll start by adding the ability to order a pizza.
For the client to be able to talk pizzas with us, we need to do several things:
- Decide what resource(s) need to be available.
- Assign URLs to those resources.
- Decide what actions the client should be allowed to perform on those resources.
- Figure out what pieces of data are required for each action and what format they should be in.
Step 1: Picking resources
Picking resources can be a difficult first task. One way to approach the problem is to step through what a typical interaction involves. For our pizza parlor, we probably have a menu. On that menu are pizzas. When a customer wants us to make one of the pizzas for them, they place an order. In this context, menu, pizza, customer, and order all sound like good candidates for resources. Let's start with order.
Step 2: Assigning URLs
The next step is assigning URLs to the resource. There are lots of possibilities, but luckily REST conventions give some guidance. In a typical REST API, a resource will have two URL patterns assigned to it. The first is the plural of the resource name, like /orders
. The second is the plural of the resource name plus a unique identifier to specify a single resource, like /orders/<order_id>
, where <order_id> is the unique identifier for an order. These two URL patterns make up the first endpoints that our API will support. These are called endpoints simply because they go at the end of the URL, as in http://example.com/<endpoint_goes_here>
.
Step 3: Deciding client actions
Now that we picked our resource and assigned it URLs, we need to decide what actions the client can perform. Following REST conventions, we say that the plural endpoint (/orders
) is for listing existing orders and creating new ones. The plural with a unique identifier endpoint (/orders/<order_id>
) is for retrieving, updating, or canceling a specific order. The client tells the server which action to perform by passing the appropriate HTTP verb (GET, POST, PUT or DELETE) in the request.
HTTP verb | Endpoint | Action |
---|---|---|
GET | /orders | List existing orders |
POST | /orders | Place a new order |
GET | /orders/1 | Get details for order #1 |
GET | /orders/2 | Get details for order #2 |
PUT | /orders/1 | Update order #1 |
DELETE | /orders/1 | Cancel order #1 |
Step 4: Identifying data to exchange
With the actions for our order endpoints fleshed out, the final step is to decide what data needs to be exchanged between the client and the server. Borrowing from our pizza parlor example in Chapter 3, we can say that an order needs a crust and toppings. We also need to select a data format that the client and server can use to pass this information back and forth. XML and JSON are both good choices, but for readability sake, we'll go with JSON.
At this point, you should pat yourself on the back; we have designed a functional API! Here is what an interaction between the client and server might look like using this API:
Linking resources together
Our pizza parlor API is looking sharp. Orders are coming in like never before. Business is so good, in fact, we decide we want to start tracking orders by customer to gauge loyalty. An easy way to do this is to add a new customer resource.
Just like with orders, our customer resource needs some endpoints. Following convention, /customers
and /customers/<id>
fit nicely. We'll skip the details, but let's say we decide which actions make sense for each endpoint and what data represents a customer. Assuming we do all of that, we come to an interesting question: how do we associate orders with customers?
REST practitioners are split on how to solve the problem of associating resources. Some say that the hierarchy should continue to grow, giving endpoints like /customers/5/orders
for all of customer #5's orders and /customers/5/orders/3
for customer #5's third order. Others argue to keep things flat by including associated details in the data for a resource. Under this paradigm, creating an order requires a customer_id
field to be sent with the order details. Both solutions are used by REST APIs in the wild, so it is worth knowing about each.
Searching data
As data in a system grows, endpoints that list all records become impractical. Imagine if our pizza parlor had three million completed orders and you wanted to find out how many had pepperoni as a topping. Sending a GET request to /orders
and receiving all three million orders would not be very helpful. Thankfully, REST has a nifty way of searching through data.
URLs have another component that we have not mentioned yet: the query string. Query means search and string means text. The query string is a bit of text that goes onto the end of a URL to pass things along to the API. For example, everything after the question mark is the query string in http://example.com/orders?key=value
.
REST APIs use the query string to define the details of a search. These details are called query parameters. The API dictates what parameters it will accept, and the exact names of those parameters need to be used. Our pizza parlor API could allow the client to search for orders by topping by using this URL: http://example.com/orders?topping=pepperoni
. The client can include multiple query parameters by listing one after another, separating them by an ampersand ("&"). For example: http://example.com/orders?topping=pepperoni&crust=thin
.
Another use of the query string is to limit the amount of data returned in each request. Often, APIs will split results into sets (say, 100 or 500 records) and return one set at a time. This process of splitting up the data is known as pagination (an analogy to breaking up words into pages for books). To allow the client to page through all the data, the API will support query parameters that allow the client to specify which page of data it wants. In our pizza parlor API, we can support paging by allowing the client to specify two parameters: page and size. If the client makes a request like GET /orders?page=2&size=200
, we know they want the second page of results, with 200 results per page, so orders 201-400.
Chapter 6 recap
In this chapter, we learned how to design a REST API. We showed the basic functions an API supports and how to organize the data so that it can be easily consumed by a computer.
The key terms we learned were:
- SOAP: API architecture known for standardized message formats
- REST: API architecture that centers around manipulating resources
- Resource: API term for a business noun like customer or order
- Endpoint: A URL that makes up part of an API. In REST, each resource gets its own endpoints
- Query string: A portion of the URL that is used to pass data to the server
- Query parameters: A key-value pair found in the query string (topping=cheese)
- Pagination: Process of splitting up results into manageable chunks
Next
In the next chapter, we explore ways to make the client react to changes on the server in real time.
Published in April 2014; last updated January 23, 2024
Previous chapter:
Next chapter: