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?

This project started at Hitch. We're in love with API machine-readable documentation formats (OpenAPI, RAML, etc.) and 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: Streetlights API
  version: '1.0'
  description: |
    The Smartylighting Streetlights API allows you
    to remotely manage the city lights.
  license:
    name: Apache 2.0
    url: 'https://www.apache.org/licenses/LICENSE-2.0'
baseTopic: smartylighting.streetlights.1.0

servers:
  - url: api.streetlights.smartylighting.com:{port}
    scheme: mqtt
    description: Test broker
    variables:
      port:
        description: Secure connection (TLS) is available through port 8883.
        default: '1883'
        enum:
          - '1883'
          - '8883'

topics:
  event.{streetlightId}.lighting.measured:
    publish:
      $ref: '#/components/messages/lightMeasured'

components:
  messages:
    lightMeasured:
      summary: Inform about environmental lighting conditions for a particular streetlight.
      payload:
        $ref: "#/components/schemas/lightMeasuredPayload"

  schemas:
    lightMeasuredPayload:
      type: object
      properties:
        lumens:
          type: integer
          minimum: 0
          description: Light intensity measured in lumens.
        sentAt:
          $ref: "#/components/schemas/sentAt"
    sentAt:
      type: string
      format: date-time
      description: Date and time when the message was sent.

Streetlights service

This example describes a very basic streetlights service. It says there's a service you can connect at api.streetlights.smartylighting.com (port 1883 or 8883) and it allows you to publish information about environmental lighting conditions.

Afterwards, the service might decide to turn on or off certain lights or it might simply log it for statistics. Or both! That's up to your implementation.

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 event.{streetlightId}.lighting.measured? 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 message's content. We do not enforce you to make any difference between them, although we encourage you to do it.

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.