423 likes
·
179.8K reads
44 comments
This can be a great and very helpful checklist! Can I have you permission to translate this article into Chinese and put in my Wechat official account?Please let me know if this is ok.
Hey LE Xie! I love that you're considering translating my article into Chinese – I'd be more than happy. ❤️🔥 Please just make sure to attribute my original article and link back to my blog. Let me know once you publish it – looking really forward. :)
Thank you for your permission! Of course, your blog and original article will be put into Chinese translations. Here is the article url. mp.weixin.qq.com/s/v6BO_E8e-oJRazuYEEpksA
LE Xie awesome, thanks so much for translating the post! 🥳
- API keys can be easily stolen and distributed. You should use OAuth2 for securing access to your api endpoints
- expanding objects can lead to security issues. Attackers can run queries that take up significant system resources. Such a query can disrupt your service. Attackers can access sensitive information from a clever join.
Otherwise, nice blog post
Thank you for your feedback Christos Matskas!
I'm not sure if I agree whether expanding resources can lead to security issues. It's typically a responsibility of the API not to disclose any sensitive information from the database. If you're not transferring database objects directly (which you probably shouldn't), I don't see a big problem.
What do you think?
Awesome tips Ronald! Bookmarking this one for when I get deeper into the BE and have to think more seriously about API design!
Thank you Annie 🦄⚡! I'm glad you found this post useful. 🙂
Great Article, so many things I didn't know.
Thank you!
Thanks Ezequiel E. Tejada! Happy to help. 🤗
Great tips ! Regards
Thank you Ronald. PS: Great name! 😉
This is really a good and useful article, everyone should read this before creating an API! Congrats 🎉
Thank you for your kind words, Yannick. 🤗
Great Tips! I just finished building a small API for a project, but I missed something as small as a health check, which looking at it further, is super important for this API. Awesome
Thank you so much, Jackson Lee! 🤗 I appreciate the kind words and I'm happy you could use some of the tips for your project. If you have any questions, just let me know.
This is a nice list! I have found that a good number of these points are covered by Microsoft’s OData standard (which hasn’t caught on in circles beyond Microsoft’s sphere of influence).
Thank you Rohan Ankarigari Boda. You are right, OData already covers some of these. Although I have a feeling that OData never really got to the point where it would make sense for me to support it.
Have you ever implemented OData?
Ronald Blüthl Yes, I have implemented OData APIs as part of my work on Microsoft’s Graph API. The Microsoft Graph API platform is perhaps the largest OData based set of APIs.
The biggest challenge I faced was implementing OData APIs for data and contracts which didn’t exactly fit into the OData way of things. Another challenge was the fact that the OData libs are not ready for a microservices world (IMO) where data resides in some service and data is surfaced by another service.
In my personal projects I have been lucky not to use OData.
Great article !
Do you have any recommandations on how to implement resource expansions/field selection with Sprint Boot ? I took a look at github.com/Cosium/spring-data-jpa-entity-g… which provides a way to fetch relationships at runtime but is only half of the problem.
Hey Simon Espigolé, happy you liked my post. I'm not familiar with Spring Boot, but the principle is usually the same. If you're using an OR mapper (such as Prisma for example), you can "include" or "expand" related entities and load them from the database in one go.
The flow would roughly look like this:
- API accepts an
expand
parameter for GET requests - The expand parameter is interpreted and passed to the OR mapper
- Entities are loaded from the database and passed back as response
Check out the Prisma documentation for more details: prisma.io/docs/concepts/components/prisma-…
If you have any questions, just let me know.
Thanks for your answser Ronald Blüthl. I'm familiar with the concept of resource expansion and how to do it but I'm struggling with the implementation with Spring Boot/Hibernate, especially with lazy-loaded entities (where I only want to join the tables that the client has requested via ?expand=
).
Anyway, thanks for the link to Prisma, I didn't know this ORM. Have a nice day !
Great article. Saved it for my future projects. Thank you!
Glad you liked it, Xuan Nguyen! Thanks for reading. :)
All reasonable suggestions except the versioning bit. Perhaps every long while you replace one api with another. In that case you either keep supporting to old one or force clients to move to the new one.
But while you have an api you have to keep your interfaces constant, support all the old signatures and add new ones as necessary.
Thanks for your feedback, Robert!
Versioning could be a separate topic in itself I guess. As aways, there are many approaches I'd say. :)
A valuable checklist to follow. Really helpful content man.
That's awesome to hear, Saikat! Glad you enjoyed the post.
Thank you, Ronald, for sharing. Definitely bookmarking this!
Happy to help, Chinwendu. :) Thanks for your valuable feedback, I appreciate it.
Useful!
Thank you very much, Héctor!
Great article Ronald!. Is there any free public API out there that you think that has a good design? I need it as a reference. Many thanks
Thank you, Afdallah! 🥳 I‘m thinking about putting together a reference implementation myself, but in the meantime I recommend you to look at Stripe‘s API, which is probably the best one I‘ve worked with: stripe.com/docs/api
Hope this helps! ✌️
Discovered some new things about API design. Interesting read I must say.
Love to hear that the post was helpful to you, Aisha! ✌️
I'm in a bootcamp periode, after I read this article , honestly, work without something that not followed by standarization will make development phase getting long, I hope can implement this one on my next project, Thank you to share this 👍👍
It‘s so nice to hear that you can benefit from my article, Ilyas! 🙂 All the best to you, and if you have any questions just let me know. ✌️
It's hard to disagree with any of the bullets, but I think the most important of them is to be consistent. It will help both API consumers and the API developer(s).
Great article !
I totally agree. It's the most important part - that's why it's #1. :) Thanks for your kind words!
That was a nice read, thanks Ronald!
I have a question regarding point 6, why prefer a custom header for passing api keys when we could use standard Authorization header with bearer scheme?
Hey Jamarob! I'm happy you liked the post - thank you. 😎
You could definitely do that - I think there's no "convention" here, just best practices.
What I usually do is use the "Authorization: Bearer {token}" format when passing JWT tokens, but use the "Api-Key: {apiKey}" format when passing API keys. It's more like a matter of taste I guess.
thank you ! What method should we use for requests that neither return ( GET ) nor receive ( POST ) anything? For example, the endpoint of follow user Sorry, I can not speak English well
Hey abdolrahman kiany!
Thanks for your question. POST
doesn‘t necessarily imply that the endpoint needs to return something. It merely implies that something is written or changed instead of read.
So in your case (following a user) I‘d go with something like.
POST /users/{id}/follow
POST
because something is WRITTEN (e.g. following a user, which triggers a change in your database){id}
of the user that is subject to be followed- And then
follow
to explicitly specify the action
Of course it depends a bit on your current structure, but something along those lines should work just fine.
Hope that helps – reach out to me via Twitter (@rbluethl) if you need any more help.