
Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

Imagine the Twitter API. You can use it to post, get, and even delete tweets. The Twitter API is an example of an external API. It's provided by a third-party service, Twitter, that allows us to interact with their service programmatically.
We need a way to interact with the Twitter API. How we do that is where API design comes in.
In this post, we'll focus on the basics of API design.
When designing an API, we often talk about CRUD operations. CRUD stands for Create, Read, Update, and Delete. These are the basic operations that we can perform on a resource.
Often, it'll be helpful to think about the operations as functions, e.g., createTweet, getTweet, updateTweet, deleteTweet.
However, in REST APIs, the HTTP methods dictate the operation. POST is used to create a resource, GET is used to read a resource, PUT is used to update a resource, and DELETE is used to delete a resource.
A resource is an object or representation of something with data associated with it. For example, a user is a resource, and a user's name, email, and address are data associated with that resource.
Referring back to the Twitter example, a Tweet is a resource. A Tweet has data associated with it, like the tweet's content, the user who posted the tweet, and the timestamp when the tweet was posted.
When designing an API, we need to consider how it will be used and evolve over time. We can't simply change it whenever we want. Once an API is released and used, we need to be careful about making changes. We need to maintain backward compatibility so existing clients can continue using the API without any issues.
Let's say we have createTweet(userId, content) API for creating a tweet.
In REST, it'd look something like https://api.twitter.com/tweets with a POST request.
We want to add a feature where users can reply to a tweet. We can't simply add another field like parentId to the createTweet API. It wouldn't be backward compatible. We could make the field optional to maintain backward compatibility, but that's not a good design. It's not a good design because it's not clear that the parentId field is for replying to a tweet.
But, you can imagine a different scenario where introducing an optional field is a good design not to break existing clients.
Instead, we could create a new API like createReply(userId, content, parentId).
In REST, it'd look something like https://api.twitter.com/replies with a POST request.
If we have to introduce breaking changes, we can version our API. We can have different versions of our API running simultaneously. This way, existing clients can continue to use the old version, and new clients can use the new version.
For example, the Twitter API might look like https://api.twitter.com/v1/tweets for version 1 and https://api.twitter.com/v2/tweets for version 2. Existing clients can continue to use v1, and new clients can use v2.
Let's take a look at what a Tweet may look like:
{
id: string
userId: string
content: string
createdAt: Date
likes: int
}
If the user wants to create a tweet, they'd send a POST request to https://api.twitter.com/tweets with the following payload:
{
userId: "123",
content: "Hello, world!"
}
They would only need to pass the userId and content fields. The id, createdAt, and likes fields would be generated by the server.
It's important to understand that not everything in a resource needs to be passed in the request. Some fields should be generated by the server.
What if we wanted to get a specific tweet?
We could make a GET request to https://api.twitter.com/tweets/:id, where :id is the ID of the tweet. It would look something like https://api.twitter.com/tweets/123.
To the same endpoint, we could make a DELETE request to delete the tweet.
What if we wanted a specific user's list of tweets?
We could make a GET request to https://api.twitter.com/users/:userId/tweets, where :userId is the ID of the user. It would look something like https://api.twitter.com/users/123/tweets.
What happens if the user has thousands of tweets?
It would be inefficient to return all the tweets at once. Instead, we can use pagination. We can limit the number of tweets returned per page and provide a way to get to the next page of tweets.
This is where query parameters like limit and offset come in. We could make a GET request to https://api.twitter.com/users/123/tweets?limit=10&offset=0 to get the first 10 tweets, and https://api.twitter.com/users/123/tweets?limit=10&offset=10 to get the next 10 tweets.
limit specifies how many tweets to return, and offset specifies where to start fetching the tweets.
Internally, we may order the tweets by createdAt in descending order to get the latest tweets first.
GET and PUT requests are supposed to be idempotent, meaning they should not have any side effects.
POST and DELETE requests are not idempotent. They can have side effects. For example, making the same POST request multiple times will create multiple resources.
The most important points to remember when designing an API are:
Keep your API backward compatible.
Make sure your API is idempotent where it should be.
Endpoints should be intuitive and easy to understand.
Use query parameters for filtering, sorting, and pagination.
Use nouns for resources and HTTP methods for operations.
If you have to introduce breaking changes, version your API.