AsyncAPI is a standard for documenting contracts for asynchronous APIs. Let’s say, you connect multiple services via Apache Kafka or RabbitMQ, AsyncAPI is there to provide information about available servers, topics, queues and payload structures. If you already heard about „OpenAPI“ before: AsyncAPI is the counterpart for asynchronous APIs.
Main Concepts
The four main concepts in AsyncAPI are Server, Producer, Consumer and Channel.
As I introduced this blog article by mentioning two concrete messaging systems, you might be irritated by the term Server now – at least I was :). The reason for this confusion is that AsyncAPI is not limited to APIs that build on top of messaging systems but also supports client/server models as it is known from WebSockets.
Producers are components which create and send data. Consumers receive and process exactly that data from the server. Channels are a concept of organizing different types of messages into separate units – like directories on a file system.
To get a little bit more concrete, just imagine an online payment service just like PayPal. It has a User Accounts Service which publishes events when users sign up or sign out. A Newsletter Service wants to know both about sign ups and sign outs in order to maintain its own user database. The invoice Service needs to know about sign outs, because this should send back the remaining credits of a user.
AsyncAPI Definition File
AsyncAPI definitions are YAML or JSON files. The top-level sections servers and channels refer to AsyncAPI’s main concepts already mentioned above. The other two terms from the main concepts, Producer and Consumer do not occur in the AsyncAPI document.
asyncapi: 2.5.0 info: title: SuperPay version: '1.0.0' servers: production: url: rabbitmq.superpay.com protocol: amqp description: This is SuperPays central RabbitMQ production deployment. security: - user-password: [] channels: signups: bindings: amqp: is: routingKey exchange: name: myExchange type: topic durable: true autoDelete: false bindingVersion: 0.2.0 publish: description: When a user signs up, a message MUST be published on this channel. message: $ref: '#/components/messages/signup-msg' subscribe: message: $ref: '#/components/messages/signup-msg' signouts: publish: message: $ref: '#/components/messages/signout-msg' subscribe: message: $ref: '#/components/messages/signout-msg' components: messages: signup-msg: name: Signup message summary: >- Informs about a new user has signed up in the system. payload: type: object additionalProperties: false properties: id: type: integer fullName: type: string email: type: string format: email age: type: integer minimum: 18 signout-msg: name: Signout message summary: >- Informs about a user signed out the system payload: type: object additionalProperties: false properties: userId: type: integer securitySchemes: user-password: type: userPassword
Components is just a container for re-useable snippets of the definition file. In the example snippet above, I re-used the payload definition for signup messages by referencing it from channels/signups/publish
and channels/signups/subscribe
with $ref: '#/components/messages/signup-msg'
.
How does AsyncAPI integrate protocol-specific concepts?
A client that should consume data from Apache Kafka needs to know the name of the topic that holds the data. In another scenario, it might not be Kafka but RabbitMQ. Now, there are no topics but queues and exchanges, because, although they are both message brokers, the protocols used under the hood are different.
AsyncAPI integrates these protocol/broker-specific data via so-called bindings. Examples for available bindings are AMQP, JMS, Kafka, NATS, Google Pub/Sub, AWS SQS or WebSocket.
Tooling
Just to get hands dirty as fast as possible, I recommend AsyncAPI Studio (beta). By combining a text editor and a live html documentation generator, it is a good starting point with a low entry barrier to start fiddling with your first AsyncAPI document.
While AsyncAPI Studio might serve as a good starting point, there will rise more advanced requirements when you start using AsyncAPI in your project. The following list contains just a few examples.
- Code-first tools
- Create AsyncAPI Documents via code
- Code Generators
- Generate a html or markdown documentation
- Generate project stubs in several platforms (spring, node, python, Typescript…. )
- Generate just payload data models for your programming language
- Converters
- Migrates AsyncAPI documents from older to newer versions
- Formatters
- Validators
More related tools can be found here.
Data Model Generator: Modelina
Right now, Modelina allows you to quickly generate data models for TypeScript, Java, Go, Javascript and C#. The tool is available as an npm
package and can be installed via npm install @asyncapi/modelina
. Similar to AsyncAPI Studio, a handy browser-based instance is available here. Side note: Modelina is not limited to AsyncAPI. OpenAPI and JSON Schema documents are also supported inputs.