Designing APIs for Humans: Design Patterns ![rw-book-cover](https://res.cloudinary.com/practicaldev/image/fetch/s--Eco_yODz--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjxokgtpw9orgvx9dgms.jpg) ## Metadata - Author: [[DEV Community]] - Full Title: Designing APIs for Humans: Design Patterns - Category: #articles - Document Note: --- tags: - #api-design - #developer-experience - #product-design Author: Paul Asjes Source: DEV Community (Stripe series) Reference: https://dev.to/stripe/designing-apis-for-humans-design-patterns-5847 date created: 2025-08-22 00:00 --- # Title: Designing APIs for humans: Design patterns ## Table of Contents: - [📚 References](#-references) - [📝 Summary](#-summary) - [📖 Main Content](#-main-content) - [🗒️ Notes](#-notes) - [📖 References](#-references-1) - [🗣️ Paraphrase](#-paraphrase) - [📰 Newsletter](#-newsletter) - [✅ Action Items](#-action-items) - [🧪 Hypotheses](#-hypotheses) - [📊 Methodology](#-methodology) - [❓ Questions](#-questions) - [🔮 Future Research](#-future-research) - [💡 Implications](#-implications) - [🧠 Learning Styles Assessment](#-learning-styles-assessment) - [📊 Accessibility Assessment](#-accessibility-assessment) - [🌍 DEIB (Diversity, Equity, Inclusion, and Belonging) Assessment](#-deib-diversity-equity-inclusion-and-belonging-assessment) - [✅ Logical validity](#-logical-validity) - [🔍 DARVO Analysis](#-darvo-analysis) - [🔍 SEO Evaluation](#-seo-evaluation) - [🎯 Conclusion](#-conclusion) ### References: - “Previously in this series I’ve argued that we should design our APIs with the humans that use them in mind… the API is part of the product” (0%) - “Understanding your humans… keep three things in mind” (8%) - “Who is the intended audience?” (17%) - “How customizable do you want the API to be?” (25%) - “You want to be somewhere in the middle…” (33%) - “How much accessibility are you willing to give up for customizability?” (42%) - “Be consistent” (50%) - “Now imagine the frustration if you were able to list PaymentIntents, but not other resources” (58%) - “Be intuitive… Customer resource object” (67%) - “This is a simple request… absence as a request to unset both values” (75%) - “Designing APIs for Humans… next article” (83%) - “About the author… Paul Asjes” (92%) Note: Percentages indicate approximate positions within the article’s progress as clickable references above. ## 📝 Summary: The article argues that API design patterns should center humans, not just technical correctness. Before coding, designers should clarify the intended audience, strike a balance between power and accessibility, and decide how much customizability to allow without sacrificing intuitiveness. Two core patterns are emphasized: consistency (predictable endpoints and behaviors like list endpoints for all resources) and intuition (APIs should “do what users mean,” e.g., partial updates should not unset unspecified fields). The piece concludes by positioning the API as a first-class part of the product that can drive adoption or abandonment. ## 📖 Main Content: The author frames API design as product design. If developers can’t make meaningful progress in 30 minutes, you may lose them—so human-centered patterns are crucial. - Understanding your humans - Intended audience: Are you targeting power users, juniors, or niche enterprise developers? Your audience dictates opinionated simplicity versus specialized constructs. - Customizability vs. accessibility: More options increase power but also complexity, raising learning curves and integration risk. - Start simple: Begin near the accessible side; you can add complexity later but can’t easily go the other direction. - Choosing the middle ground - Aim for a “happy path” that covers most use cases, with room for power users. - Avoid brittle designs that force early, irreversible complexity. - Be consistent - Provide predictable patterns across resources (e.g., GET one, list many, POST create/update). - Include list endpoints for all resources, not just some, to avoid rate-limit and operational pain. - Consistency speeds onboarding and conveys polish. - Be intuitive - Partial updates should not erase unspecified fields. - Design for common assumptions and human expectations rather than literal machine behavior. - Example: Updating a customer’s address should not unset name and email unless explicitly requested. Personal insight: - The “happy path first, extensibility second” approach pairs well with progressive disclosure: novices see a clean surface; experts discover advanced parameters and webhooks as needed. In the WordPress and open source ecosystems, this mirrors offering high-level, opinionated SDKs alongside lower-level REST endpoints for power users. - The partial update example suggests supporting PATCH semantics or explicit null/unset operations to avoid accidental data loss. ### 🗒️ Notes - API = part of the product (0%) - Developer time-to-first-success is a key metric. - Great APIs can elevate mediocre products; bad APIs can sink great products. - Design before code (8%) - Define audience: juniors vs. enterprise specialists. - Decide degree of customizability and acceptable complexity. - Power vs. accessibility tradeoff (25–33%) - More options increase learning curve and fragility. - Aim for a middle zone; strong “happy path.” - Start simple, evolve (42%) - Easier to add power than remove complexity later. - Avoid architecture that traps you in complexity. - Consistency patterns (50–58%) - Provide GET one, GET list, POST create/update consistently per resource. - Predictability lets users infer patterns across endpoints. - Intuition patterns (67–75%) - Partial updates should not unset fields missing from payloads. - Prefer designs that match human expectations (“it just works”). - Consider PATCH semantics, explicit nulls, or dedicated unset operations. - Closing (83%) - Promises a follow-up with Stripe patterns and points to prior parts of the series. ## 📖 References: - DEV Community article by Paul Asjes: Designing APIs for humans: Design patterns — https://dev.to/stripe/designing-apis-for-humans-design-patterns-5847 ## 🗣️ Paraphrase: 1) Original idea (0%): “APIs can make or break a product… the API is part of the product.” - Paraphrase: The quality of your API often determines product success. A clunky interface can hide an otherwise excellent product, while an elegant API can propel even average offerings. Treat your API as an integral product surface deserving the same polish. 2) Original idea (67–75%): Partial update example where unspecified fields get unset. - Paraphrase: When updating a resource, users expect only the provided attributes to change. Removing omitted fields because they weren’t included contradicts user intuition and causes data loss. Design updates to honor common expectations: leave absent fields untouched unless explicitly cleared. ## 📰 Newsletter: Developers, let’s talk APIs with a human touch. This week we’re exploring how thoughtful design patterns make or break the developer experience: define your audience, keep the “happy path” front and center, and be ruthless about consistency. If you offer GET for one resource, offer GET for lists—everywhere. And please, when we update an address, don’t nuke the name and email. Consider PATCH semantics, explicit nulls, or dedicated “unset” fields to match real-world expectations. Learning web dev? Pair these lessons with your WordPress projects: craft REST endpoints that are consistent, add progressive disclosure for advanced parameters, and document partial updates clearly to prevent accidental data loss. Community highlights: contributors are shipping smarter APIs across the ecosystem, from cleaner JSON Schema definitions to more ergonomic SDKs. New plugin radar: keep an eye out for tools that add OpenAPI specs to WordPress endpoints for automatic docs and client generation. Further reading: “Designing APIs for humans: Design patterns” by Paul Asjes on DEV. For WordPress REST best practices, see the WordPress REST API Handbook and OpenAPI Initiative for schema-driven tooling. Keep building with empathy—and ship interfaces that reduce cognitive load while scaling power for experts. ## ✅ Action Items: Prompt for aligning articles with your DevRel, open source advocacy, and OSPO trajectory: - “Analyze how this article’s API design principles advance inclusive contributor onboarding, sustainable open-source practices, and educational outcomes - Summary: Designing APIs with the humans who use them in mind is crucial for creating a successful product. When considering design patterns for APIs, it is important to understand the intended audience and how customizable the API should be. Striking a balance between power and accessibility is key, as a complex API can be frustrating to use. Consistency and intuitiveness are also vital in API design, ensuring that users can easily navigate and understand the API's functionality. Taking these factors into account early on can greatly benefit the longevity and development velocity of an API. - URL: https://dev.to/stripe/designing-apis-for-humans-design-patterns-5847?utm_source=substack&utm_medium=email Previously in this series I’ve argued that we should design our APIs with the humans that use them in mind. I've covered [object IDs](https://dev.to/stripe/designing-apis-for-humans-object-ids-3o5a) and [error messages](https://dev.to/stripe/designing-apis-for-humans-error-messages-94p) and how Stripe approaches each, but left arguably the most impactful consideration for last: design patterns. APIs are interesting because of how much they can make or break a product. Having a product that’s amazing but an API that’s incomplete, difficult to work with or outright confusing means that the vast majority of your users might never discover how great your product really is. If a developer isn’t able to make some meaningful progress within the first 30 minutes, you might have lost them forever. On the flip side, mediocre products with a great API experience are likely to outperform. The reason is quite simple: the API is part of the product, so we should treat it with the same level of attention and polish. #### Understanding your humans A great first step to getting to a great API experience is to start thinking about design patterns before you write your first line of code. When designing, you should keep three things in mind: 1. Who is the intended audience? 2. How customizable do you want the API to be? 3. How much accessibility are you willing to give up for customizability? #### Who is the intended audience? For the first point, knowing your audience is absolutely essential before committing to a design pattern. In general, APIs are intended for power users, but do you want to cater to junior developers as well? You can do so by keeping your API overly simple to interact with and make many opinionated decisions for the user. If your product is niche and only used by a subset of developers (e.g., only enterprise level developers using Java or C++), do you lean in more to their preferred object models and language constructs? #### How customizable do you want the API to be? Power and accessibility are big factors here too. A powerful API is one that gives a lot of options to its end users, like being able to customize many different factors of an API request. This comes at a cost of accessibility, as the more options available the more complex the API gets. A complex API means you’re more likely to run into walls when trying to build your integration, making it frustrating to work with. For instance you might have to make complex decisions that could have ramifications for future versions of your project, potentially without enough experience. [![Graph showing how APIs get more complex as they increase in power](https://res.cloudinary.com/practicaldev/image/fetch/s--6ARZT4er--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7u3nqeak3ui5ydr69l4.png)](https://res.cloudinary.com/practicaldev/image/fetch/s--6ARZT4er--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7u3nqeak3ui5ydr69l4.png) An API on the far left of this graph is easy to use, likely only exposes a single route and can be learned in a matter of minutes. It however is also constrained by its ease-of-use. If the end-user’s use case differs from the “happy path” devised by the API’s designers, they’re out of luck. On the far right of this graph you have a powerful API, where the user has full control of every aspect, molding the API to their exact specifications. However, it comes with a steep learning curve and is vulnerable to any future change to the API. You want to be somewhere in the middle, perhaps leaning towards a less complex API. Ideally the “happy path” is an integration path that covers nearly all of your users’ use cases, allowing some wriggle room for those power users that have a hyper-specific need. #### How much accessibility are you willing to give up for customizability? Where you sit on the graph will largely depend on that first question of who your intended audience is. Remember that while you can turn a low-power, low-complexity API into a powerful yet complex one, it’s near impossible to do the reverse without starting from scratch. Bias towards starting simple and then build up, but try to not to architect yourself into a corner that’s hard to get out of later. Figuring out your design patterns early unlocks some huge benefits that’ll help the longevity and development velocity of your API. #### Be consistent First up is consistency. Let’s start with a quick example of what I mean by that here. The most common operations for an API are usually a request to GET a resource and a POST to create or update a resource. ``` // Create a PaymentIntent POST /v1/payment_intents // Update a PaymentIntent POST /v1/payment_intents/:id // Get a specific PaymentIntent GET /v1/payment_intents/:id ``` In the above example we show a route to GET a PaymentIntent, but it only allows you to retrieve one at a time. If you need to obtain a list of PaymentIntents, then it can be quite painful to call the endpoint multiple times. This is especially true if you don’t already have a list of PaymentIntent IDs, not to mention the possibility of being rate limited if your list is too large. Adding a [“list” endpoint](https://stripe.com/docs/api/payment_intents/list) is a nice quality of life improvement here, giving the user flexibility and the ability to reduce operations into as few API requests as possible. ``` // Get a list of PaymentIntents GET /v1/payment_intents ``` Now imagine the frustration if you were able to list PaymentIntents, but not other resources like Customers. As an API designer you want your API to be as predictable as possible, allowing users to guess what combination of HTTP verbs and endpoints work based on prior experience with your API. Be strict with maintaining consistency in your design; new routes should work in largely the same way as existing ones. Not only does this allow users to ramp up much quicker in using your API, but it gives it that polished feel of a well-designed, intuitive experience. #### Be intuitive Speaking of which, let’s dive a little deeper into intuition and what that means. To illustrate, let’s pretend that we have a Customer resource object in our API that takes 3 fields: name, email and address. First we create the customer: ``` // Request curl https://api.example.com/v1/customers -u sk_test_123 -d "name"="Leto Atreides" -d "email"="[email protected]" -d "address"="1 Palace Street, Caladan" // Response { "id": "cus_123", "object": "customer", "name": "Leto Atreides", "email": "[email protected]", "address": "1 Palace Street, Caladan" } ``` Then at some later point we update the customer: ``` // Request curl https://api.example.com/v1/customers/cus_123 -u sk_test_123: -d "address"="1 Spice Road, Arrakis" // Response { "id": "cus_123", "object": "customer", "name": undefined, "email": undefined, "address": " 1 Spice Road, Arrakis" } ``` This is a simple request, just updating an existing customer’s address, but hang on, where did the values for `name` and `email` go? Well, the API did exactly as it was told to. It updated the `address` value, but since the `name` and `email` values were absent in the update request, it interpreted the absence as a request to unset both values. This is extremely frustrating, but *technically* correct and a clear indicator that this API wasn’t designed with humans in mind. Instead of checking to see if the parameter was passed in, the designers of this API updated the object with the attribute’s value, whether it was provided or not. APIs thrive on being intuitive, operations such as the above should “just work” based on the common assumption rather than a computer’s tendency to do exactly as it was told. #### Designing APIs for Humans There are many resources out there for how you should design your API, and I hope that this article gave you some food for thought and the incentive to dive deeper into this rabbit hole. In the next article we’ll cover some design patterns that we use at Stripe and why I think they warrant a closer look. I also recommend you check out the previous articles in this series to learn more about how we approach API design at Stripe. #### About the author [![Profile picture of Paul Asjes](https://res.cloudinary.com/practicaldev/image/fetch/s--om-lC9GK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ou2vfm40qzozpcozj92m.png)](https://res.cloudinary.com/practicaldev/image/fetch/s--om-lC9GK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ou2vfm40qzozpcozj92m.png) [Paul Asjes](https://twitter.com/paul_asjes) is a Developer Advocate at Stripe where he writes, codes and talks to developers. Outside of work he enjoys brewing beer, making [biltong](https://en.wikipedia.org/wiki/Biltong) and losing to his son in Mario Kart., Designing APIs for Humans: Design Patterns, DEV Community, 01h5mgc7yyfznp5gtbh769cw5c.