Entities aren’t resources, resources aren’t representations

One of the easy mistakes in building a REST API is trying to take your rows out of the database and expose them directly as JSON. Such technology exists, where you can directly expose stored procedures as SOAP web services, or protocols like OData.  You can also just expose your entities directly as JSON through a web service, but you’re missing out on some big distinctions of resources and representations.

So first, what is a resource? That’s actually quite easy – a resource is anything with a URL. The converse is not true, a URL is not a resource, mainly because the URL is the Uniform Resource Locator. If you can locate a resource, then it exists. And Fielding was pleased.

The representation is a bit different – it describes the current state of the resource (when requested).

So what does this have to do with entities? Well, nothing. There is no relationship between entities and resources. And that’s a good thing, it’s exactly how the web works.

When you navigate to a web page, an online retailer, and look at a list of products, what is the resource? From the client’s perspective, we don’t know. We have no idea of the implementation details of the resource, other than a way to locate it and request a representation. Again, Fielding was pleased, as this decoupled us from the implementation details of the resource.

So where does this leave us when building APIs?

A decoupled API

In APIs that serve the client according to their needs, the resource often includes details from many different data sources, combined together to build a representation to the end user. A REST API builds all this together:


In hypermedia APIs I build, the resource state combines multiple entities together from one or more data sources into the state of the resource. This plus links, forms a queries makes a “resource”, though it’s still a bit more abstract than that. Finally I build out the representation, perhaps JSON API, HAL, Siren etc.

If I made my entities equivalent to resources, I’m likely forcing clients to make many round trips to all the entities they need, but even more, I’m directly exposing the implementation details of my service to the world. Perhaps I’m removing some fields here and there, but in reality this is only one step above handing clients a connection string to my database. Sure, it’s easy and convenient to expose entities directly as resources and representations, but there’s some serious coupling that comes with that choice that you must accept.

In my experience, if I approach the API design strictly from the client perspective, on what they’re trying to achieve and why, it’s actually quite rare that I arrive at an API design that is simply database CRUD exposed as HTTP. And Fielding was pleased, as this design most closely matches the everyday use of the web. Makes sense. That’s what REST is about – a set of architectural constraints describing basically, the web.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in REST. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Thibaud Desodt

    Some teams learned it the hard way : http://blog.nuget.org/20160216/Switching-from-WCF-OData-to-Web-API.html :)

    Thanks for another great article !

  • If OData endpoint is built on top of Entity Framework then it doesn’t necessarily mean that the exposed entities are directly mapped to database tables. The simplest example would be navigation properties witg junction tables and many to many relationships. I don’t say this is bad or good, just that on might end up with.

  • Macchendra

    OData promises everything and expects everything. I am reminded of the “IQueryableT is Tight Coupling” article. Having a version 2 of your “API” means getting every client to rewrite their code, or some serious pain if you’ve made any significant database changes. Also, if you leave no room for business logic between the database and the API client, the database is effectively the integration point for that client.