Skip to content

Free your HTTP API. Misconceptions are holding you back!

Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.

Learn more about Software Architecture & Design.
Join thousands of developers getting weekly updates to increase your understanding of software architecture and design concepts.


We all get caught in the trap of following various practices because everyone else is and seems like an industry standard. So here are three HTTP API Misconceptions that will make you start thinking about your system and other best practices you’re applying.

YouTube

Check out my YouTube channel, where I post all kinds of content accompanying my posts, including this video showing everything in this post.

Custom Headers

The first of the HTTP API Misconceptions is about custom headers. This is a great example of just following the herd and assuming that because everyone else does it “this way”, then that’s how we should do it.

Let’s say you wanted to add a custom header to the response of your HTTP API. You’ve probably done this or used an HTTP that defined their headers this way. Specifically, they prefix it with X-

That’s probably familiar. But why? Because over 10 years ago that was generally the way, and the trend continues, even though the “current best practice” is not to. Check out RFC 6648 from 2012.

Historically, designers and implementers of application protocols have often distinguished between standardized and unstandardized parameters by prefixing the names of unstandardized parameters with the string “X-” or similar constructs. In practice, that convention causes more problems than it solves. Therefore, this document deprecates the convention for newly defined parameters with textual (as opposed to numerical) names in application protocols.

https://datatracker.ietf.org/doc/html/rfc6648

The point is that standards evolve and change, but because there’s often momentum with them, they continue for no good reason. There’s evolution and change, and just because everyone is following along, doesn’t mean that it necessarily even makes sense anymore or should be a “best practice”. I put “best practice” in quotes because I think the term is one of the biggest scams in software development.

What else are you doing in your own systems that you believe are best practices, but might not be?

CRUD

One of the most common HTTP API Misconceptions is believing that you need to use HTTP Methods (they aren’t verbs!) to map to CRUD (Create, Read, Update, Delete). Further to that is that a resource is represented by an Entity or, as some think of, a record or document in a database.

I call this type of HTTP API design Entity Services, and Alex Moore, many years ago, called these Objects Resources.

We’ve all seen this evangelized where HTTP methods map to CRUD operations.

GET is to SELECT and return an entity. POST is to create/insert an entity. PUT is a full update to an entity. PATCH is a partial update to an entity, and DELETE maps directly.

As an example, the push for having structured URIs around the Entities.

This means you’re driving your API by nouns and CRUD. This is, from what I can tell, the most standard way in the industry to develop a “REST” API (more quotes… you get my sarcasm. You’ll notice I generally use HTTP API instead for this exact reason).

Why is this a misconception? Because everyone follows it, however, it does not at all have to be this way. Especially if developing a system that’s behavior-driven. Sure, if you’re writing CRUD-style systems or parts of your system are, sure, this can absolutely work. But it will not at all work where you’re trying to capture intent.

HTTP Methods aren’t directly related to CRUD. Nor do they have to be. Resources do not be entities or documents in your database.

A good example of your API not being CRUD is Stripes Payment Intents. These are specific actions that don’t map to entities or CRUD.

Confirming a payment intent isn’t performing a PATCH or PUT (Update) on a database record to update a property/column. It’s something very specific that needs to be explicit.

Don’t get hung up on that you need to make your resources entities and map to CRUD. Resources can be whatever you want them to be.

The target of an HTTP request is called a “resource”, whose nature isn’t defined further; it can be a document, a photo, or anything else. Each resource is identified by a Uniform Resource Identifier (URI) used throughout HTTP for identifying resources.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web

There’s way too much bikeshedding around URI structures. Can they matter? Yes, if you’re developing a URI-driven API (cough, alternative being hypermedia), but don’t get hung up too much on it thinking you can’t have action-specific URIs that are explicitly based on behaviors.

Versioning

There are all kinds of strategies for versioning an HTTP API. One common approach is versioning using the URI.

https://my.app/v1/orders then becomes https://my.app/v2/orders

The issue with this approach is you’re versioning your entire API together for what could be minimal change to just one URI.

Another approach is to use a custom header to define, when making a request, which version of the API you’re requesting.

Similarly, you can also use the existing defined Accept header to specify a custom vendor type.

Or, the less often taken approach, which I advocate for, is… don’t version.

You may think this sounds crazy because you need to version because you’re going to make breaking changes. I get it. But realize that when you make breaking changes, you’re putting all the burden on your consumers. Depending on your change, it might be worth it. But it’s seriously something to think about, especially if your consumers are your customers.

You can make backward-compatible changes in a lot of situations. Adding additional properties shouldn’t break consumers. For both requests and responses, it shouldn’t break consumers. If you add a new property to a request, it should be optional. If not provided by the consumer/client, then have a default value. This is no different than if you were adding a new column/property to a table/document in a database.

Check out my post Want to build a good API? Here are 5 Tips for API Design. that specifically talks about responses and using Hypermedia as way to evolve your API.

HTTP API Misconceptions

There are a lot of perceived industry standards that aren’t actually standards anymore, or they fit best within a specific context. Too often, we get into the dogma of following certain patterns or practices when we really don’t know why or what problems the solution solves or if we even have that problem, to begin with. Understand the patterns or practices you are using, if they are still relevant, and if they solve a problem that you actually have.

HTTP API misconceptions are probably the most common in our industry, but looking at what they are can hopefully give you a glimpse into other patterns or practices you might be applying by just taking a step back to look.

Join CodeOpinon!
Developer-level members of my Patreon or YouTube channel get access to a private Discord server to chat with other developers about Software Architecture and Design and access to source code for any working demo application I post on my blog or YouTube. Check out my Patreon or YouTube Membership for more info.

Leave a Reply

Your email address will not be published. Required fields are marked *