Message-based APIs
Tags: api, messaging
Published: 2017-07-07 20:10:55

---
title: Message-based APIs
published: true
description: For APIs that have behavior rather than state.
tags: api, messaging
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ug0rl27c0rs6ztx8hery.jpeg
---

REST APIs seem to have taken over dev mindshare. I believe part of that is how well they map to already-understood concepts like databases. Databases tables are nouns, REST resources are nouns. Databases have 4 manipulation operations INSERT, SELECT, UPDATE, DELETE; REST has 4 HTTP verbs POST, GET, PUT, DELETE. Also known as [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete).

While REST APIs are a great alternative to direct database access for untrusted clients, they are often an [uncomfortable fit](https://softwareengineering.stackexchange.com/questions/323415/how-to-design-a-rest-api-to-handle-non-crud-operations) for application APIs. Trying to use them in this way ends up causing the same issues as trying to use a database as your integration point. See [Integration Database](https://martinfowler.com/bliki/IntegrationDatabase.html).

> By application APIs, I mean APIs which are not just CRUD wrappers over a database. There is some business logic involved that goes beyond checking for blank strings.

Application APIs often need to handle use cases or user stories which cross multiple "resources". Much like the Integration Database, when you model this in REST, the client has to know all the resources to touch plus handle failures along the way. In other words the client becomes responsible for use case handling. In practice, I often see "REST" operations on the server affecting other resources and performing other side effects because it is too inconvenient to let the client manage this. The problem is that now the operation has non-obvious side effects. Like triggering an email. It makes what is supposed to be a general operation not really reusable for other purposes.

***Ok, enough background.***

To avoid these issues, for a little while now I have been developing [message](http://www.enterpriseintegrationpatterns.com/patterns/messaging/Message.html)-based APIs. In this kind of API, the client simply constructs a message (commonly a class that gets serialized to a wire format like JSON), and sends it to an API endpoint. It is similar to RPC except that the arguments are packaged into a first-class concept - a message - which represents a use case. An HTTP message API endpoint might look like this.


    /api/{message_type}


The `{message_type}` is often something like a class name. Some possible examples of calls to this API.


    POST /api/Register
    POST /api/BulkRegister
    POST /api/CancelRegistration
    POST /api/StartCourseMaterial
    POST /api/GradeExam

    GET /api/SearchRegistrations
    GET /api/SearchCompletions


As you can see, each of these messages expresses its intent. On the server, I read the name of the message from the URL. With the name I lookup a) how to parse the request into an object and b) the function to handle that message and generate a response. The handling function may read multiple entities or other APIs. It may also write to multiple places, send emails, etc. Whatever it needs to fulfill the use case. Since this is not directly exposing database tables as endpoints, _a message-based API can be completely decoupled from the back-end data structure_.

> Messages as a first-class concept also leads to some interesting scalability options as your project grows. For example, messages can be queued or routed to other nodes.

Permissions are also pretty nice in this setup. Literally read the name of the message from the request URL, see if that item exists in the user's permission list. Since these operations are specific to the business logic, not to database operations, they are exactly scoped to the business needs. For example the business may want Instructors to be able to create courses, but without being able to set certain administrative parameters. I can make a message for CreateCourse with all options and CreateLimitedCourse with limited options. I have to write code for these different cases anyway!

> Following the [CQS principle](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation), I also tend to categorize messages intended to produce side effects as Commands and messages asking for data as Queries. But that is just a further refinement to Messaging.

And by the way, there is nothing preventing you from using a REST endpoint for your CRUD operations and a message-based endpoint for behavioral operations.

_Dive deeper into messaging in [Part 2](https://dev.to/kspeakman/message-based-api-part-2-67c)._