Introduction

The AsyncAPI specification allows you to create machine-readable definitions of your asynchronous APIs. It's protocol-agnostic, so you can use it for APIs that work over MQTT, AMQP, WebSockets, STOMP, etc. The specification is heavily inspired on OpenAPI (fka Swagger) and it's designed to maintain as much compatibility as possible with it.

Why another specification?

At Hitch we're in love with API machine-readable documentation formats (OpenAPI, RAML, etc.). We always encourage our customers to use a machine-readable definition for their APIs because it allows them to get extra benefits. From documentation and code generation to setup their own API Assistant.

Internally, we use a message-driven microservices architecture and we couldn't have all those tools that we have with the HTTP APIs. All those things you get because you have your API defined with a machine-readable documentation format. And, on top of that, at the same time we noticed that some of our customers were creating IoT APIs over MQTT and they couldn't get all the benefits from Hitch because the existing specifications don't support message-driven APIs.

It was time to come up with something good enough for everyone instead of having every company doing its own battle. We can learn a lot together if we join forces. Let's start!

A basic example

asyncapi: '1.0.0'
info:
  title: 'Sign up email example'
  version: '1.0.0'
baseTopic: 'hitch'
host: 'asyncapi.hitchhq.com'
schemes:
  - 'amqp'
  - 'mqtt'

topics:
  accounts.1.0.event.user.signup:
    subscribe:
      $ref: '#/components/messages/userSignedUp'
  email.1.0.event.email.sent:
    publish:
      $ref: '#/components/messages/emailSent'

components:
  messages:
    emailSent:
      summary: 'Email sent to user.'
      description: 'A message notifying an email has been sent.'
      payload:
        type: 'object'
        properties:
          user:
            $ref: '#/components/schemas/user'
          content:
            $ref: '#/components/schemas/content'

    userSignedUp:
      summary: 'A user has signed up.'
      payload:
        type: 'object'
        properties:
          user:
            $ref: '#/components/schemas/user'
          signup:
            $ref: '#/components/schemas/signup'
  schemas:
    content:
      title: 'content'
      description: 'The email content'
      type: 'string'
    id:
      title: 'id'
      description: 'Resource identifier'
      type: 'string'
    username:
      title: 'username'
      description: 'User handle'
      type: 'string'
    datetime:
      title: 'datetime'
      description: 'Date and Time of the message'
      type: 'string'
      format: 'date-time'
    user:
      type: 'object'
      required:
        - 'id'
        - 'username'
      properties:
        id:
          description: 'User Id'
          $ref: '#/components/schemas/id'
        full_name:
          description: "User's full name"
          type: 'string'
        username:
          $ref: '#/components/schemas/username'
    signup:
      type: 'object'
      required:
        - 'method'
        - 'datetime'
      properties:
        method:
          description: 'Signup method'
          type: 'string'
          enum:
            - 'email'
            - 'facebook'
            - 'twitter'
            - 'github'
            - 'google'
        datetime:
          $ref: '#/components/schemas/datetime'

Email service

This example describes a very basic email service. It sends an email every time a new user signs up. It subscribes for the hitch.accounts.1.0.event.user.signup event and, when received, sends the email and publishes a new message notifying the system that the email has been sent. Easy, right?

If you are familiar with the OpenAPI specification I'm sure you already found lots of similarities. But, what's this topics section in the file? And what's this accounts.1.0.event.user.signup? Let's dive into it!

Core concepts

The AsyncAPI specification is based on the assumption of 2 core concepts:

Messages

The way a consumer(s) can communicate with your API is based on messages. A message is a piece of information two or more programs exchange. Most of the times to notify the other end(s) that, either an event has occurred or you want them to perform an action.

Technically speaking the events and actions will always be sent in the same way. These are just messages and their content can be anything. So when we speak about the difference between events and actions, this is just a semantic differentiation of the content of the message. We do not enforce (although we encourage you to do it) you to make any difference between them.

A message can contain headers and a payload, however both are optional. To remain as much protocol-agnostic as possible, the specification allows you to define any kind of header.

Topics

Message-driven protocols usually contain something that can be found as topic (MQTT), routing key (AMQP), destination (STOMP), etc. To some extent, they can compare to URLs in HTTP APIs. So when you send a message to your API it will be routed depending on the topic you published on. It allows you to create APIs that subscribe to certain topics and publish to other ones.

There's no standard way of naming topics so we recommend you to have a look at our proposal here.

Tooling

Code generators

Link Description Language/Framework
https://github.com/asyncapi/node-codegen Use your AsyncAPI definition to generate the Node.js ES7 code for your API.
The generated code features:
  • ES7
  • No transpiling
  • ESLint
  • YAML config file
  • Hermes
Node.js/Hermes

The language you're looking for is not here? Please create an issue here.

Documentation generators

Link Description
https://github.com/asyncapi/docgen Use your AsyncAPI definition to generate beautiful human-readable documentation for your API. It generates documentation in HTML, CSS and JS.
https://github.com/Mermade/widdershins OpenApi 3.0 / Swagger 2.0 / AsyncAPI 1.0 definition to Slate / Shins compatible markdown. Thanks to @Permittedsoc.