# AsyncAPI documentation

> Open source tools to easily build and maintain your event-driven architecture. All powered by the AsyncAPI specification, the industry standard for defining asynchronous APIs.

Concatenated core docs. Community and blog pages are listed under Optional in /llms.txt.

---

# Welcome
Source: https://www.asyncapi.com/docs.md

# Welcome

## Welcome to AsyncAPI Docs! 

AsyncAPI is an open source initiative that seeks to improve the current state of Event-Driven Architectures (EDA). Our long-term goal is to make working with EDAs as easy as working with REST APIs. That goes from documentation to code generation, from discovery to event management, and beyond.

## Explore the Docs

- [Concepts](https://www.asyncapi.com/docs/concepts.md): Our Concepts section defines the concepts of AsyncAPI features and capabilities.
- [Tutorials](https://www.asyncapi.com/docs/tutorials.md): Our Tutorials section teaches beginner processes with AsyncAPI, guiding you from Point A to Point B.
- [Guides](https://www.asyncapi.com/docs/guides.md): Our Guides section teaches AsyncAPI's capabilities at a high level.
- [Tools](https://www.asyncapi.com/docs/tools.md): Our Tools section documents the AsyncAPI tools ecosystem.
- [Reference](https://www.asyncapi.com/docs/reference.md): Our Reference section documents the AsyncAPI specification.
- [Migration](https://www.asyncapi.com/docs/migration.md): Our migration guides on how to upgrade to newer AsyncAPI versions.
- [Community](https://www.asyncapi.com/docs/community.md): Our Community section documents the community guidelines and resources.
- [Specification Explorer](https://www.asyncapi.com/docs/reference/specification/v3.0.0-explorer.md): Simplifying our Specification JSON Schema like a pro.

---

---

# Overview
Source: https://www.asyncapi.com/docs/concepts.md

# Overview

## Concepts

Welcome to AsyncAPI **Concepts**! This section defines AsyncAPI features and capabilities.

> **Remember**
>
> ## Contribute to AsyncAPI Concepts
> Code isn't the only way to contribute to OSS; Dev Docs are a **huge** help that benefit the entire OSS ecosystem. At AsyncAPI, we value Doc contributions as much as every other type of contribution. ❤️
> 
> To get started as a Docs contributor:
> 
> 1. Familiarize yourself with our [project's Contribution Guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md).
> 2. Head over to our [AsyncAPI Docs Board](https://github.com/orgs/asyncapi/projects/12).
> 3. Pick an issue you would like to contribute to and leave a comment introducing yourself. This is also the perfect place to leave any questions you may have on how to get started.
> 4. If there is no work done in that Docs issue yet, feel free to open a PR and get started!
> 
> ### Docs contributor questions
> 
> Do you have a question about contributing to the docs or an issue with your pull request? [Join our Slack community](https://www.asyncapi.com/slack-invite) and ask in the `#docs` channel; the maintainers will get back to you.

---

# Server
Source: https://www.asyncapi.com/docs/concepts/server.md

# Server

## What is a server?
A _server_ acts as a _messaging broker_ system, establishing connections and facilitating communication between [_producers_](producer) and [_consumers_](consumer). Unlike traditional API servers that rely on request-response interactions, message broker interactions occur bidirectionally across various channels.

## What is the purpose of servers?
Servers play a crucial role in establishing a connection between producers and consumers. In the context of designing and setting up an event-driven application, servers are responsible for delivering asynchronous messages from the producer to the consumers through the use of [_channels_](channel). Additionally, servers can integrate various messaging [_protocols_](protocol) to facilitate the transmission and exchange of messages between _clients_.

### Clients and Server
```mermaid
flowchart TD
    a[Client Browser] --> b[(server)]
    b --> a
    c[Client Mobile] --> b[(server)]
    b --> c 
```
The diagram above illustrates a bidirectional communication between one server and several clients. In this case, in your AsyncAPI file, you describe the `server`, so the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) holds information about the actual server, including its physical location.

### Broker Centric
```mermaid
flowchart TD
    A[producer]
    A --> a1[channel1]
    A --> a2[channel2]
    subgraph one[broker]
    a1
    a2
    end
    a1 --> B[consumer1]
    a2 --> C[consumer2]
```

The diagram above illustrates the Broker-centric Architecture. In this case, there are three AsyncAPI files for the `producer`, `consumer1`, and `consumer2`. In these AsyncAPI files, the [`Server Object`](https://www.asyncapi.com/docs/reference/specification/latest#serverObject) provides information about the `broker`, so that API users know where to connect to start receiving or sending messages.

---

# Producer
Source: https://www.asyncapi.com/docs/concepts/producer.md

# Producer

## What is a Producer? 
A _producer_ is an application that detects state changes (_events_) and publishes these events as messages. An event signifies a state change or update triggered by a user’s or device’s action.

The following are sample events:
* Adding an item to a shopping cart on an e-commerce website.
* Clicking the subscribe button on a YouTube channel.
* Detecting a temperature change using a sensor.

## Why do we need Producers? 
The publish/subscribe communication model is one of the core concepts of event-driven architecture. In this model, producers are publishers, acting as the first logical layer responsible for distributing messages to the broker, enabling others to subscribe and receive these messages.

```mermaid
flowchart TD
    a[Producer]-- Message 1 --->d[(Broker)]
    d -- Message 1 --->g[Consumer]
```

The diagram above illustrates the communication flow between a producer who publishes events to a specific channel in a broker and a consumer who subscribes to the same channel.

In some cases, an entity can simultaneously function as both a producer, publishing messages to a specific channel in the broker, and a consumer, subscribing to messages from a different channel in the broker.

```mermaid
flowchart LR
    a[Producer]-- Message 1 --->c[(Broker)]
    b[Producer]-- Message 2 --->c
    c -- Message 1 --> b
    c -- Message 2 ---> d[Consumer]
```

In the diagram above, there is a producer publishing messages to a specific channel and a consumer subscribing to messages from that channel. Also, there is a second producer publishing to one channel and subscribing to messages from another channel.

---

# Consumer
Source: https://www.asyncapi.com/docs/concepts/consumer.md

# Consumer

## What is a consumer?
A _consumer_ is an application that subscribes to a specific event from a broker and responds accordingly.

## Why do we need consumers?
Unlike traditional REST APIs, in Event-Driven Architecture (EDA), event consumers are asynchronous, which means they are not required to respond immediately on the same connection. In this architecture, consumers are unaware of the producers or other consumers. All they know is that when a broker sends them an event, it is because they have subscribed to it.

When you want your application to process events asynchronously, the consumer plays a crucial role in completing the event data flow through the event channel.

```mermaid
flowchart LR
    a[Producer] -- Event A --->c[(Broker)]
    a -- Event B ---> c
    c -- Event A ---> d[Consumer A]
    c -- Event A ---> e[Consumer B]
    c -- Event B ---> e[Consumer B]
    c -- Event B ---> f[Consumer C]
    subgraph Consumers
    d
    e
    f
    end
```

The diagram above illustrates a sample flow of events from the `producer` to the `broker` to the `consumers`. In this scenario, the `producer` publishes two events _(A and B)_ and sends them to the `broker`. Subsequently, each `consumer` subscribes to receive those events.

> **Remember**
>
> <b>Subscribers</b> can also be <a href="https://www.asyncapi.com/docs/concepts/producer">producers</a>.

---

# Channel
Source: https://www.asyncapi.com/docs/concepts/channel.md

# Channel

# What is a channel?
A _channel_ is a mechanism created by the server that facilitates the organization and transmission of messages. Depending on the used protocol, users can define channels as a _topic_, _queue_, _routing key_, _path_, or _subject_.

# Why do we need channels?
Channels are pivotal for establishing communication between producers and consumers. They enable producers to send messages, while consumers receive messages from specific channels. The primary function of a channel is to ensure that the intended messages reach the appropriate consumers.

```mermaid
graph LR
    A[Producer] --> B(message)
    B --> C(Channel)
    C --> D[Consumer]
    C --> E[Consumer]
    C --> F[Consumer]
```

The diagram above illustrates the communication process between a producer and multiple consumers. The producer sends a message through the channel, which then queues the message for delivery to the appropriate consumers.

---

# Application
Source: https://www.asyncapi.com/docs/concepts/application.md

# Application

## What is an application?
An _application_ is a computer program or a group of them. 

An application can be a micro-service, IoT (Internet of things) device (for example, a sensor), mainframe process, and more. Users can create applications using various programming languages that support the chosen protocols.

## Why do we need applications?
In Event-Driven Architecture (EDA), an application can either be a producer, a consumer, or both. Additionally, if an application wants to connect and exchange messages with the server, it must adhere to the protocols supported by the server.

### Applications: producers and consumers
```mermaid
flowchart TD
        A[PRODUCER application] --> B[message] 
        B --> C[channel] 
        C --> D[message] 
        D --> F[CONSUMER application]
```

The diagram above illustrates a message transmission between a Producer application and a Consumer application through a channel.

---

# Protocol
Source: https://www.asyncapi.com/docs/concepts/protocol.md

# Protocol

## What is a protocol?
A _protocol_ is a set of rules that governs the exchange of information between applications and/or servers.

Protocol examples:
* [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
* [HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
* [Kafka](https://kafka.apache.org/)
* [MQTT](https://mqtt.org/)

## Why do we need protocols?
Protocols play a crucial role in message transmission. Whenever a producer detects a state change (events) and publishes those events as messages, a protocol carries those messages to the channel and then to the consumer.

```mermaid
sequenceDiagram
    Publisher->>+Broker: PUBLISH(QoS0,Msg)
    Broker->>+Subscriber: PUBLISH(QoS0,Msg)
    Publisher->>+Publisher: Delete(Msg)
```

The diagram above illustrates the message exchange flow from `producer` to `broker` to `consumer` using the MQTT protocol with QoS0 (quality of service 0). In other words, the information transferred from the producer to broker to consumer is delivered at most once.

The quality of service information rule is defined at the protocol level. Broker implementations and other involved parties must adhere to this rule.

In AsyncAPI documents, all protocol-specific details that the application follows can be described using [bindings](https://www.asyncapi.com/docs/reference/specification/latest#definitionsBindings).

---

# Message
Source: https://www.asyncapi.com/docs/concepts/message.md

# Message

## What is a message?
A _message_ is a communication asset that transmits or exchanges information from a sender to the receiver through channels.

One message can also be defined as an event or command and can be consumed by multiple independent receivers. The sender encodes a payload of data (serialized into a suitable format, such as JSON, XML, binary, or others) that requires processing by the receiver. Additionally, the message may include _metadata_, which is information that describes the message itself. This metadata is commonly referred to as _headers_ or _properties_.

``` mermaid
graph LR
subgraph one[channel]
b([message])
end

A{{sender application}} --> b --> C{{receiver application}}
  
```

The diagram above illustrates how a sender application transmits a message through a channel to a receiver application, demonstrating the basic flow of message-based communication.

## Messages vs Events
A **message** conveys information between applications, while an **event** is a message that provides details of something that has already occurred. A crucial aspect to note is that depending on the type of information a message carries, it can either be an event, query, or command. Check the diagram below.

``` mermaid
graph TD
    A(Message)
    A --> B(Event)
    A --> C(Request)
    C --> D(Query)
    C --> E(Command)
```

Summing up, events are messages, but not all messages are events.

---

# Introduction
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document.md

# Introduction

The [AsyncAPI specification](/docs/reference/specification/latest) defines fields for describing an application's API in an *AsyncAPI document*. While the document may reference other files for details or shared fields, it typically serves as a single, primary document that encapsulates the API description.

The AsyncAPI document is a communication contract between senders and receivers within an event-driven system. It specifies the payload content required for a service to send a message and provides the receiver with guidance about the message's properties.

```yaml
asyncapi: 3.1.0
info:
  title: Cool Example
  version: 0.1.0
channels:
  userSignedUp:
    address: user/signedup
    messages:
      userSignedUp:
        description: An event describing that a user just signed up.
        payload:
          type: object
          properties:
            fullName:
              type: string
            email:
              type: string
              format: email
            age:
              type: integer
              minimum: 18
operations: 
  userSignedUp:
    action: send
    channel: 
      $ref: '#/channels/userSignedUp'
```

> **Remember**
>
> Depending on the protocol (such as MQTT, AMQP, Kafka), your AsyncAPI document may have additional fields. For example, for [configuring Kafka bindings](https://github.com/asyncapi/bindings/tree/master/kafka).

---

# AsyncAPI document structure
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/structure.md

# AsyncAPI document structure

An AsyncAPI document structure must follow a specific format defined by the [AsyncAPI specification][asyncapi-spec]. It has mandatory and optional fields.

## Root elements

Root elements of an AsyncAPI document provide an overview of the API's characteristics and behavior. These root elements define metadata, channels, components, and more.

```mermaid
graph 
A[asyncapi]
B[info]
C[servers]
D[channels]
E[operations]
F[components]

A --> B
A --> C
A --> D
A --> E
A --> F
```

### `info` field

The [`info` field][info-object] is a mandatory element of the AsyncAPI specification that serves as the initial reference point for users navigating the API documentation and helping developers, architects, and other stakeholders quickly grasp the API's purpose and capabilities. This field contains essential metadata, including:

- `title`: API title.
- `version`: API version.
- `description`: Brief description of the API's purpose and features.
- `termsOfService`: URL or document specifying the API's terms of service.
- `contact`: Contact information of the API's owner or maintainer (name, email, and URL).
- `license`: API's license information, including name and URL.
- `tags`: A list of keywords to organize and categorize API documentation. They are also used to group applications logically.
- `externalDocs`: Links to additional, external documentation related to the API.

Below is an example of the `info` field:
```yaml
info:
  title: My Event-Driven API
  version: 1.0.0
  description: This API provides real-time event streaming capabilities
  termsOfService: https://example.com/terms-of-service
  contact:
    name: Rohit
    email: rohitwashere@asyncapi.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  tags:
    - name: Events
      description: APIs related to event streaming
    - name: Authentication
      description: APIs for authentication and authorization
  externalDocs:
    description: Additional documentation 
    url: https://example.com/docs
```

### `servers` field

The [`servers` field][server-object] details various servers, including network endpoints or message brokers to which applications can connect. This field includes connection information like protocol, host, port, and other options, enabling connectivity across different environments like production, staging, or development.

The individual `servers` field contains the following properties:

- `host`: The server hostname. It may include the port.
- `protocol`: The protocol or messaging protocol that is used by the server (for example, AMQP, MQTT, WebSocket).
- `protocolVersion`: The protocol version used for the connection.
- `pathname`: The path to a resource in the host.
- `description`: A string describing the server.
- `title`: A human-friendly title for the server.
- `summary`: A brief overview of the server.
- `security`: A declaration of security schemes supported by the server.
- `tags`: a list of keywords to logically group and categorize servers.
- `externalDocs`: Additional external documentation for this server.
- `bindings`: A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the server.

Below is an example of the `servers` field with multiple servers:
```yaml
servers:
  production:
    host: rabbitmq.in.mycompany.com:5672
    pathname: /v1
    protocol: amqp
    protocolVersion: 1.0
    description: Production RabbitMQ broker (uses the `production` vhost)
    title: Production Server
    summary: Production environment server
    security:
      - type: http
        scheme: bearer
    tags:
      - name: production
        description: Production environment
    externalDocs:
      description: Additional documentation for the production server
      url: https://example.com/docs/production
    bindings:
      amqp:
        exchange: my-exchange
        queue: my-queue
  staging:
    host: rabbitmq.in.mycompany.com:5672
    pathname: /v1
    protocol: amqp
    protocolVersion: 1.0
    description: Staging RabbitMQ broker (uses the `staging` vhost)
    title: Staging Server
    summary: Staging environment server
    security:
      - type: apiKey
        in: user
        description: Provide your API key as the user and leave the password empty
    tags:
      - name: staging
        description: Staging environment
    externalDocs:
      description: Additional documentation for the staging server
      url: https://example.com/docs/staging
    bindings:
      amqp:
        exchange: my-exchange
        queue: my-queue
```

### `channels` field

With the [`channels` field][channel-object], you can provide a map of channels the application communicates with during runtime. For each channel, you can specify the purpose, address, and expected message formats so that API consumers can understand the supported message-based interactions and the corresponding data models.

The individual `channels` field contains the following properties:

- `address`: A string representation of this channel's address.
- `messages`: A map of all messages sent to this channel by any application.
- `title`: A human-readable title for the channel.
- `summary`: A summary of the channel.
- `description`: A description of the channel, providing additional context and details of the message.
- `servers`: An array of `$ref` pointers to the server definitions for this channel. If servers are absent or empty, this channel must be available on all servers defined in the `servers` field.
- `parameters`: A map of the parameters included in the channel address.
- `tags`: a list of keywords to logically group channels.
- `externalDocs`: Additional external documentation for this channel.
- `bindings`: A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the channel.

Below is an example of the `channels` field with one channel:
```yaml
channels:
  user:
    address: 'users.{userId}'
    title: Users channel
    description: This channel is used to exchange messages about user events
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
      userCompletedOrder:
        $ref: '#/components/messages/userCompletedOrder'
    parameters:
      userId:
        $ref: '#/components/parameters/userId'
    servers:
      - $ref: '#/servers/production'
    bindings:
      amqp:
        is: queue
        queue:
          exclusive: true
    tags:
      - name: user
        description: User-related messages
    externalDocs:
      description: Find more info here
      url: https://example.com
```

### `operations` field

The [`operations` field][operation-object] specifies operations the application can perform. It offers a clear and structured description detailing whether the application sends or receives messages and the specific purpose of each operation.

The individual `operations` field contains the following properties:

- `action`: Use `send` when the application expects to send a message to a channel and `receive` when it expects to receive messages from a channel.
- `channel`: A `ref` pointer to the channel definition that ensures the operation execution.
- `title`:	A human-friendly title for the operation.
- `summary`: A brief overview of the operation.
- `description`: A detailed explanation of the operation. 
- `security`:	A declaration of security schemes associated with the operation.
- `tags`: a list of keywords to logically group and categorize operations.
- `externalDocs`:	Additional external documentation for this operation.
- `bindings`: A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.
- `traits`: A list of traits to apply to the operation object. 
- `messages`: A list of `$ref` pointers to the supported Message Objects that this operation can process.
- `reply`: The definition of the reply in a reply/request operation.

Below is an example of the `operations` field with one operation:
```yaml
operations:
  sendUserSignUp:
    action: send
    title: User sign up
    summary: Action to sign a user up
    description: A longer description
    channel:
      $ref: '#/channels/user'
    security:
      - type: oauth2
        description: The oauth security descriptions
        flows:
          clientCredentials:
            tokenUrl: https://example.com/api/oauth/dialog
            availableScopes:
              'subscribe:auth_revocations': Scope required for authorization revocation topic
        scopes:
          - 'subscribe:auth_revocations'
    tags:
      - name: user
      - name: signup
      - name: register
    bindings:
      amqp:
        ack: false
    traits:
      - $ref: '#/components/operationTraits/kafka'
    messages:
      - $ref: '#/components/messages/userSignedUp'
    reply:
      address:
        location: '$message.header#/replyTo'
      channel:
        $ref: '#/channels/userSignupReply'
      messages:
        - $ref: '#/channels/userSignupReply/messages/userSignedUpReply'
```

### `components` field

The [`components` field][components-object] lets you define reusable structures or definitions across your document. Items in `components` only become part of the API when explicitly referenced by properties outside this field, so you can use it to avoid repetition and improve maintainability.

The `components` field contains the following properties:

- `schemas`: An object to hold the reusable [Schema Object][schema-object].
- `servers`: An object to hold the reusable [Server Objects][server-object].
- `channels`: An object to hold the reusable [Channel Objects][channel-object].
- `operations`: An object to hold the reusable [Operation Item Objects][operation-item-object].
- `messages`: An object to hold the reusable [Messages Objects][message-object].
- `securitySchemes`: An object to hold the reusable [Security Scheme Objects][security-scheme-object].
- `serverVariables`: An object to hold the reusable [Server Variable Objects][server-variable-object].
- `parameters`: Contains reusable [Parameter Objects][parameter-object] that can be used in various parts of the AsyncAPI document.
- `correlationIds`: An object to hold the reusable [Correlation ID Objects][correlation-id-object].
- `replies`: An object to hold the reusable [Operation Reply Objects][operation-reply-object].
- `replyAddresses`: An object to hold the reusable [Operation Reply Address Objects][operation-reply-address-object].
- `externalDocs`: An object to hold the reusable [External Documentation Objects][external-documentation-object].
- `tags`: An object to hold the reusable [Tag Objects][tag-object].
- `operationTraits`: An object to hold the reusable [Operation Trait Objects][operation-trait-object].
- `messageTraits`: Represents common traits or characteristics that can be applied to messages or hold reusable [Message Trait Objects][message-trait-object].
- `serverBindings`: An object to hold the reusable [Server Bindings Objects][server-bindings-object].
- `channelBindings`: An object to hold the reusable [Channel Bindings Objects][channel-bindings-object].
- `operationBindings`: An object to hold the reusable [Operation Bindings Objects][operation-bindings-object].
- `messageBindings`: An object to hold the reusable [Message Bindings Objects][message-bindings-object].

Here's a code example of the components object in an AsyncAPI document:
```yaml
components:

  schemas:
    Category:
      type: object
      properties:
        id:
          type: integer
          format: int64
    AvroExample:
      schemaFormat: application/vnd.apache.avro+json;version=1.9.0
      schema:
        $ref: 'path/to/user-create.avsc/#UserCreate'

  servers:
    development:
      host: '{stage}.in.mycompany.com'
      protocol: amqp
      description: RabbitMQ broker
      bindings:
        $ref: '#/components/serverBindings/devAmqp'
      variables:
        stage:
          $ref: '#/components/serverVariables/stage'
      security:
        - $ref: '#/components/securitySchemes/oauth'

  serverVariables:
    stage:
      default: demo
      description: This value is assigned by the service provider in this example of `mycompany.com`

  channels:
    user:
      address: 'users.{userId}'
      title: Users channel
      description: This channel is used to exchange messages about user events
      messages:
        userSignedUp:
          $ref: '#/components/messages/userSignUp'
      parameters:
        userId:
          $ref: '#/components/parameters/userId'
      servers:
        - $ref: '#/components/servers/development'
      bindings:
        $ref: '#/components/channelBindings/user'
      tags:
        - $ref: '#/components/tags/user'
      externalDocs:
        $ref: '#/components/externalDocs/infoDocs'

  messages:
    userSignUp:
      summary: Action to sign a user up
      traits:
        - $ref: '#/components/messageTraits/commonHeaders'
      payload:
        $ref: '#/components/schemas/Category'
      correlationId:
          $ref: '#/components/correlationIds/default'
      bindings:
        $ref: '#/components/messageBindings/user'

  parameters:
    userId:
      description: Id of the user

  correlationIds:
    default:
      description: Default Correlation ID
      location: $message.header#/correlationId

  operations:
    sendUserSignUp:
      action: send
      title: User sign up
      bindings:
        $ref: '#/components/operationBindings/sendUser'
      traits:
        - $ref: '#/components/operationTraits/binding'
      reply:
        $ref: '#/components/replies/signupReply'

  replies:
    signupReply:
      address:
        $ref: '#/components/replyAddresses/signupReply'
      channel:
        $ref: '#/channels/userSignupReply'

  replyAddresses:
    signupReply:
      location: '$message.header#/replyTo'

  securitySchemes:
    oauth:
      type: oauth2
      description: The oauth security descriptions
      flows:
        clientCredentials:
          tokenUrl: https://example.com/api/oauth/dialog
          availableScopes:
            'subscribe:auth_revocations': Scope required for authorization revocation topic
      scopes:
        - 'subscribe:auth_revocations'

  operationTraits:
    binding:
      bindings:
        amqp:
          ack: false

  messageTraits:
    commonHeaders:
      headers:
        type: object
        properties:
          my-app-header:
            type: integer
            minimum: 0
            maximum: 100

  tags:
    user:
      name: user
      description: User-related messages

  externalDocs:
    infoDocs:
      url: https://example.com/docs
      description: Find more info here

  serverBindings:
    devAmqp:
      amqp:
        exchange: my-exchange
        queue: my-queue

  channelBindings:
    user:
      amqp:
        is: queue
        queue:
          exclusive: true

  operationBindings:
    sendUser:
      amqp:
        ack: false

  messageBindings:
    user:
      amqp:
        contentEncoding: gzip
        messageType: 'user.signup'
        bindingVersion: 0.2.0
```

[asyncapi-spec]: /docs/reference/specification/latest
[info-object]: /docs/reference/specification/latest#infoObject
[schema-object]: /docs/reference/specification/latest#schemaObject
[server-object]: /docs/reference/specification/latest#serverObject
[channel-object]: /docs/reference/specification/latest#channelObject
[operation-object]: /docs/reference/specification/latest#operationObject
[operation-item-object]: /docs/reference/specification/latest#operationObject
[components-object]: /docs/reference/specification/latest#componentsObject
[message-object]: /docs/reference/specification/latest#messageObject
[security-scheme-object]: /docs/reference/specification/latest#securitySchemeObject
[server-variable-object]: /docs/reference/specification/latest#serverVariableObject
[parameter-object]: /docs/reference/specification/latest#parameterObject
[correlation-id-object]: /docs/reference/specification/latest#correlationIdObject
[operation-reply-object]: /docs/reference/specification/latest#operationReplyObject
[operation-reply-address-object]: /docs/reference/specification/latest#operationReplyAddressObject
[external-documentation-object]: /docs/reference/specification/latest#externalDocumentationObject
[tag-object]: /docs/reference/specification/latest#tagObject
[operation-trait-object]: /docs/reference/specification/latest#operationTraitObject
[message-trait-object]: /docs/reference/specification/latest#messageTraitObject
[server-bindings-object]: /docs/reference/specification/latest#serverBindingsObject
[channel-bindings-object]: /docs/reference/specification/latest#channelBindingsObject
[operation-bindings-object]: /docs/reference/specification/latest#operationBindingsObject
[message-bindings-object]: /docs/reference/specification/latest#messageBindingsObject

---

# Tags
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/tags.md

# Tags

## `tags` in AsyncAPI document
A tag is a label or category that groups related entities in an event-driven system.

In the AsyncAPI document, tags are defined as a list of [`tag` objects](/docs/reference/specification/latest#tagObject) within the [`tags` object](/docs/reference/specification/latest#tagsObject) at the [`info` level](/docs/concepts/asyncapi-document/structure.md#info-field).

The individual `tags` field contains the following properties:

- `name`: The name of the tag.
- `description`: A short description explaining the tag's purpose or usage.
- `externalDocs`: Additional external documentation for the tag.

Tags have different purposes depending on the context. They can either be used for consistent tag usage across the AsyncAPI document and logical component grouping or be applied to individual components like [`servers`](/docs/concepts/asyncapi-document/structure.md#servers-field), [`channels`](/docs/concepts/asyncapi-document/structure.md#channels-field), or [`operations`](/docs/concepts/asyncapi-document/structure.md#operations-field) for more specific purposes.

To reuse `tags`, you must define them in the [`components` object](/docs/reference/specification/latest#componentsObject) of an AsyncAPI document and then use [reference objects](/docs/reference/specification/latest#referenceObject) to include them.

### `tags` in `info` object
Tags specified in the `tags` property of the `info` object categorize the entire AsyncAPI document. These globally defined tags provide an overarching context, representing key themes or functional areas within the event-driven system. They group elements like channels or servers by relevance, offering a holistic understanding of the application's structure.

Below is a visual representation of the `tags` object inside the `info` object in an AsyncAPI document:

```mermaid
graph LR
  B[info]
  B --> C[title]
  B --> D[version]
  B --> F[tags]
  F --> G[name]
  F --> I[description]
  F --> K[externalDocs]

  class B,F,I,K,G cyanColor;
  classDef cyanColor fill:#47BCEE,stroke:#000;
```

Below is an example of the `tags` object inside the `info` object in an AsyncAPI document:

```yaml
asyncapi: 3.1.0
info:
  title: AsyncAPI Documentation
  version: 1.0.0
  description: |
    This AsyncAPI document provides an overview
    of the event-driven system
  tags:
    - name: Applications
      description: All applications related topics
      externalDocs:
        description: More info about applications
        url: https://applications.example.com/docs
    - name: Time
      description: All time related topics
      externalDocs:
        description: More info about time
        url: https://time.example.com/docs
```

### `tags` in `servers` object
Tags specified in the `tags` property of the `servers` object categorize server configurations and characteristics. They allow for server categorization based on:

- criteria like location, environment type (like production or development), and unique server features.
- specific tags or labels.

Using the `tags` object under `servers` is optional.

Below is a visual representation of the `tags` object inside the `servers` object in an AsyncAPI document:

```mermaid
graph LR
  B[servers]
  B --> C[host]
  B --> E[protocol]
  B --> G[tags]
  G --> H[name]
  G --> I[description]
  G --> J[externalDocs]
  
  class B,G,I,J,H cyanColor;
  classDef cyanColor fill:#47BCEE,stroke:#000;
```

Below is an example of the `tags` object inside the `servers` object in an AsyncAPI document:

```yaml
asyncapi: 3.1.0

info:
  title: AsyncAPI Documentation
  version: 1.0.0

servers:
  development:
    host: localhost:5672
    description: Development AMQP broker
    protocol: amqp
    protocolVersion: 0-9-1
    tags:
      - name: env:development
        description: This environment is meant for developers to run their tests
  production:
    host: rabbitmq.in.mycompany.com:5672
    description: RabbitMQ broker for the production environment
    protocol: amqp
    protocolVersion: 0-9-1
    tags:
      - name: env:production
        description: This environment is the live environment available for final users
```

### `tags` in `channels` object
Tags specified in the `tags` property of the `channels` object enable logical grouping and categorization based on specific functionalities or business domains.

Using the `tags` object under the `channels` object is optional.

Below is a visual representation of the `tags` object inside the `channels` object in an AsyncAPI document:

```mermaid
graph LR
  A[channel]
  B(address)
  E(messages)
  P(tags)
  F(name)
  G(description)
  I(externalDocs)

  A --> B
  A --> E
  A --> P
  P --> F
  P --> G 
  P --> I 
  
  class A,P,F,G,I cyanColor;
  classDef cyanColor fill:#47BCEE,stroke:#000;
```

Below is an example of the `tags` object inside the `channels` object in an AsyncAPI document:

```yaml
asyncapi: 3.1.0

info:
  title: AsyncAPI Documentation
  version: 1.0.0

channels:
  SignedUp:
    address: 'user.signedup'
    messages:
      userSignedUp:
        payload:
          type: object
    tags:
      - name: user
        description: User-related messages
```

### `tags` in `operations` object
Tags specified in the `tags` property of the `operations` object facilitate logical grouping and categorization of `operation` objects by type, functionality, and more.

Using the `tags` object under the `operations` object is optional.

Below is a visual representation of the `tags` object inside the `operations` object in an AsyncAPI document:

```mermaid
graph LR
  A[operation]
  E(channel)
  F(action)
  H(tags)
  X(name)
  Y(description)
  Z(externalDocs)

  A --> E
  A --> F
  A --> H
  H --> X
  H --> Y
  H --> Z
  
  class A,H,X,Y,Z cyanColor;
  classDef cyanColor fill:#47BCEE,stroke:#000;
```

Below is an example of the `tags` object inside the `operations` object in an AsyncAPI document:

```yaml
operations:
  onUserSignUp:
    title: User sign up
    summary: Action to sign a user up
    description: A longer description
    channel:
      $ref: '#/channels/userSignup'
    action: send
    tags:
      - name: user
        description: operation related to user
      - name: signup
        description: operation related to a user's signUp
      - name: register
        description: operation related to a new registration
    bindings:
      amqp:
        ack: false
    traits:
      - $ref: '#/components/operationTraits/kafka'
```

### `tags` in `message` object
Tags specified in the `tags` property of the `message` object group and categorize messages based on criteria, requirements, channels, and operations.

Using the `tags` object under the `message` object is optional.

Below is a visual representation of the `tags` object inside the `message` object in an AsyncAPI document:

```mermaid
graph LR
  A[message] --> B[summary]
  A --> C[tags]
  C --> D[name]
  C --> E[description]
  A --> F[headers]
  A --> I[payload]
  C --> Y[externalDocs]
  
  class A,C,D,E,Y cyanColor;
  classDef cyanColor fill:#47BCEE,stroke:#000;
```

Below is an example of the `tags` object inside the `message` object in an AsyncAPI document:

```yaml
 name: SimpleSignup
summary: A simple UserSignup example message
tags: 
    - name: userSignUp
      description: some message related to user signup
headers:
  correlationId: my-correlation-id
  applicationInstanceId: myInstanceId
payload:
  user:
    someUserKey: someUserValue
  signup:
    someSignupKey: someSignupValue
```

Below is an example of all the tags defined in the `components` object and referenced in other components like `servers` and `channels`:

```yml
asyncapi: 3.1.0

components:
  tags:
    speech:
      name: Speech
      description: All speech related topics
    video:
      name: Video
      description: All video related topics
      
info:
  title: AsyncAPI Documentation
  version: 1.0.0
  description: |
    This AsyncAPI document provides an overview
    of the event-driven system
  tags:
    - $ref: '#/components/tags/speech'
    - $ref: '#/components/tags/video'

servers:
  speech:
    host: localhost:5672
    description: RabbitMQ broker for sending speech data
    protocol: amqp
    tags:
      - $ref: '#/components/tags/speech'
  video:
    host: localhost:5673
    description: RabbitMQ broker for video information
    protocol: amqp
    tags:
       - $ref: '#/components/tags/video'

channels:
  getSpeech:
      address: 'application/speech/get'
      servers: 
        - $ref: '#/servers/speech'
      messages:
        voice:
          name: Voice
          summary: Add info about the voice stream data
          tags:
            - $ref: '#/components/tags/speech'
  getVideo:
      address: 'application/video/get'
      servers: 
        - $ref: '#/servers/video'
      messages:
        voice:
          name: Video
          summary: Add info about the video data live bitrate and others
          tags: 
            - $ref: '#/components/tags/video'

operations:
  onVoiceStreamed:
    title: Get speech data
    channel:
      $ref: '#/channels/getSpeech'
    action: receive
    tags:
      - $ref: '#/components/tags/speech'

  onVideoStreamed:
    title: Get video data
    channel:
      $ref: '#/channels/getVideo'
    action: receive
    tags:
      - $ref: '#/components/tags/video'
```

---

# Adding channels
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/adding-channels.md

# Adding channels

Incorporating [channels](/docs/concepts/channel.md) in the AsyncAPI document facilitates message organization and categorization, streamlining message routing to suitable consumers. It also enables the decoupling of producers and consumers, which contributes to the API's scalability and extensibility. Moreover, it offers comprehensive documentation and transparent communication about the API's communication patterns. Additionally, alternative names for channels can be user-defined to suit specific contexts and preferences.

Here is an example of how to define channels:

```yml
userSignedUp:
  address: 'user.signedup'
  messages:
    userSignedUp:
      $ref: '#/components/messages/userSignedUp'
```

The previous AsyncAPI document sets up an interface for a `userSignedUp` channel, where the `address` field holds the actual address of the channel (`user.signedup`).

### Channel availability on specific servers

When you add a channel to the AsyncAPI document, by default it is expected to be available on any server described in the document. In other words, if you have two servers, `production-kafka-secure` and `development-kafka`, the channel described in the AsyncAPI document must be present on both servers.

It's possible to encounter a scenario where an AsyncAPI document describes an application communicating in a production environment through multiple servers, each utilizing distinct protocols. For example, the application might receive messages from a channel on an MQTT server while concurrently sending messages to a different channel on a Kafka server. In such cases, it's imperative to distinctly specify the exclusive availability of one channel on the MQTT server and another channel solely on the Kafka server. 

```mermaid
graph LR
    D[MQTT Server] --> |receive| E[Application]
    E -->|send| G[Kafka Server]
```

Here is an example of how you might specify that a channel is available only on specific servers:

```yml
channels:
  lightTurnOn:
    address: light.on
    messages:
      lightOn:
        description: An event describing that lights are on
    servers:
      - $ref: '#/servers/serverA'
  lightTurnOnOff:
    address: light/onoff
    messages:
      lightOnOff:
        description: An event describing that light is either on or off
    servers:
      - $ref: '#/servers/serverB'
servers:
  serverA:
    host: serverA.example.com
    protocol: kafka
  serverB:
    host: serverB.example.com
    protocol: mqtt
```

The above example shows two different channels available only on selected servers. Notice the `servers` field under each channel. It means that the `lightTurnOn` channel is only available on `serverA` which uses Kafka protocol, and the `lightTurnOnOff` channel is available only on `serverB` which uses MQTT protocol.

---

# Parameters in channel address
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/dynamic-channel-address.md

# Parameters in channel address

In the context of channel addresses within AsyncAPI documents, parameters play a crucial role in defining the dynamic components of an address. That aspect is particularly beneficial in setups like IoT, where topics are often assigned per device or device segment. In this scenario, your AsyncAPI document would describe a system composed of multiple channels. While these channels share the same definition, messages, and purpose, they differ in their channel addresses, which vary according to each device's identifier. To efficiently manage this setup, you provide a singular channel definition. The dynamic segment of each channel address, which corresponds to the device identifier, is then articulated through the use of parameters. 

## Add parameters

You can add parameters to the `channel.address` by adding a parameter between curly braces like `{braces}`. Next, use `channel.parameters` to define your parameters. Finally, leverage the `components.parameters` to enable reusable parameters' definitions across multiple channels.

The diagram below describes how to use reusable parameters in AsyncAPI.

```mermaid
graph LR
  C[channels]
  F[address]
  I[messages]
  A[components]
  B[parameters]
  D[parameters]
  C --> F
  C --> I
  C --> D
  D --> |$ref| B
  A --> B
  
  style C fill:#47BCEE,stroke:#000;
  style D fill:#47BCEE,stroke:#000;
  style F fill:#47BCEE,stroke:#000;
```

First, configure the variables in `address`. Next, define reusable variables in `components.parameters`. Finally, ensure that your `channel.parameters` references definitions in the `components.parameters` using `$ref`.

### Channels section

Here is an example of a parametrized channel address:

```yml
  lightingMeasured:
    address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
    description: The topic on which measured values may be produced and consumed.
    parameters:
      streetlightId:
        description: The ID of the streetlight.
```

In the above example, you can see a definition of a `lightingMeasured` channel that contains a `streetlight` parameter. During runtime, there can be two or more channels serving the same purpose, but with different devices. For example, you could have channels for  `smartylighting/streetlights/1/0/event/2/lighting/measured` and `smartylighting/streetlights/1/0/event/1/lighting/measured`.

### `parameters` section

In your AsyncAPI document, it's important to carefully define the `components.parameters` section. For each parameter utilized in the channel `address`, provide a comprehensive description along with other pertinent details. Avoid repeating the parameter definitions. For example:

```yaml
components:
  parameters:
    streetlightId:
      description: The ID of the streetlight.
```

You can reuse parameters using the [Reference Object](/docs/reference/specification/v3.1.0.md#referenceObject) like in the following example:

```yml
    parameters:
      streetlightId:
        $ref: '#/components/parameters/streetlightId'
```

Here's the complete AsyncAPI document with the channels' parameters for the `address` field:
```yaml
asyncapi: 3.1.0
info:
  title: Example API
  version: '1.0.0'
channels:
  lightingMeasured:
    address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
    description: The topic on which measured values may be produced and consumed.
    parameters:
      streetlightId:
        $ref: '#/components/parameters/streetlightId'
components:
  parameters:
    streetlightId:
      description: The ID of the streetlight.
```

---

# Adding operations
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/adding-operations.md

# Adding operations

In a messaging system, 'operations' are how messages are sent and received between participants or components. In AsyncAPI, understanding operations helps you see how the system sends asynchronous messages back and forth without waiting for responses. They serve as a vital tool, aiding users in comprehending the range of tasks and functionalities that the API is capable of performing.

In an AsyncAPI document, operations describe your application's behaviors and capabilities by exchanging messages through channels configured in the AsyncAPI document. An `operation` represents a particular action or interaction that can be performed. The purpose of operations is to provide a standardized means for describing the process of sending, receiving from, requesting, or replying to messages within the messaging system. 

## Defining operations

Operations can be defined as an independent object in the AsyncAPI document. More information about each field name that is used to define operations can be found [in the reference documentation of the specification](/docs/reference/specification/v3.1.0.md#operationObject). 

The following diagram declares the field names that are frequently used to define operations in an AsyncAPI document:

```mermaid
flowchart LR
  C[operations]
  F[action]
  I[channel]
  A[messages]
  B[reply]
  D[bindings]
  E[security]
  C --> F
  C --> I
  C --> D
  C --> B
  C --> E
  C --> A
  classDef default fill:#47BCEE,stroke:#000;
```

## Adding operations

In the AsyncAPI document, 'operations' are distinct fields located at the root level of the document, alongside 'channels' and other key fields.
Operations must specify on what channel they are performed by referencing the `channel` with `$ref`. For example:

```
onUserSignUp:
  title: User sign up
  summary: React and process information about new user sign up.
  description: Process information about user sign up and update the information in the table that counts numbers of currently signed up users.
  action: receive
  channel:
    $ref: '#/channels/userSignup'
```

The operation definition mentioned above gives the details needed for the application to send a message. Its 'title' and 'summary' clearly show that it's about receiving an event when a new user signs up to the system.

Some fields are missing from this example:
- No `messages` field means that this operation processes any message coming from the `userSignup` channel.
- No `security` field means that there are no special security measures related to this operation and that the security should be applied the same as for other operations. Essentially, the security from the server level should be respected.
- No `reply` field means that after reacting to the user sign up, this application will not send any reply as a reaction.

---

# Operation security
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/securing-operations.md

# Operation security

The server security concept in AsyncAPI means that the security settings specified at the server level automatically apply to all operations across all channels. If you want to modify these default security settings for a particular operation, you need to specify the security details directly on that operation.

## Add security

To accommodate such scenarios, the AsyncAPI document allows you to use the `security` field at the `operation` level. You can have multiple security schemes, but only one must be satisfied to authorize such an operation.

The diagram below describes how to implement reusable security schemes:

```mermaid
graph LR
  C[components]
  F[address]
  I[messages]
  A[components]
  B[securitySchemes]
  D[security]
  C --> F
  C --> I
  C --> D
  D --> |$ref| B
  A --> B
  
  style C fill:#47BCEE,stroke:#000;
  style D fill:#47BCEE,stroke:#000;
```

## Operation section

Security information for an operation is defined using a [Security Scheme](/docs/reference/specification/v3.1.0.md#securitySchemeObject) at the operation level. You can reference a scheme from another location, such as `components.securitySchemes`, using the `$ref` keyword.

```yaml
operations:
  sendAuthRevoke:
    action: send
    channel:
      $ref: '#/channels/authRevoke'
    security:
      - type: oauth2
        description: The oauth security descriptions
        flows:
          clientCredentials:
            tokenUrl: 'https://example.com/api/oauth/dialog'
            availableScopes:
              'subscribe:auth_revocations': Scope required for authorization revocation topic
        scopes:
          - 'subscribe:auth_revocations'
```

The previous example, featuring the `sendAuthRevoke` operation in an AsyncAPI document, demonstrates the capabilities of a client application with an existing notification service. If a server has its own security requirements, this operation must also comply with those.

## `securitySchemes` section

To reuse security schemes between operations, place them in `components.securitySchemes` and reference them via the `$ref` keyword in your operation:

```yaml
operations:
  sendAuthRevoke:
    action: send
    channel:
      $ref: '#/channels/authRevoke'
    security:
      - $ref: '#/components/securitySchemes/oauth'

components:
  securitySchemes:
    oauth:
       type: oauth2
        description: The oauth security descriptions
        flows:
          clientCredentials:
            tokenUrl: 'https://example.com/api/oauth/dialog'
            availableScopes:
              'subscribe:auth_revocations': Scope required for authorization revocation topic
        scopes:
          - 'subscribe:auth_revocations'
```

The previous code snippet shows the approach for reusing schema within multiple operations, even across multiple AsyncAPI documents.

---

# Adding messages
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/adding-messages.md

# Adding messages

In an AsyncAPI document, adding [messages](/docs/reference/specification/v3.1.0.md#messageObject) mainly means setting up channels and operations. This is key for explaining how data moves between your applications. However, sometimes you might just want to use the AsyncAPI document to describe the messages themselves, without anything else.

## Add messages

In an AsyncAPI document, you define message definitions under channels. However, the best practice is to first define these messages under the 'components' section as reusable definitions. That way, you can reference them easily from a channel.

Here is a diagram showing some channel fields and the relation between channel messages and components messages:

```mermaid
graph LR
  C[channels]
  F[title]
  I[address]
  A[components]
  B[messages]
  D[messages]
  C --> F
  C --> I
  C --> D
  D --> |$ref| B
  A --> B
  
  style C fill:#47BCEE,stroke:#000;
  style D fill:#47BCEE,stroke:#000;
```

### Channels section

Define the channels section in your AsyncAPI document, including the `messages` your channel accepts. For example:

```yaml
channels:
  allCommentsLiked:
    address: comment/liked
    messages:
      commentLiked:
        description: Message that is being sent when a comment has been liked by someone.
        payload:
           type: object
           title: commentLikedPayload
           additionalProperties: false
           properties:
               commentId: 
                 type: string
                 description: Id of the comment that was liked
    description: Notification channel for all the services that need to know comment is liked.
```

The above example presents an application that communicates over the `allCommentsLiked` channel, which only accepts one message called `commentLiked`.

### `messages` section

In your AsyncAPI document, create a `components.messages` section to define each message your application uses as a reusable message. When setting up multiple channels, you won't have to repeat the same message definitions. For example:

```yaml
components:
  messages:
    commentLiked:
        description: Message that is being sent when a comment has been liked by someone.
        payload:
           type: object
           title: commentLikedPayload
           additionalProperties: false
           properties:
               commentId: 
                 type: string
                 description: Id of the comment that was liked
```

You can reuse messages using the [Reference Object](/docs/reference/specification/v3.1.0.md#referenceObject). For example:

```yml
    messages:
      commentLiked:
        $ref: '#/components/messages/commentLiked'
```

Here's the complete AsyncAPI document with channels reusing the same message:
```yml
asyncapi: 3.1.0
info:
  title: Example API
  version: '1.0.0'
channels:
  allCommentsLiked:
    address: comment/liked
    messages:
      commentLiked:
        $ref: '#/components/messages/commentLikedUnliked'
    description: Notification channel for all the services that need to know comment is liked.
  allCommentUnliked:
    address: comment/unliked
    messages:
      commentUnliked:
        $ref: '#/components/messages/commentLikedUnliked'
    description: Notification channel for all the services that need to know comment is liked.
components:
  messages:
    commentLikedUnliked:
        description: Message that is being sent when a comment has been liked or unliked by someone.
        payload:
           type: object
           title: commentInfoPayload
           additionalProperties: false
           properties:
               commentId: 
                 type: string
                 description: Id of the comment that was liked or unliked
```

### Identifier of the message

The key name that represents a message in your AsyncAPI document must be interpreted as `messageId`. If your document defines channels, the message key defined in the channel is the `messageId`.

```yaml
channels:
  allCommentsLiked:
    address: comment/liked
    messages:
      commentLiked:
        $ref: '#/components/messages/commentLikedUnliked'
    description: Notification channel for all the services that need to know comment is liked.
```

The above example shows a `commentLiked` message under the `allCommentsLiked` channel. It references a reusable message definition from the `components` section represented by the `commentLikedUnliked` key. In this setup, the `commentLiked` key is the `messageId` and not `commentLikedUnliked`.

### Messages under operations

Operations specify which channels they interact with. If a channel has several messages, but your operation only involves one, indicate which specific message the operation uses. 

```yaml
channels:
  allComments:
    address: comments
    messages:
      commentLiked:
        $ref: '#/components/messages/commentLikedMsg'
      commentUnliked:
        $ref: '#/components/messages/commentUnlikedMsg'
    description: Notification channel for all the services that need to know comment is liked.
operations:
  onCommentLiked:
    action: receive
    channel:
      $ref: '#/channels/allComments'
    messages:
      - $ref: '#/channels/allComments/messages/commentLiked'
```

The above example demonstrates how to specify the message for the `onCommentsLiked` operation received from the `allCommentLiked` channel. It's important to note that the message reference points to the channel, not the components section. That ensures accurate information about the `messageId`, which in this case is `commentLiked`, not `commentLikedMsg`.

---

# Reusability with traits
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/reusability-with-traits.md

# Reusability with traits

Traits work only with the `operations` and `messages` fields. Traits allow the definition of properties to be reused across multiple messages and operations within the specification. Reusing traits promotes code maintainability and reduces duplication while making your AsyncAPI documents cleaner to manage.

## Defining traits

Traits are meant to be reused, so it's best to define them in the `components` section of your AsyncAPI document, either under `operationTraits` or `messageTraits`. Choose depending on whether they're for operations or messages. Give each trait a unique name and list the properties it includes. You can reference these traits with the `$ref` keyword, allowing you to keep traits in a separate file outside the AsyncAPI document. For more on using `$ref` and reusability, check out the [reusable parts document](/docs/concepts/asyncapi-document/reusable-parts.md).

```mermaid
graph LR
    A[channels] --> F[messages]
    F -->|$ref| D
    B[components] --> C[operationTraits]
    B --> D[messageTraits]
    E[operations] -->|$ref| C

    style A fill:#47BCEE,stroke:#47BCEE;
    style F fill:#47BCEE,stroke:#47BCEE;
    style E fill:#47BCEE,stroke:#47BCEE;
```

[Message traits](/docs/reference/specification/latest#messageTraitObject) do not fully cover all fields that a normal message has, such as the `payload`. The same is true with [Operation traits](/docs/reference/specification/latest#operationTraitObject) which represent only selected fields usually used in an operation.

Here is a part of a message that has a trait defined inline in a message:

```yaml
description: Example description.
traits:
  - name: UserSignup
    description: Trait description.
  - tags:
      - name: user
```

When traits are combined with a message object, the resulting message will look like the example shown below:

```yaml
name: UserSignup
description: Example description.
tags:
  - name: user
```

Notice that the trait description didn't override the already defined description in a message outside the trait. 

## Applying traits from components

Once a trait is defined, you can apply it to an operation or a message using the `$ref` keyword in the `traits` section. The `$ref` value should point to the path of the trait within the `components` section.

For example, let's say we have a trait named `commonHeaders` defined in `messageTraits`:

```yml
components:
  messageTraits:
    commonHeaders:
      headers:
        type: object
        properties:
          content-type:
            type: integer
```

To apply the above trait to a message object, you can do:

```yml
name: lightMeasured
title: Light measured
summary: Inform about environmental lighting conditions of a particular streetlight.
headers:
  type: object
  properties:
    custom-header:
      type: string
traits:
  - $ref: '#/components/messageTraits/commonHeaders'
```

Notice how the `commonHeaders` trait includes a `content-type` header and is merged into the `headers` object in a message:

```yaml
name: lightMeasured
title: Light measured
summary: Inform about environmental lighting conditions of a particular streetlight.
headers:
  type: object
  properties:
    content-type:
      type: integer
    custom-header:
      type: string
```

## Trait merging mechanism

In the AsyncAPI document, traits are merged into the operation or message object in the order they are defined, without overriding any properties. For detailed information on how this merging works, refer to [the specification's section on the traits merge mechanism](/docs/reference/specification/v3.1.0.md#traitsMergeMechanism).

---

# Server security
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/server-security.md

# Server security

Server security refers to the measures and practices implemented to protect servers from unauthorized access, data breaches, and other security threats. Server security involves implementing various security mechanisms to ensure the confidentiality, integrity, and availability of server resources.

In the context of AsyncAPI, securing servers ensures secure exchange of messages between clients and servers. While also protecting sensitive data, preventing unauthorized access, and maintaining the overall security of the API or server.

You can describe how your server is secured with the `security` property where you define which security schemes can be used with the server in context. Each `server` in the AsyncAPI document can have one or more security schemes declared. A security scheme defines a security requirement that must be satisfied to authorize an operation, such as an API key or a username and password. 

Here is an example of adding security to your server, demonstrating that different servers can employ various security mechanisms:
```yml
asyncapi: 3.1.0
info:
  title: Streetlights Kafka API
  version: 1.0.0
servers:
  scram-connections:
    host: 'test.mykafkacluster.org:18092'
    protocol: kafka-secure
    description: Test broker secured with scramSha256
    security:
      - $ref: '#/components/securitySchemes/saslScram'
  mtls-connections:
    host: 'test.mykafkacluster.org:28092'
    protocol: kafka-secure
    description: Test broker secured with X509
    security:
      - $ref: '#/components/securitySchemes/certs'
components:
  securitySchemes:
    saslScram:
      type: scramSha256
      description: Provide your username and password for SASL/SCRAM authentication
    certs:
      type: X509
      description: Download the certificate files from service provider
```

Here is an illustration of securing servers: 
```mermaid
graph LR
  C[servers]
  F[host]
  I[protocol]
  E[security]
  C --> F
  C --> E
  C --> I
  style C fill:#47BCEE,stroke:#000;
  style E fill:#47BCEE,stroke:#000
```

Here are some of the security schemes that AsyncAPI supports:
- User/Password
  ```yml
  type: userPassword
  ```

- API key (either as a user or as a password)
  ```yml
  type: apiKey
  in: user
  ```

- X.509 certificate
  ```yml
  type: X509
  ```

- End-to-end encryption (either symmetric or asymmetric)
  ```yml
  type: symmetricEncryption
  ```

- HTTP authentication
  ```yml
  type: http
  scheme: basic
  ```

- HTTP API key
  ```yml
  type: httpApiKey
  name: api_key
  in: header
  ```

- JWT Bearer
  ```yml
  type: http
  scheme: bearer
  bearerFormat: JWT
  ```

- Implicit oauth2
  ```yml
  type: oauth2
  flows:
    implicit:
      authorizationUrl: https://example.com/api/oauth/dialog
      availableScopes:
        write:pets: modify pets in your account
        read:pets: read your pets
  scopes:
    - 'write:pets'
  ```

- SASL (Simple Authentication and Security Layer) as defined in RFC4422
  ```yml
  type: scramSha512
  ```

Although the `security` property is not mandatory, it is a good practice to always secure your server(s) in production. Similarly, having multiple security schemes declared does not necessarily mean that the server is more secure; it depends on other factors such as the protocol used, use case, business perspective, and more. Additionally, you can also [add security at the `operation` level](securing-operations).

---

# Adding reply info
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/reply-info.md

# Adding reply info

Request/Reply is a communication pattern where one entity, the 'requestor,' sends a message to another, the 'replier', and waits for a response. Such a pattern is used when a component (or service) needs to initiate an action and receive a specific response in return, either synchronously or asynchronously. In Event-Driven Architectures, this communication pattern is asynchronous, meaning that the requester does not block and wait for an immediate response. Instead, it can continue processing other tasks or even send out other requests while waiting for the reply to arrive. 

In the case of multiple requests made, each request is processed independently and sends the reply/response to the corresponding requestor when ready.

Here is diagram to illustrate the working of a basic request/reply pattern:
```mermaid
sequenceDiagram
    Requester->>Channels: Send Request through Channel A
    Channels->>Responder: Deliver Request
    activate Responder
    Responder-->>Channels: Send Reply through Channel B
        deactivate Responder
    Channels-->>Requester: Deliver Reply
```

The request/reply pattern in AsyncAPI works in the same fashion while supporting all the different sub-patterns. Irrespective of the sub-pattern you would like to represent, the request/reply pattern can be implemented in the AsyncAPI document in the `Operation` object.

You can add the reply info using the `Operation Reply` object under the `Operation` object. The `reply` field represents the response details.

In AsyncAPI, you have the flexibility to represent the request/reply pattern in two different ways.

The first approach is when the requester specifies at runtime, within the request itself, where the response should be sent. Such an approach allows for the dynamic determination of the reply address based on factors such as the request message payload or header.

The second approach is when the requester already knows exactly where the response should be sent. In such cases, the address of the reply channel is directly specified in the AsyncAPI document.

## Dynamic response channel

There are situations where you do not know the reply channel at the design time. Instead, the reply address is dynamically determined at runtime, based on factors such as the request message payload or header. 

In the case where you don't know the address of the reply yet, you have the option to either assign null to the `address` property or omit the property entirely indicating that the address is not known at the moment. The `address` property being referred to in this case is part of the channel that the operation with the reply references to. To dynamically specify where the reply should be sent, you can use the `Operation Reply Address` object. The `Operation Reply Address` object has a property called `location` that allows you to define a runtime expression that specifies the address of the reply channel. 

For instance, this pattern allows the replier to direct its response to a specific channel as defined by the requestor. This is typically achieved by including a `replyTo` property in the request header. The requestor specifies this property to indicate where it expects to receive the response, guiding the communication flow in a structured and predictable manner.

```yml
asyncapi: 3.1.0

info:
  title: Ping/pong example for a requester with a dynamic reply channel
  version: 1.0.0
  description: Example with a requester that initiates a request/reply interaction, with the response directed to the destination specified in the request's `replyTo` header.

channels:
  ping:
    address: /ping
    messages:
      ping:
        $ref: '#/components/messages/ping'
  pong:
    address: null
    messages:
      pong:
        $ref: '#/components/messages/pong'

operations:
  pingRequest:
    action: send
    channel: 
      $ref: '#/channels/ping'
    reply:
      address:
        description: The response destination is dynamically set according to the `replyTo` field in the request header
        location: "$message.header#/replyTo"
      channel: 
        $ref: '#/channels/pong'
```

## Multiple channels with single message when reply address is known

The request/reply pattern can also be implemented over multiple channels with a single message. You can do this by specifying multiple channels with a single message and specifying the same address for both the requester and the replier.

Here's an example of setting up both the requestor and replier over the same address:
```yml
asyncapi: 3.1.0

info:
  title: Ping/pong example with requester over the same channel
  version: 1.0.0
  description: Requester example initiating a request-reply interaction, utilizing the same channel for both sending the request and receiving the reply.

channels:
  ping:
    address: /
    messages:
      ping:
        $ref: '#/components/messages/ping'
  pong:
    address: /
    messages:
      pong:
        $ref: '#/components/messages/pong'

operations:
  pingRequest:
    action: send
    channel: 
      $ref: '#/channels/ping'
    reply:
      channel: 
        $ref: '#/channels/pong'
```

## Multiple messages over the same channel when reply address is known

In some cases, representing the [same information](#multiple-channels-with-single-message-when-reply-address-is-known) might require a different approach. You can do so by specifying multiple messages under the same channel. In such scenarios, use the `messages` property in the `Operation` object to explicitly define which message among the multiple messages available over the same channel is a request and which is a reply.  

Consider an example where multiple messages are transmitted over a single channel, all sharing the same address. In this setup, the `Operation` object is utilized to distinctly specify which of these messages serves as the request and which functions as the reply:
```yml
asyncapi: 3.1.0

info:
  title: Ping/pong example when a channel contains multiple messages
  version: 1.0.0
  description: Requester example that initiates the request-reply pattern within a root channel that contains multiple messages

channels:
  rootChannel:
    address: /
    messages:
      ping:
        $ref: '#/components/messages/ping'
      pong:
        $ref: '#/components/messages/pong'

operations:
  pingRequest:
    action: send
    channel: 
      $ref: '#/channels/rootChannel'
    messages:
      - $ref: "/components/messages/ping"
    reply:
      messages:
        - $ref: "/components/messages/pong"
      channel: 
        $ref: '#/channels/rootChannel'
```

---

# Extending specification
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/extending-specification.md

# Extending specification

Extending the AsyncAPI specification allows you to include specific information for your domain or use case that's not currently supported by the original specification or the protocol bindings. Extension capability allows for customization, making it possible to integrate unique aspects into APIs that the standard AsyncAPI specification doesn't normally accommodate.

## Specification extensions

The AsyncAPI Specification allows the addition of custom properties through patterned fields prefixed with an `x-`. That way, you can create unique things without causing problems in future updates.

The `x-` prefix is used to define custom properties. These properties are user-defined and won't conflict with future specification versions because any property starting with `x-` is reserved for user definitions.

Extensions can be used in any part of the AsyncAPI document.

Here is an example of how to extend the AsyncAPI document with a custom property:

```yml
asyncapi: 3.1.0
info:
  title: Cool Example
  version: 0.1.0
  x-linkedin: '/company/asyncapi'  
```

The above document shows an `info` object extended with custom information about a company's LinkedIn account that owns the application. Custom information is represented via a custom property called `x-linkedin`.

> **Remember**
>
> AsyncAPI tools might not support AsyncAPI extensions. Our tools can be extended to understand and handle the added data, especially if the tools are internal or open source.

## Extending unsupported features

If you need a feature not covered by the AsyncAPI specification, you can create an extension for it. Should this extension be useful to others, consider contributing it back to the AsyncAPI community. You can do this by [opening a spec issue](https://github.com/asyncapi/spec) in the AsyncAPI GitHub repository. Before contributing, review the [AsyncAPI contribution guidelines](https://github.com/asyncapi/spec/blob/master/CONTRIBUTING.md).

---

# Adding bindings
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/adding-bindings.md

# Adding bindings

Bindings in AsyncAPI provide a way to add protocol-specific information to the AsyncAPI documentation. They can be added to different document parts, such as servers, channels, or messages; they specify standard details specific to a particular protocol. The purpose of bindings is to enhance the API's understanding and usage by providing additional context and configuration options for different protocols.

The following diagram highlights the sections where bindings can be implemented:

```mermaid
graph TD
A[AsyncAPI Document] --> B((Servers))
A --> D((Channels))
A --> E((Operations))
D --> F((Messages))
B --> C{Server Bindings}
D --> G{Channel Bindings}
E --> H{Operation Bindings}
F --> I{Message Bindings}

style C fill:#47BCEE,stroke:#47BCEE;
style G fill:#47BCEE,stroke:#47BCEE;
style H fill:#47BCEE,stroke:#47BCEE;
style I fill:#47BCEE,stroke:#47BCEE;
```

## Server bindings

Server bindings provide protocol-specific information related to the server configuration. For example, if you use Pulsar as your message broker, you can specify the tenant name in the server bindings. 

Here is a diagram explaining server bindings:

```mermaid
graph LR
A[AsyncAPI Document] --> B((Servers))
B --> C{Server Bindings}

style C fill:#47BCEE,stroke:#47BCEE;
```

This diagram shows where server bindings fit into the AsyncAPI document structure.

The next example showcases how to use server bindings to detail protocol-specific configurations for the server:

```yml
servers:
  production:
    bindings:
      pulsar:
        tenant: contoso
        bindingVersion: '0.1.0'
```

The previous document shows how to set up server bindings for a server that is a Pulsar broker.

## Channel bindings

Channel bindings are used to specify protocol-specific information for a specific channel. For example, in Kafka, you can specify number of partitions for a given topic.

Here is a diagram explaining where channel bindings fit into the AsyncAPI document structure:

```mermaid
graph LR
A[AsyncAPI Document] --> D((Channels))
D --> G{Channel Bindings}

style G fill:#47BCEE,stroke:#47BCEE;
```

Here is an example of using channel bindings to specify protocol-specific information for a specific channel:

```yml
channels:
  user-signedup:
    bindings:
      kafka:
        topic: 'my-specific-topic-name'
        partitions: 20
        replicas: 3
        topicConfiguration:
          cleanup.policy: ["delete", "compact"]
          retention.ms: 604800000
          retention.bytes: 1000000000
          delete.retention.ms: 86400000
          max.message.bytes: 1048588
        bindingVersion: '0.4.0'
```

The previous document shows how to configure channel bindings for a Kafka topic-representative channel.

## Message bindings

Message bindings provide protocol-specific information for a specific message. For example, for the AMQP protocol, you can specify the message type in a protocol-specific notation. 

Here is a diagram explaining where message bindings fit into the AsyncAPI document structure:

```mermaid
graph LR
A[AsyncAPI Document] --> F((Channels))
F --> G{Message Bindings}

style G fill:#47BCEE,stroke:#47BCEE;
```

Here is an example of using message bindings to provide protocol-specific information for a specific message:

```yml
channels:
  userSignup:
    address: 'user/signup'
    messages:
      userSignupMessage:
        bindings:
          amqp:
            contentEncoding: gzip
            messageType: 'user.signup'
            bindingVersion: 0.3.0
```

The previous document shows how to set up message bindings for a message transported using the AMQP protocol.

## Operation bindings

Operation bindings allow you to specify protocol-specific information for a specific operation. For example, for MQTT, you can specify the quality of the service for a given operation.

Here is a diagram explaining where operation bindings fit into the AsyncAPI document structure:

```mermaid
graph LR
A[AsyncAPI Document] --> D((Channels))
D --> E{Operations}
E --> H{Operation Bindings}

style H fill:#47BCEE,stroke:#47BCEE;
```

Here is an example of using operation bindings to specify protocol-specific information for a specific operation:

```yml
channels:
  user/signup:
operations:
  userSignup:
    action: receive
    bindings:
      mqtt:
        qos: 2
        retain: true
        bindingVersion: 0.2.0
```

The previous document shows how to set up operation bindings for an operation that describes how an application that uses MQTT as transport, receives the message.

Using bindings helps you enhance the AsyncAPI documentation with protocol-specific details, making it easier to understand and implement the API.

---

# Payload schema
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/define-payload.md

# Payload schema

The payload schema sets the format, data types, and properties of a message. Such an approach ensures the message's payload follows a specific structure and data format.

It's recommended to use AsyncAPI Schema (a superset of JSON Schema) for handling complex messages and structured data.  AsyncAPI Schema helps consumers understand the payload's structure and data types. However, AsyncAPI allows any schema format. For example, when using the Avro schema format, define your message payload in Avro directly instead of trying to represent it in JSON Schema format.

## Define schema

Define the schema for the message payload with one of the following methods:

- Inline: Define the JSON schema within the message payload property.
- Components reference: Specify the schema using a reference to the `components.schemas` section, such as `$ref: '#/components/schemas/user`.
- Remote reference: Specify the schema using an absolute remote endpoint, such as `$ref: 'https://schemas.example.com/user'`.
- Local file reference: Specify the schema using a relative reference, such as `$ref: './user-signedup.json'`.

The diagram below describes how payload referencing works within the component reference:

```mermaid
graph LR
  C[message]
  F[contentType]
  I[headers]
  A[components]
  B[schemas]
  D[payload]
  C --> F
  C --> I
  C --> D
  D --> |$ref| B
  A --> B
  
  style C fill:#47BCEE,stroke:#000;
  style D fill:#47BCEE,stroke:#000;
```

Here is an example of an AsyncAPI document where the payload's schema is defined directly within it:

```yaml
channels:
  exampleChannel:
    address: exampleChannel
    messages:
      SimpleSignup:
        payload:
          type: object
          properties:
            name:
              type: string
            email:
              type: string
```

## Attach examples

Although optional, attaching examples to the AsyncAPI document is highly recommended. You can use JSON or YAML format for binary encodings. Attach the examples to the examples property within the message payload definition. For example:

```yaml
examples:
  - name: SimpleSignup
    summary: A simple UserSignup example message
    payload:
      user:
        name: Demo
        email: demo@demo.io
```

## Reuse schemas between messages

To reuse a schema in your AsyncAPI document, define it in the `components/schemas` section and reference it using the `$ref` keyword. Using `$ref` avoids duplication and ensures consistency. Here's an example of reusing a schema from components in AsyncAPI:

```yaml
components:
  messages:
    SimpleSignup:
      name: SimpleSignup
      contentType: application/json
      payload:
        $ref: '#/components/schemas/SimpleSignup'
    examples:
    - name: SimpleSignup
      payload: 
        user:
          name: Demo
          email: demo@demo.io
  schemas:
    SimpleSignup:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
```

## Schema formats

The default schema in an AsyncAPI document is the AsyncAPI schema itself. However, you can choose from other formats like JSON Schema, Avro, OpenAPI Schema, Protobuf, and more. Remember to indicate in your AsyncAPI document which schema format you're using.

You specify the format of the schema inside the `payload` field. The type of information you can put in `payload` can be described as a tuple. (A tuple is an ordered sequence of elements that can't be changed during a program's execution.) 

When using AsyncAPI Schema, the `payload` must represent a reference or the payload schema definition as described in previous sections. 

If you're using various formats, the `payload` field should include both `payload.schemaFormat` and `payload.schema`. For example:
```yaml
  payload:
    schemaFormat: application/vnd.apache.avro;version=1.9.0
    schema:
      $ref: "https://www.asyncapi.com/resources/casestudies/adeo/CostingRequestPayload.avsc"
```

The above example specifies that the provided schema of the message payload is in Avro, version 1.9.0. It also specifies where the Avro schema file is located.

## Schema formats and limitations related to their structures

Some schema formats are too challenging to manage in JSON/YAML. Complex schema formats — Avro, AsyncAPI schemas, and other JSON-based schemas — can be directly included in the AsyncAPI document or referenced using `$ref` for specific sections.
```yaml
    payload:
        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
        schema: # The following is an Avro schema in YAML format (JSON format is also supported)
          type: record
          name: User
          namespace: com.company
          doc: User information
          fields:
            - name: displayName
              type: string
            - name: email
              type: string
            - name: age
              type: int
```

The process is more complex for Protobuf schemas, as their Protocol Buffers are not JSON-based. You cannot use `$ref` to reference parts of the schema. Instead, you must include the entire Protobuf schema definition as a string:

```yaml
      payload:
        schemaFormat: application/vnd.google.protobuf;version=3
        schema: |
            message Point {
                required int32 x = 1;
                required int32 y = 2;
                optional string label = 3;
            }

            message Line {
                required Point start = 1;
                required Point end = 2;
                optional string label = 3;
            }
```

---

# Server variables
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/variable-url.md

# Server variables

The server's URL consists of the `host` and `pathname` fields. These values are not always known when you design your system. AsyncAPI enables you to construct dynamic URLs while enhancing the flexibility and maintainability of your AsyncAPI documents. These dynamic values (variables) are placeholders for values you can replace during runtime. You can easily manage multiple endpoints, handling various server configurations and environments.

## Add variables

You can add variables to `server.host` and `server.pathname` by adding a variable between curly braces like `{braces}`. Next, you use `server.variables` to provide definitions of your variables. Finally, leverage `components.serverVariables` to enable reusable variable definitions across multiple servers.

The diagram below describes how to use reusable variables in AsyncAPI.

```mermaid
graph LR
  C[servers]
  F[host]
  I[protocol]
  E[pathname]
  A[components]
  B[serverVariables]
  D[variables]
  C --> F
  C --> I
  C --> E
  C --> D
  D --> |$ref| B
  A --> B
  
  style C fill:#47BCEE,stroke:#000;
  style D fill:#47BCEE,stroke:#000;
  style F fill:#47BCEE,stroke:#000;
  style E fill:#47BCEE,stroke:#000
```

First, configure the variables in `host` and/or `pathname`. Next, define reusable variables in `components.serverVariables`. Finally, ensure that your `server.variables` from the server reference definitions in the `components.serverVariables` uses `$ref`.

### Servers section

Define the servers section in your AsyncAPI document, including the `host` and `pathname` for your API servers. Use placeholders enclosed in curly braces {} to represent the variables in the server. For example:

```yaml
servers:
  production:
    host: '{subdomain}.example.com:{port}'
    pathname: '/{version}
    variables:
      subdomain:
        enum:
          - development
          - staging
          - production
      port:
        default: '8080'
      version:
        enum:
          - v1
          - v2
```

### `serverVariables` section

Define the `components.serverVariables` section in your AsyncAPI document. For each variable used in the server `host` or `pathname`, provide a default value and an optional description to avoid repeating the variable definitions. For example:

```yaml
components:
  serverVariables:
    subdomain:
      enum:
        - development
        - staging
        - production
      default: development
    port:
      default: '8080'
    version:
      enum:
        - v1
        - v2
```

### Define domain and port variables

Use `components.serverVariables` in your server using the [Reference Object](/docs/reference/specification/v3.1.0.md#referenceObject) to avoid repeating information:

```yml
    variables:
      subdomain:
        $ref: '#/components/serverVariables/subdomain'
```

Here's the complete AsyncAPI document with the servers' variables for the `host` field:

```yaml
asyncapi: 3.1.0
info:
  title: Example API
  version: '1.0.0'
servers:
  production:
    host: '{subdomain}.example.com:{port}'
    pathname: '/{version}'
    protocol: amqp
    variables:
      subdomain:
        $ref: '#/components/serverVariables/subdomain'
      port:
        $ref: '#/components/serverVariables/port'
      version:
        $ref: '#/components/serverVariables/version'
  development:
    host: '{subdomain}.dev.example.com:{port}'
    pathname: /v1
    protocol: amqp
    variables:
      subdomain:
        $ref: '#/components/serverVariables/subdomain'
      port:
        $ref: '#/components/serverVariables/port'
      version:
        $ref: '#/components/serverVariables/version'
components:
  serverVariables:
    subdomain:
      enum:
        - development
        - staging
        - production
      default: development
    port:
      default: '8080'
    version:
      enum:
        - v1
        - v2
```

---

# Reusable parts
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/reusable-parts.md

# Reusable parts

Reusable parts in AsyncAPI provide flexibility, modularity, and code reusability. You can reuse the majority of document sections like messages, schema definitions, channels, operations, and more.

Reusable parts allow you to split up the AsyncAPI document into many files and reference them using the [Reference Object](/docs/reference/specification/v3.1.0.md#referenceObject). You can use the `$ref` keyword to reference the same document, another local file, or an external URL. The diagram below describes how to reuse parts in AsyncAPI:

## Same document

You can use the `$ref` keyword to reference a component in an AsyncAPI document. In the example below, you define a component called `MyMessageSchema` under the `schemas` section to describe the structure of a message. Under the `myChannel` channel, you have a message with a payload definition that's represented as a reference to the `MyMessageSchema` schema via the `$ref` keyword.

```yaml
channels:
  myChannel:
    message:
      myMessage:
        payload:
          $ref: '#/components/schemas/MyMessageSchema'
components:
  schemas:
    MyMessageSchema:
      type: object
      properties:
        message:
          type: string
```

## Another local file

You can reference another local document using the `$ref` keyword. Ensure the path to the local file is correct and accessible from your main AsyncAPI document.

In the code below, you reference the component from another local document, such as `message-schema.yaml`.

```yaml
UserSignup:
  name: UserSignup
  title: User signup
  summary: Action to sign a user up.
  description: A longer description
  contentType: application/json
  payload: null
```

In the code below, you use another local document, `message-schema.yaml`, through a reference inside the AsyncAPI document. 

```yaml
channels:
  signUp:
    address: user/signedup
    messages:
      UserSignup:
        $ref: './message-schema.yaml#/UserSignup'
operations:
  user/signedup.publish:
    action: receive
    channel:
      $ref: '#/channels/signUp'
    messages:
      - $ref: '#/channels/signUp/messages/UserSignup'
```

## External URL

You can reference an external URL using the `$ref` keyword. Ensure the external URL provides the referenced component in a compatible format, such as YAML or JSON. In the example below, you reference the component from an external URL. The `$ref` value specifies the full URL to the external resource and the component's location.

```yaml
channels:
  signUp:
    address: user/signedup
    messages:
      UserSignup:
        $ref: https://example.com/my-components.yaml#/schemas/MySchema
operations:
  user/signedup.publish:
    action: receive
    channel:
      $ref: '#/channels/signUp'
    messages:
      - $ref: '#/channels/signUp/messages/UserSignup'
```

---

# Add servers
Source: https://www.asyncapi.com/docs/concepts/asyncapi-document/add-server.md

# Add servers

A server often acts as a message broker, managing communication between producers and consumers. However, it can represent different concepts too. To understand this better, please first review our [server concepts doc](/docs/concepts/server.md).

Adding and defining servers is important because it specifies how and where connections are made, enabling the sending and receiving of messages.

Unique keys identify the server and contain information about the server's connection details, such as the host, protocol, and authentication. 

Here is a diagram of server information with selected fields: 

```mermaid
graph LR
  C[servers]
  F[host]
  I[protocol]
  E[security]
  C --> F
  C --> E
  C --> I
```

The server is one of the main sections of the AsyncAPI document next to others like `info`, `channels`, or `operations`.

## Define servers

Include server definitions in your AsyncAPI document to specify which server a channel or operation connects to. Here is an example of defining a server in AsyncAPI:

```yaml
servers:
  prod:
    host: test.mosquitto.org
    protocol: mqtt
    description: Test MQTT server
```

The previous example shows a server setup using the MQTT protocol, where messages are sent to or received from the `test.mosquitto.org` host.

## Server reusability

Add server definitions in a single location, such as `components.servers`, and then refer to them using the `$ref` keyword for easy reuse.

Here's an example of an AsyncAPI document with two servers referenced from the `components` section:
```yaml
servers:
  kafka-test:
    $ref: '#/components/servers/kafka-test'
  mqtt-test:
    $ref: '#/components/servers/mqtt-test'
components:
  servers:
    kafka-test:
      host: my.kafka.pl
      protocol: kafka-secure
      description: Test Kafka server
    mqtt-test:
      host: test.mosquitto.org
      protocol: mqtt
      description: Test MQTT server
```

In this example, the main `servers` section lists multiple servers with sharable definitions. You can also store these server definitions separately and use them across various AsyncAPI documents.

## Channel only on specific server

Your AsyncAPI document can outline an application that receives messages on a channel from an MQTT server, while sending messages on a different channel via a Kafka server. This setup requires defining two servers, with each channel being exclusive to one server – one channel is only available on the MQTT server and the other only on the Kafka server. The AsyncAPI document describes this by adding a `servers` array to each channel, containing references to the respective server definitions.

Here's an example of how to add a server reference to a channel:

```yaml
servers:
  kafka-test:
    host: my.kafka.pl
    protocol: kafka-secure
    description: Test Kafka server
  mqtt-test:
    host: test.mosquitto.org
    protocol: mqtt
    description: Test MQTT server
channels:
  myChannel:
    servers:
      $ref: "#/servers/mqtt-test"
    message:
      $ref: '#/components/messages/myMessage'
```

In this example, the `myChannel` channel is only available on the `mqtt-test` server.

---

# Overview
Source: https://www.asyncapi.com/docs/tutorials.md

# Overview

## Tutorials: Learn how AsyncAPI works

Welcome to AsyncAPI **Tutorials**! Our Tutorials section teaches beginner processes with AsyncAPI by doing.

> **Remember**
>
> ## Contribute to AsyncAPI Tutorials
> Code isn't the only way to contribute to OSS; Dev Docs are a **huge** help that benefit the entire OSS ecosystem. At AsyncAPI, we value Doc contributions as much as every other type of contribution. ❤️
> 
> To get started as a Docs contributor:
> 
> 1. Familiarize yourself with our [project's Contribution Guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md).
> 2. Head over to our [AsyncAPI Docs Board](https://github.com/orgs/asyncapi/projects/12).
> 3. Pick an issue you would like to contribute to and leave a comment introducing yourself. This is also the perfect place to leave any questions you may have on how to get started.
> 4. If there is no work done in that Docs issue yet, feel free to open a PR and get started!
> 
> ### Docs contributor questions
> 
> Do you have a question about contributing to the docs or an issue with your pull request? [Join our Slack community](https://www.asyncapi.com/slack-invite) and ask in the `#docs` channel; the maintainers will get back to you.

---

# Introduction
Source: https://www.asyncapi.com/docs/tutorials/getting-started.md

# Introduction

AsyncAPI is an open source initiative that seeks to improve the current state of Event-Driven Architectures (EDA). Our long-term goal is to make working with EDAs as easy as working with REST APIs. That goes from documentation to code generation, and from discovery to event management. Most of the processes you apply to your REST APIs nowadays would be applicable to your event-driven/asynchronous APIs too.

To make this happen, the first step is to create a specification that allows **developers, architects, and product managers** to define the interfaces of an async API. Much like [OpenAPI (aka Swagger)](https://github.com/OAI/OpenAPI-Specification) does for REST APIs.

**The AsyncAPI specification lays the foundation for a greater and better tooling ecosystem for EDAs**.

If you are looking for a solution to automate and formalize the documentation or code generation of your event-driven (micro)services, you are in the right place. Likewise, if you are aiming to establish solid standards for your events and improve the governance of your asynchronous APIs, welcome to your new home.

---

# Event-Driven Architectures
Source: https://www.asyncapi.com/docs/tutorials/getting-started/event-driven-architectures.md

# Event-Driven Architectures

Many developers, architects, and product managers have used REST APIs and are familiar with the synchronous communication paradigm. You make a request and wait for the response. This is exactly how the world wide web works. You enter a URL (e.g., www.google.com) in the browser's address bar and it sends a request to the server. The server then sends the response with the website content. **The web is the greatest implementation of a REST API.**

However, there are certain situations where you don't need a response from the server. In most cases, it's only important to have some confirmation that the request was received. This is also called _"fire and forget"_, and it's very useful when you just want to communicate or inform that "something happened." You're not requesting or asking for anything, thus you don't need a response.  

Some examples of this can be:
* A user just signed up.
* You have a new follower.
* Your fridge is almost empty.

Along with the event, you may also want to send _extra information_. For instance:

* A user just signed up: here's the user information (e.g., name, email, age, etc.)
* You have a new follower: here are the follower details (e.g., username, name, picture, etc.)
* Your fridge is almost empty: here's the percentage of "emptiness" or available volume (e.g. 23%)

This extra information is often referred to as the _event payload_ or _message payload_.

An Event-Driven Architecture (EDA) uses events to trigger and communicate between services and is common in modern applications built with microservices. An event is a state change, or an update, like adding a shopping item to a cart on an e-commerce website.

## Core concepts

![](https://www.asyncapi.com/img/diagrams/simple-event-driven.png)

In most cases, EDAs are broker-centric, as seen in the diagram above. There are some new concepts in that diagram, so let's go through them now.

### Message broker

A message broker (or _"broker"_) is a piece of infrastructure in charge of receiving messages and delivering them to those who have shown interest. They often store messages until they are delivered, which makes EDAs very resilient to failures. Examples of brokers are [RabbitMQ](https://rabbitmq.com), [Apache Kafka](http://kafka.apache.org/), [Solace](http://solace.com), etc.

### Publisher/Subscriber

A publisher (a.k.a. _producer_) is an application that sends messages to the _broker_.

A subscriber (a.k.a. _consumer_) is an application that connects to the _broker_, manifests an interest in a certain type of message, and leaves the connection open so the _broker_ can push messages to them.

### Message

A message is a piece of information that is sent by publishers to the broker, and received by all interested subscribers. Messages can contain anything and are frequently cataloged as _events_ and _commands_. As you saw above, _events_ communicate a fact that occurred. On the other hand, _commands_ are very similar to _requests_ in REST APIs. They instruct the subscribers to "do this."

**To be precise, _events_ and _commands_ share the same structure but differ conceptually.**

### Channels

One detail that might pass unnoticed from the diagram above is the existence of _channels_. All _brokers_ support communication through multiple channels. The industry doesn't have a common term for them, so you may see them referred to as _topics_, _routing keys_, _event types_, etc.

A channel is usually assigned a name or identifier (e.g., `user_signed_up`) and it is often good practice to send a single type of message through a particular channel. Think about TV or radio channels; the BBC only broadcasts its information through an assigned channel. If the broadcasters (publishers) didn't respect that rule, you (the subscriber) would only see and hear interference.

## Why "event-driven" and not "message-driven"?

You will find both used interchangeably, although they are not the same. You will even find _"message-based"_ and _"event-based"_. In practice, chances are they all refer to the same thing.

Theoretically, _"message-driven"_ is the most generic term -meaning you may use events and commands- while _event-driven_ means that it's purely about events.

However, that's not always the case, as Martin Fowler explains in his
talk ["the many meanings of Event-Driven Architecture"](https://www.youtube.com/watch?v=STKCRSUsyP0).

## Conclusion

We've seen what an Event-Driven Architecture is, how it works, and explained its components. AsyncAPI defines and documents each of these components. We'll cover each of the components during the rest of this guide. To continue, choose your next step:

---

# Coming from OpenAPI
Source: https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi.md

# Coming from OpenAPI

If you're coming from OpenAPI, you must know that AsyncAPI [started as an adaptation of the OpenAPI specification](https://medium.com/asyncapi/whats-new-on-asyncapi-lots-2d9019a1869d). AsyncAPI wanted to be as compatible as possible with OpenAPI so that the users could reuse parts in both.

Before AsyncAPI `3.0.0`, you could find many similarities between OpenAPI and AsyncAPI. Remember that in the world of Event-Driven Architectures, you have more than one protocol; therefore, some things are different. Check out the following comparison chart, inspired by [Darrel Miller's blog post](https://www.openapis.org/blog/2016/10/03/tdc-structural-improvements-explaining-the-3-0-spec-part-2):

import OpenAPIComparison from '../../../../components/OpenAPIComparison'

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi

To enable more flexibility, the AsyncAPI `3.0.0` specification changes more and is less similar to OpenAPI starting with this version. The biggest change is in the channel structure, where operations are separated from it. It is like detaching operations from paths in OpenAPI. 

import OpenAPIComparisonV3 from '../../../../components/OpenAPIComparisonV3'

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi

Aside from structural differences, you should know:

1. AsyncAPI is compatible with OpenAPI schemas.
1. The message payload in AsyncAPI can be any value, not just an AsyncAPI/OpenAPI schema. For instance, it could be an [Avro](https://avro.apache.org/) schema.
1. The [AsyncAPI server object](/docs/reference/specification/latest#serverObject) is almost identical to its OpenAPI counterpart, with the exception that `scheme` has been renamed to `protocol` and AsyncAPI introduces a new property called `protocolVersion`. AsyncAPI supports multiple protocols, not only HTTP, like in the case of OpenAPI.
1. OpenAPI path parameters and [AsyncAPI channel parameters](/docs/reference/specification/latest#parameterObject) are a bit different since AsyncAPI doesn't have the notion of "query" and "cookie", and header parameters can be defined in the [message object](/docs/reference/specification/latest#messageObject). Therefore, AsyncAPI channel parameters are the equivalent of OpenAPI path parameters.

## Conclusion

As you have seen above, OpenAPI and AsyncAPI are similar, but the specification's evolution will bring more differences in the future. In a real-world environment, systems don't have just REST APIs or events, but a mix of both. Most of the time, the information flowing in the events is very similar to the one the REST APIs have to handle in requests and responses; thus, being able to reuse schemas is a huge win.

Let's learn how to create an AsyncAPI document that defines a "Hello world" application.

---

# Hello world
Source: https://www.asyncapi.com/docs/tutorials/getting-started/hello-world.md

# Hello world

Let's define an application that's capable of receiving a `"hello {name}"` message:

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

Let's get into the details of this sample AsyncAPI document:

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

The first line of the specification starts with the document type `asyncapi` and the version (3.1.0). That line doesn't have to be the first one, but it's a best practice.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

The `info` object contains the minimum required information about the application. It contains the `title`, which is a memorable name for the API, and the `version`. While it's not mandatory, it's strongly recommended to change the version whenever you make changes to the API.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

The `channels` section of the specification houses all of the mediums where messages flow through. For example, some systems use `topic`, `event name` or `routing key`. Different kinds of information flow through each channel similar to the analogy of TV channels.

You only have one channel called `hello`, and you see what message is available in this channel and how it must be structured. The `payload` object defines that the message must be a string and match the given regular expression in a string format such as `hello {name}`.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

The `operations` section is where you describe what the application is doing. Each operation has a unique identifier for example, `receiveHello`.

In the above example, you see that the `Hello world application` is a consumer listening to the `sayHelloMessage` message from the `hello` channel. In other words, you can say that the `Hello world application` subscribes to the `hello` topic to `receive` the `sayHelloMessage` message. That AsyncAPI document describes what the `Hello world application` is doing, not what others can do with it.

---

# Request/reply pattern
Source: https://www.asyncapi.com/docs/tutorials/getting-started/request-reply.md

# Request/reply pattern

In this tutorial, you'll learn how to implement the request/reply pattern in an AsyncAPI document using a straightforward ping-pong example.

Before we begin, it would be beneficial for you to have a basic understanding of AsyncAPI and Event-Driven Architectures (EDA). If you need a refresher, refer to our [Event-Driven Architecture](/docs/tutorials/getting-started/event-driven-architectures.md) document.

[Request/reply](https://www.enterpriseintegrationpatterns.com/patterns/messaging/RequestReply.html) is a messaging pattern involving two key components: the **requester**, which sends a request message, and the **replier**, responsible for receiving this request and responding with a reply. This pattern fundamentally revolves around these two roles, requester and replier.

## Static reply address 

Here's how you can implement the request/reply pattern when the response address is known at the compile or design time. 

A requester can be configured with the `send` operation, where it dispatches a message to the `ping` channel and anticipates receiving a response through the `pong` channel.

In the below example, the `Operation Reply` object within the `pingRequest` operation provides essential details, like the destination for the reply, which is the `pong` channel. Since the `pong` channel is configured with only one message, there's no need to explicitly define the reply message. Similarly, the `ping` channel has just one message, eliminating the need to specify the message sent in the request.

```yaml
asyncapi: 3.1.0
info:
  title: Ping/pong example with static reply channel
  version: 1.0.0
  description: Requester example that initiates the request/reply pattern on a different channel than the reply is using
channels:
  ping:
    address: /ping
    messages:
      ping:
        $ref: '#/components/messages/ping'
  pong:
    address: /pong
    messages:
      pong:
        $ref: '#/components/messages/pong'
operations:
  pingRequest:
    action: send
    channel: 
      $ref: '#/channels/ping'
    reply:
      channel: 
        $ref: '#/channels/pong'
components: 
  messages: 
    ping:
      payload:
        type: object
        properties:
          event:
            type: string
            const: ping
    pong:
      payload:
        type: object
        properties:
          event:
            type: string
            const: pong
```

## Dynamic reply address 

Occasionally, the destination for a reply cannot be predetermined during the design or compile phase. In such cases, the address for the reply is dynamically determined at runtime, allowing for more flexible and adaptive communication.

In scenarios where the address or reply channel is unknown at design time, the `address` property can either be set to `null` or omitted entirely. To define the reply address dynamically, the `Operation Reply Address` object can be used, allowing for runtime expressions. That enables the `requester` to specify where the `replier` should send the reply, detailing the address's location and its specific position within the request.

In this situation, the `location` property is assigned the runtime expression `$message.header#/replyTo`. Such an expression indicates that the address for the reply is located within the header of the request, specifically in the `replyTo` field. This method dynamically determines the reply address based on the content of the request header.

```yaml
asyncapi: 3.1.0
info:
  title: Ping/pong example with reply specified as dynamic information provided in the runtime
  version: 1.0.0
  description: Example document for an application that processes ping requests and replies to the address dynamically specified by the requestor in the message header
channels:
  ping:
    address: /ping
    messages:
      ping:
        $ref: '#/components/messages/ping'
  pong:
    address: null
    messages:
      pong:
        $ref: '#/components/messages/pong'
operations:
  pingRequest:
    action: receive
    channel: 
      $ref: '#/channels/ping'
    reply:
      address:
        description: Reply is sent to topic specified in 'replyTo' property in the message header
        location: "$message.header#/replyTo"
      channel: 
        $ref: '#/channels/pong'
components:
  messages:
    ping:
      headers:
        type: object
        properties:
          replyTo:
            type: string
            description: Provide path to which reply must be provided
          requestId:
            type: string
            format: uuid
            description: Provide request id that you will use to identify the reply match
      payload:
        type: object
        properties:
          event:
            type: string
            const: ping
      correlationId:
        $ref: "#/components/correlationIds/pingCorrelationId"
    pong:
      headers:
        type: object
        properties:
          requestId:
            type: string
            format: uuid
            description: Reply message must contain id of the request message
      payload:
        type: object
        properties:
          event:
            type: string
            const: pong
      correlationId:
        $ref: "#/components/correlationIds/pingCorrelationId"
  correlationIds:
    pingCorrelationId:
      location: '$message.header#/requestId'
```

While the above examples are a simple implementation of the request/reply pattern, in a protocol-agnostic world there are many different ways to represent the request/reply pattern. All of which are supported by AsyncAPI.

---

# AsyncAPI documents
Source: https://www.asyncapi.com/docs/tutorials/getting-started/asyncapi-documents.md

# AsyncAPI documents

An AsyncAPI document is a file that defines and annotates the different components of **a specific Event-Driven API**.

The file format must be JSON or YAML; however, only the subset of YAML that matches the JSON capabilities is allowed.

```yaml
asyncapi: 3.1.0
info:
  title: Example application
  version: '0.1.0'
channels:
  userSignup:
    address: 'user/signedup'
    messages:
      userSignedupMessage: 
        description: A message describing that a user just signed up.
        payload:
          type: object
          additionalProperties: false
          properties:
            fullName:
              type: string
            email:
              type: string
              format: email
            age:
              type: integer
              minimum: 18
operations:
  publishUserSignedup:
    action: 'send'
    channel:
      $ref: '#/channels/userSignup'
```

The AsyncAPI document is a machine-readable definition of your Event-Driven API. That document can be used afterward to generate documentation and code, validate the messages that `Example application` sends, and even apply API management policies to your messages before they arrive at the broker.

Your API documentation is now machine-readable (easily parseable by code) so the myriad of useful applications is endless.

---

# Servers
Source: https://www.asyncapi.com/docs/tutorials/getting-started/servers.md

# Servers

In the previous lesson, you learned how to create the definition of a simple [Hello World application](/docs/getting-started/hello-world). Let's take it from there.

In this tutorial, you'll learn how to add `servers` to your AsyncAPI document. Adding and defining servers is useful because it specifies where and how to connect. The connection facilitates where to send and receive messages.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
servers:
  production:
    host: broker.mycompany.com
    protocol: amqp
    description: This is "My Company" broker.
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        payload:
          type: string
          pattern: '^hello .+$'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
```

You've now added a new section called `servers` in your AsyncAPI document.

You might have noticed that our example mentions `amqp`, a very common protocol that was popularized by RabbitMQ (among others). While our example uses `amqp`, you can use any protocol. The most common protocols used are `mqtt` (widely adopted by the Internet of Things and mobile apps), `kafka` (popular for its streaming solution), `ws` (WebSockets are frequently used in browsers), and `http` (used in HTTP streaming APIs).

> **Remember**
>
> The `servers` section defines where your application should connect to start sending and receiving messages. 
> 
> 1. If you are using a broker-centric architecture such as Kafka or RabbitMQ, specify the broker URL. 
> 2. If you have the classic client-server model such as for REST APIs, then your `server` should be the URL of the server.

## Conclusion

Now you know where the `Hello world application` connects to, and you can start receiving `hello {name}` messages.

In the next section, you'll learn how to add security requirements to your server.

---

# Adding security
Source: https://www.asyncapi.com/docs/tutorials/getting-started/security.md

# Adding security

In production environments, your API may have to access a message broker that's protected by some auth mechanisms. 

Auth mechanism examples:
* User & password
* Certificates
* API keys
* OAuth 2

If you're using AsyncAPI to define an API that connects to a message broker, you'll probably use user/password or certificates. Traditionally, message brokers are infrastructure pieces that serve an internal purpose, and they're not exposed to the public. That's why their security mechanisms are also simpler than what we're used to with REST APIs. However, AsyncAPI also helps you define your HTTP streaming APIs, and therefore, it supports more sophisticated mechanisms like OAuth2 or OpenID. 

Continuing with the `hello world` application example, let's learn how to define a simple security scheme (mechanism) for it.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
servers:
  production:
    host: broker.mycompany.com
    protocol: amqp
    description: This is "My Company" broker.
    security:
      - type: userPassword
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        $ref: '#/components/messages/hello-msg'
  goodbye:
    address: 'goodbye'
    messages:
      sayGoodbyeMessage:
        $ref: '#/components/messages/goodbye-msg'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
  receiveGoodbye:
    action: 'receive'
    channel:
      $ref: '#/channels/goodbye'
components:
  messages:
    hello-msg:
      payload:
        type: object
        properties:
          name:
            type: string
          sentAt:
            $ref: '#/components/schemas/sent-at'
    goodbye-msg:
      payload:
        type: object
        properties:
          sentAt:
            $ref: '#/components/schemas/sent-at'
  schemas:
    sent-at:
      type: string
      description: The date and time a message was sent.
      format: datetime
```

The example above shows how to specify that your server (a RabbitMQ broker) requires a user and a password to establish a connection. Let's break this down.

There's a property in the server object called `security`. It's an array and can contain multiple security mechanisms. You chose to specify only one mechanism which is `userPassword`.

A best practice is to put security details inside the `components.securitySchemes` section as it enables reusability across multiple servers. Below, you can see the same example, but this time, under server security, you see that `$ref` links to more security details located under the `user-password` object in `securitySchemes`.

```yaml
asyncapi: 3.1.0
info:
  title: Hello world application
  version: '0.1.0'
servers:
  production:
    host: broker.mycompany.com
    protocol: amqp
    description: This is "My Company" broker.
    security:
      - $ref: "#/components/securitySchemes/user-password"
channels:
  hello:
    address: 'hello'
    messages:
      sayHelloMessage:
        $ref: '#/components/messages/hello-msg'
  goodbye:
    address: 'goodbye'
    messages:
      sayGoodbyeMessage:
        $ref: '#/components/messages/goodbye-msg'
operations:
  receiveHello:
    action: 'receive'
    channel:
      $ref: '#/channels/hello'
  receiveGoodbye:
    action: 'receive'
    channel:
      $ref: '#/channels/goodbye'
components:
  messages:
    hello-msg:
      payload:
        type: object
        properties:
          name:
            type: string
          sentAt:
            $ref: '#/components/schemas/sent-at'
    goodbye-msg:
      payload:
        type: object
        properties:
          sentAt:
            $ref: '#/components/schemas/sent-at'
  schemas:
    sent-at:
      type: string
      description: The date and time a message was sent.
      format: datetime
  securitySchemes:
    user-password:
      type: userPassword
```

> **Hint**
>
> Learn more about the several kinds of <span className="text-teal-600 font-medium hover:underline cursor-pointer">security schemes</span>.

## Conclusion

You can now define what security mechanisms your application needs to connect to the server. You've also seen how to require a user and a password, which is the most common use case.

At this point, you know AsyncAPI well enough to create a simple `Hello world application`. However, real use cases are more complicated than that. The following tutorials can teach you how to create real-world use cases from zero to production.

---

# Create AsyncAPI document
Source: https://www.asyncapi.com/docs/tutorials/create-asyncapi-document.md

# Create AsyncAPI document

> In this tutorial, you'll learn how to create an AsyncAPI document.

## Introduction

In this tutorial, you'll learn how to create an AsyncAPI document based on a sample real-world use case. Additionally, you will learn about event-driven architecture, message brokers, pub/sub pattern.

Let's pretend you have a company called Smarty Lighting, and you install smart-city streetlight lighting systems. Such a smart lighting system is an Internet of Things (IoT) use case. You will create a Smarty Lighting Streetlights application using Node.js and Mosquitto (MQTT) as the message broker. Your application will allow you to manage city lights remotely. 

You want to build a system that can turn streetlights on and off based on their environmental conditions: 

- You will implement an event-driven architecture (EDA) with a message broker in its "center."

- The Streetlights application will receive information about environmental lighting conditions.

- The Streetlights application will connect to the broker and receive a stream of events from all the streetlights devices reporting their conditions.

- The Streetlights application is unaware of how many streetlights devices send measurement events to the broker; it just connects to the broker and receives all events.

## Background context

Event-driven architecture (EDA) is a design pattern built around the production, detection, and reaction to events that take place in time. In this pattern, a message broker, event publishers, and subscribers are its main components for event exchange within microservices.

[Message brokers](/docs/tutorials/getting-started/event-driven-architectures.md#message-broker) enables asynchronous communications between services so that the sending service need not wait for the receiving service’s reply. That allows interdependent services to “talk” with one another directly, even if they were written in different languages or implemented on different platforms. 

Furthermore, the [Pub/sub](/docs/tutorials/getting-started/event-driven-architectures.md#publishersubscriber) is appealing for IoT use cases due to two key features: support for flexible coupling between publishers/subscribers and inherent support for point-to-multipoint transmission.  

[MQTT](https://mqtt.org/), is a well-known protocol that is widely used in IoT applications because it was created particularly to address machine-to-machine (M2M) communication.

## Create AsyncAPI document

In this step, you will create an AsyncAPI document to describe the Streelights application. It will help you generate the code and the documentation later on.

To create one, you can either use the [AsyncAPI Studio](https://studio.asyncapi.com) or the [AsyncAPI CLI](https://github.com/asyncapi/cli), depending on your project's needs.

> **Remember**
>
> You can create a new `asyncapi.yaml` document by running: 
> `asyncapi new --example=tutorial.yml --no-tty`.

Create the following specification document titled `asyncapi` with a `.yaml` extension.

```yaml
asyncapi: 3.1.0
info:
  title: Streetlights App
  version: '1.0.0'
  description: |
    The Smartylighting Streetlights application allows you
    to remotely manage the city lights.
  license:
    name: Apache 2.0
    url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
  mosquitto:
    host: test.mosquitto.org
    protocol: mqtt
channels:
  lightMeasured:
    address: 'light/measured'
    messages:
      lightMeasuredMessage:
        name: LightMeasured
        payload:
          type: object
          properties:
            id:
              type: integer
              minimum: 0
              description: ID of the streetlight.
            lumens:
              type: integer
              minimum: 0
              description: Light intensity measured in lumens.
            sentAt:
              type: string
              format: date-time
              description: Date and time when the message was sent.
operations:
  onLightMeasured:
    action: 'receive'
    summary: Information about environmental lighting conditions for a particular streetlight.
    channel:
      $ref: '#/channels/lightMeasured'
```

Let's break the above code snippet down into pieces:

```yaml
asyncapi: 3.1.0
info:
  title: Streetlights App
  version: '1.0.0'
  description: |
    The Smartylighting Streetlights application allows you
    to remotely manage the city lights.
  license:
    name: Apache 2.0
    url: 'https://www.apache.org/licenses/LICENSE-2.0'
```

- The `asyncapi` field indicates you use the AsyncAPI version 3.1.0.

- The `info` field holds information about the Streetlights application. Here, the title, version, description, and license were defined.

Moving on, let's talk about the `servers` section:

```
servers:
  mosquitto:
    host: test.mosquitto.org
    protocol: mqtt
```
 

In this section, you point to the Eclipse Mosquitto message broker. The `url` points to a real broker instance [hosted by the Mosquitto community](https://test.mosquitto.org/), and the `protocol` is MQTT. If you do not want to use the test instance, you can spin up your own broker locally with `docker run -it -p 1883:1883 eclipse-mosquitto:1.5`. Remember to change the `url` to `mqtt://localhost`.

Now, let's move on to the `channels` section. In the `servers` section, you specified how to connect to the broker where the application sends messages to or receives messages from. In `channels`, you go into more details about the connection `address` inside the broker. (Example: A topic name that specifies what `messages` are available in the channel.)

```
channels:
  lightMeasured:
    address: 'light/measured'
    messages:
      lightMeasuredMessage:
        name: LightMeasured
        payload:
          redacted for brevity
```

In this example, `light/measured` is the channel address. From the Streetlight application example perspective, it means that `light/measured` is the topic's name in the MQTT broker.

Next is the payload property. It is used to understand how the event should look like when publishing to that channel

```
      payload:
        type: object
        properties:
          id:
            type: integer
            minimum: 0
            description: Id of the streetlight.
          lumens:
            type: integer
            minimum: 0
            description: Light intensity measured in lumens.
          sentAt:
            type: string
            format: date-time
            description: Date and time when the message was sent.
```

The `payload` property defines the event's content using AsyncAPI schemas. It means that your event payload should contain an `id` and a `lumens` property —which are integers bigger than zero—and a `sentAt` property which should be a string containing a date and time.

>  JSON Schema Draft 07 is 100% compatible with AsyncAPI schemas. You can also use other standards to describe payload schema, such as [Avro](https://github.com/asyncapi/avro-schema-parser#usage).

The last section is `operations`, where you describe what the application described in the AsyncAPI document is doing. 

```
operations:
  onLightMeasured:
    action: 'receive'
    summary: Information about environmental lighting conditions for a particular streetlight.
    channel:
      $ref: '#/channels/lightMeasured'
```

You can see that the Streetlight application is a consumer that only receives events from the broker. Using the mandatory `channel` field, you specify with `$ref` what channel the events come from.

The `onLightMeasured` key property describes the function or method name that takes care of this functionality in the generated code. It is a unique ID of the operation across the whole document.

## Summary

In this tutorial, you learned how to create an AsyncAPI specification document via a real-life example with an IoT use case.

Your finished document is just a starting point; you must add your business logic. Take some time to play with it. There are still lots of things to be covered, but the intent of this tutorial is to make it simple for you to get an idea of the potential.

## Next steps
Now that you've completed this tutorial, you can proceed to learn how to [validate your AsyncAPI document with AsyncAPI Studio](https://www.asyncapi.com/docs/tutorials/studio-document-validation).

---

# Generate code
Source: https://www.asyncapi.com/docs/tutorials/generate-code.md

# Generate code

> In this tutorial, you'll learn how to generate code from your AsyncAPI document.

## Introduction

In this tutorial, you'll learn how to generate an application that uses the [Glee](https://github.com/asyncapi/glee) framework. You'll do it with an AsyncAPI document and the [AsyncAPI CLI](/tools/cli).

## Background context
[Glee](https://github.com/asyncapi/glee) is a TypeScript/JavaScript framework that enables you to create APIs and messaging clients based on your AsyncAPI document. Instead of generating code, this framework tightly integrates with your AsyncAPI document and binds functions to specific AsyncAPI operations. You only have to provide the code for these functions and Glee handles the rest.

Glee is often used with the [AsyncAPI CLI](/tools/cli) for a better development experience.

In the previous tutorial, you created an AsyncAPI document that is used in this tutorial.

> **Remember**
>
> If you did not follow the previous tutorial and do not have an `asyncapi.yaml` file for overview, then generate one by running the following command using the AsyncAPI CLI: 
> `asyncapi new --example=tutorial.yml --no-tty`.

## Installation guide

### Prerequisites

- [Node.js](https://nodejs.org/en/download/) <b>16 or higher</b> installed, which enables installation of the required dependencies using <b>npm</b>.

### CLI Installation

> **Remember**
>
> Follow the [AsyncAPI CLI installation](https://github.com/asyncapi/cli#installation) instructions below, based on your computer’s operating system.
> 
> <details>
> <summary>macOS</summary>
> 
> - **Using `brew`**: You can install in macOS via brew: `brew install asyncapi`.
> - **Using `pkg`**: Each release of CLI produces a macOS dedicated pkg file that enables you to
>   install this CLI as macOS application.
> 
>   ```sh
>   # Download the latest release
>   curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x64.pkg
>   # Download a specific release
>   # curl -OL https://github.com/asyncapi/cli/releases/download/<version>/asyncapi.x64.pkg
>   # All releases are listed in https://github.com/asyncapi/cli/releases
>   #
>   # Install AsyncAPI CLI
>   sudo installer -pkg asyncapi.x64.pkg -target /
>   ```
> 
> </details>
> 
> <details>
> <summary>Linux</summary>
> 
> You can install in Linux via `dpkg`, a debian package manager:
> 
> ```sh
> curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.deb
> sudo dpkg -i asyncapi.deb
> ```
> 
> </details>
> 
> <details>
> <summary>Windows</summary>
> 
> For Windows, install the appropriate installer and follow the default installation steps to complete the installation process.
> 
> - For 64-bit, download the [asyncapi.x64.exe](https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x64.exe)
> - For 32-bit, download the [asyncapi.x86.exe](https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x86.exe)
> 
> </details>
> 
> <details>
> <summary>Other OS</summary>
> 
> [Read further AsyncAPI CLI installation instructions for different operating systems](https://github.com/asyncapi/cli#installation).
> 
> </details>

#### Using npm and Node.js

You can install the [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) with Node.js 16 or higher and [npm](https://nodejs.org/en/download/package-manager/).

<details>
<summary>Install CLI globally</summary>

Install AsyncAPI CLI _globally_ with the following command:

```sh
npm install -g @asyncapi/cli
```

</details>

<details>
<summary>Install specific CLI version</summary>

To install a specific version of the AsyncAPI CLI, pass the `version` during installation:

```sh
npm install -g @asyncapi/cli@{version}
```

</details>

## Create a Glee project

1. Trigger the creation of the Glee project:
    
```bash
asyncapi new glee --name=tutorial --template=tutorial
```

    Let's break down the previous command:
    - `asyncapi new glee` is how you use Glee via the AsyncAPI CLI. 
    - `--name=tutorial` is how you tell the AsyncAPI CLI to name your new Glee project. 
    - `--template=tutorial` is how you tell the AsyncAPI CLI to use the template of a Glee project that was created specifically for this tutorial. 

2. List all files in the directory and confirm your Glee project creation:
    
```bash
cd tutorial && ls
```

    Upon execution of the command above, the following is an example of the expected result:
    
```bash
$ ls
    LICENSE
    README.md
    asyncapi.yaml
    functions
    package.json
```

## Start generated application
1. Install dependencies of the newly generated application:
    
```bash
npm install
```

2. Start the application:
    
```bash
npm run dev
```

## Send message to broker
1. In another terminal install the MQTT.js library:
    
```bash
npm install mqtt -g
```

2. Send a message to the MQTT broker that's connected to your generated application. Run the following MQTT client command:
    
```bash
mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}'
```

3. Go back to the previous terminal to check if your application logged the streetlight condition you just sent. You should see something like this displayed in the terminal:
    
```bash
lightMeasured was received from mosquitto:
    { id: 1, lumens: 3, sentAt: '2017-06-07T12:34:32.000Z' }
    Streetlight with id "1" updated its lighting information to 3 lumens at 2017-06-07T12:34:32.000Z.
```

## Summary
In this tutorial, you learned how to create a Glee project from the [Streetlights API specification document created in a previous tutorial](https://asyncapi.com/docs/tutorials/create-asyncapi-document). 

Additionally, you've learned how to run your code by installing the project's dependencies and sending several test messages to the Streelights application using the MQTT client.

## Next steps
Now that you've completed this tutorial, go ahead and learn how to [validate your AsyncAPI messages (events)](https://asyncapi.com/docs/tutorials/message-validation) through the message validation techniques supported by AsyncAPI.

---

# Validate AsyncAPI document with Studio
Source: https://www.asyncapi.com/docs/tutorials/studio-document-validation.md

# Validate AsyncAPI document with Studio

> In this tutorial, you'll learn how to validate AsyncAPI documents using the AsyncAPI Studio tool.

## Introduction
In this tutorial, you'll learn how to validate AsyncAPI documents using the [AsyncAPI Studio tool](https://studio.asyncapi.com/).

You will start with a broken AsyncAPI document and troubleshoot via console errors step-by-step until you end up with a valid AsyncAPI document. This process will illustrate identifying [`REQUIRED` properties in AsyncAPI documents](https://www.asyncapi.com/docs/reference/specification/latest#A2SObject).

## Background context
An AsyncAPI document is a file that defines and annotates the different components of a specific Event-Driven API. The format of the file must be JSON or YAML. You can use this document to generate both documentation and code.

The AsyncAPI Studio tool allows you to develop an AsyncAPI document, validate it, preview it, convert it to the latest version, and visualize event flows.

Now let's experiment with an invalid file to see how errors are displayed and how to make that file valid again.

## Copy invalid AsyncAPI document
Let's pretend you have an invalid AsyncAPI document.

1. Open [Studio](https://studio.asyncapi.com/).

> **Remember**
>
> You can also skip the step below by clicking on New File in Studio and opening the Invalid Example template in the tutorials section.

2. Copy and paste the below invalid AsyncAPI document:

```yaml
asyncapi: 3.1.0
info:
  title: Streetlights API
  version: '1.0.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'

servers:
  mosquitto:
    url: test.mosquitto.org
    protocol: mqtt

channels:
  lightMeasured:
    address: 'light/measured'
    messages:
      lightMeasuredMessage:
        name: LightMeasured
        payload:
          type: object
          properties:
            id:
              type: integer
              minimum: true
              description: Id of the streetlight.
            lumens:
              type: integer
              minimum: 0
              description: Light intensity measured in lumens.
            sentAt:
              type: string
              format: date-time
              description: Date and time when the message was sent.

operations:
  onLightMeasured:
    action: 'receive'
    summary: Inform about environmental lighting conditions for a particular streetlight.
    channel:
      $ref: '#/channels/lightMeasured'
``` 
 
## Troubleshoot Studio errors
Let's fix the errors one by one until you end up with a valid AsyncAPI document.
 
1. You can see the error message on the screen: `Empty or invalid document. Please fix errors/define AsyncAPI document.`

2. Open **DIAGNOSTICS**, you can see more information related to your errors.

3. Fix the incorrect server information. Use `host` instead of `url`
 
```yaml
servers:
  mosquitto:
    host: test.mosquitto.org
    protocol: mqtt
```

> **Remember**
>
> Notice how <b>description</b> property is missing; that doesn't make the AsyncAPI document invalid, but it's always better to include.

4. Read the next error: `"minimum" property type must be number`. Fix the `minimum` by changing it to: `0`.

```yaml
          properties:
            id:
              type: integer
              minimum: 0
``` 
5. Congratulations! You identified and fixed all the errors, and now have a valid AsyncAPI document.

## Summary
In this tutorial, you learned how to validate an AsyncAPI document using the AsyncAPI Studio tool. You also learned to troubleshoot an invalid AsyncAPI document by following the error message directions in diagnostics. In doing so, you learned how to identify `REQUIRED` properties in all AsyncAPI documents.

## Next steps
Now that you have completed this tutorial, go ahead to learn [generate AsyncAPI messages (events)](/docs/tutorials/generate-code.md) which you will be sending to your application.

You may also enjoy reading our [AsyncAPI document validation guide](/docs/guides/validate.md).

---

---

# Message validation in runtime
Source: https://www.asyncapi.com/docs/tutorials/message-validation.md

# Message validation in runtime

> In this tutorial, you'll learn how to validate AsyncAPI messages (events).

## Introduction
In this tutorial, you'll learn how to validate messages (events) that are sent to your AsyncAPI application.

## Background context
Message validation can be performed at both the **producer** and **consumer** levels. Message validation requires the participation of the producer, consumer, and broker. We will learn how to validate messages at the consumer level by discarding invalid messages based on the parameters provided.

You will be using the [Eclipse Mosquitto](https://mosquitto.org/) broker. The MQTT protocol provides a lightweight method of messaging using a publish/subscribe model. You will also use an MQTT client that runs an MQTT library and connects to an MQTT broker over a network. Here producers and consumers are MQTT clients. The producer and consumer labels refer to whether the client is sending or receiving messages.

In the [previous tutorial, you generated an application](https://asyncapi.com/docs/tutorials/generate-code) that uses [Glee](https://github.com/asyncapi/glee) framework. Now you will be validating the messages that you will be sending to your application using a Mosquitto broker and an MQTT client.

> **Remember**
>
> If you did not follow the previous tutorial and do not have an application generated, then follow these instructions: 
> 
>     asyncapi new glee --name=tutorial --template tutorial`.
>     cd tutorial && npm install

## Validate messages
In this step, you will send a message to your application using an MQTT broker and check the errors logged when you accidentally send an invalid message.

1. Start your generated application:

```bash
npm run dev
```

2. Send a message:

```bash
mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": "3", "sentAt": "2017-06-07T12:34:32.000Z"}'
```

Go back to the previous terminal and check if your application logged the streetlight condition you just sent, with errors related to the invalid message. You should see something displayed in the terminal similar to the following:

```bash
lightMeasured was received from mosquitto:
{ id: 1, lumens: '3', sentAt: '2017-06-07T12:34:32.000Z' }
x You have received a malformed event or there has been error processing it. Please review the error below:
TYPE should be integer
 
  1 | {
  2 |   "id": 1,
> 3 |   "lumens": "3",
    |             ^^^ 👈🏽  type should be integer
  4 |   "sentAt": "2017-06-07T12:34:32.000Z"
  5 | }
 
ONEOF should match exactly one schema in oneOf
 
> 1 | {
    | ^
> 2 |   "id": 1,
    | ^^^^^^^^^^
> 3 |   "lumens": "3",
    | ^^^^^^^^^^
> 4 |   "sentAt": "2017-06-07T12:34:32.000Z"
    | ^^^^^^^^^^
> 5 | }
    | ^^ 👈🏽  oneOf should match exactly one schema in oneOf
```

Here, you can see that the property `lumens` has type `integer`, but you are sending a message with type `string`:

```yaml
  message:
        name: lumensInfo
        payload:
          type: object
          properties:
            id:
              type: integer
              minimum: 0
              description: Id of the streetlight.
            lumens:
              type: integer
              minimum: 0
              description: Light intensity measured in lumens.
```

3. Send a correct message to your application:

```bash
mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}'
```

You can see that your generated application received a message in the terminal:

```bash
lightMeasured was received from mosquitto:
{ id: 1, lumens: 3, sentAt: '2017-06-07T12:34:32.000Z' }
Streetlight with id "1" updated its lighting information to 3 lumens at 2017-06-07T12:34:32.000Z.
```

Such a terminal message indicates that your message is valid and the application received it correctly.

## Summary
In this tutorial, you learned how to connect your generated application to an MQTT broker, send messages through it, identify when an invalid message is sent to your application, and how to correct an invalid message. 

## Next steps
Now that you've completed this tutorial, enjoy our [AsyncAPI message validation guide](https://www.asyncapi.com/docs/guides/message-validation).

---

# Streetlights - Interactive
Source: https://www.asyncapi.com/docs/tutorials/streetlights-interactive.md

# Streetlights - Interactive

> Interactive version of the original Streetlights tutorial.

> Check out the [Streetlights interactive tutorial](https://killercoda.com/asyncapi/scenario/streetlight-tut-v3); we plan to have more docs written this way! Our interactive tutorials on [KillerCoda](https://killercoda.com) work for everyone, regardless of your operating system. 

1. Go through the [Streetlights interactive tutorial](https://killercoda.com/asyncapi/scenario/streetlight-tut-v3).
2. Share your opinion via your preferred channel:
   - [Slack](https://www.asyncapi.com/slack-invite/)
   - [Twitter](https://twitter.com/AsyncAPISpec)
   - [GitHub Issue](https://github.com/asyncapi/website/issues/)

---

# Create an AsyncAPI document for a Slackbot with WebSocket
Source: https://www.asyncapi.com/docs/tutorials/websocket.md

# Create an AsyncAPI document for a Slackbot with WebSocket

> In this tutorial, you'll learn how to create an AsyncAPI document designed for a Slack application that operates in Socket Mode using the WebSocket protocol.

## Introduction
In this tutorial, you will learn how to write an AsyncAPI document designed for a Slack application that operates in Socket Mode. The aim is to help you grasp a real-world application of AsyncAPI with the WebSocket protocol. You will learn how to write an AsyncAPI document for a consumer-only application receiving a stream of messages from a WebSocket server. You will also learn why the AsyncAPI bindings feature exists and how to use it.

Consider a scenario where you are in charge of maintaining a highly active Slack workspace. You want an easy way to keep track of the popular messages across all channels, but doing this manually would be difficult. To simplify this process, you will build a Slackbot called `Heart-Counter` that actively monitors reactions added to a message and determines its popularity by counting the reactions of the “heart” emoji.

Here’s a visual representation of how the `Heart-Counter` should work: 

```mermaid
sequenceDiagram
participant Heart-Counter
participant Slack Server (Socket Mode)
participant User

Heart-Counter ->>Slack Server (Socket Mode): Connect
Note right of Heart-Counter: Establish WebSocket connection

Slack Server (Socket Mode)->> Heart-Counter : Handshake
Note left of Slack Server (Socket Mode): Establish Socket Mode connection

Slack Server (Socket Mode)->> Heart-Counter : Sends "hello" event
Note left of Slack Server (Socket Mode): Confirms successful connection

User-->>Slack Server (Socket Mode): Adds emoji to a message.

Slack Server (Socket Mode)->>Heart-Counter: Sending "reaction_added" payload

Note left of Heart-Counter: Event received
``` 

## Background context
[WebSocket](https://en.wikipedia.org/wiki/WebSocket) is a communication protocol that enables simultaneous bidirectional data exchange between a client and a server over a single, long-lived connection. Unlike HTTP, which relies on the request-response model, WebSocket is ideal for scenarios where real-time, interactive, and low-latency communication is necessary.

```mermaid
sequenceDiagram
Client -->> Server: Initiate WebSocket Connection
Server -->> Client: Message 1
Server -->> Client: Message 2
Server -->> Client: Message 3
Server -->> Client: Message 4
```

In Slack, WebSocket is employed as part of its [Socket Mode](https://api.slack.com/apis/connections/socket) feature to facilitate real-time notifications between Slack's servers and third-party applications or bots. The [Slack Event API](https://api.slack.com/apis/connections/events-api) is a tool that lets you receive real-time notifications of specific events in a Slack workspace such as messages, reactions, and user presence changes.

## Define AsyncAPI version, API information, and server

You start your AsyncAPI document by specifying the AsyncAPI version and essential information about your Slack application's API, which includes details such as the `title,` `version,` and `description.`

The `servers` section allows you to define the protocol and specify information about the URLs your application will use, such as  `host`, `pathname`, `protocol`, and `description`.

> **Remember**
>
> The WebSocket URL is generated  by invoking the <a href="https://api.slack.com/methods/apps.connections.open">apps.connections.open</a> method from Slack’s API. You use the authentication tokens obtained during the configuration of your Slackbot to generate this URL.

```yaml
asyncapi: '3.1.0'
info:
  title: Create an AsyncAPI document for a Slackbot with WebSocket
  version: '1.0.0'
  description:  |
    The Heart-Counter manages popular messages in a Slack workspace by monitoring message reaction data
servers:
  production:
    host: wss-primary.slack.com
    pathname: /link
    protocol: wss
    description: Slack's server in Socket Mode for real-time communication 
```

## Define messages and schemas

Your AsyncAPI document needs to be very clear on the type of event it is expected to receive. Here's where the `messages` component steps in. Using the `payload` property, you can specify what these events should look like, their structure, and what content they carry.

The `payload` attribute specifies the name, format, and description of all the expected properties. `Heart-Counter` starts the popularity count of a message by validating if the `reaction` property set in the `reaction` schema definition corresponds to "heart".

```yaml
components:
  messages:
    reaction:
      summary: Action triggered when the channel receives a new reaction-added event
      payload:
        $ref: '#/components/schemas/reaction'
    hello:
      summary: Action triggered when a successful WebSocket connection is established
      payload:
        $ref: '#/components/schemas/hello'
  schemas:
    hello:
      type: object
      properties:
        type:
          type: string
          description: A hello string confirming WebSocket connection
        connection_info:
          type: object
          properties:
            app_id:
              type: string
        num_connections:
          type: integer
        debug_info:
          type: object
          properties:
            host:
              type: string
            started:
              type: string
            build_number:
              type: integer
            approximate_connection_time:
              type: integer
    reaction:
      type: object
      properties:
        user:
          type: string
          description: User ID who performed this event
        reaction:
          type: string
          description: The only reaction that we need is a heart emoji
        item_user:
          type: string
          description: User ID that created the original item that has been reacted to
        item:
          type: object
          properties:
            channel:
              type: string
              description: Channel information of original message
            ts:
              type: string
              description: Timestamp information of original message
        event_ts:
          type: string
          description: Reaction timestamp
```

## Define channels and  bindings

The `channels` attribute defines a communication channel for the event. The `address` specifies where the channel is tuned in to receive messages while the `messages` property defines a key-value pair where each key corresponds to the event it's set up to handle.

The WebSocket URL generated for `Heart-Counter` includes authentication tokens. This information is represented using `query` parameters. Query parameters are specific to HTTP protocol and partially to WebSocket, which uses HTTP to connect client and server. Since this is protocol-specific information, you must use an AsyncAPI feature called `bindings` that enables you to provide protocol-specific information inside the AsyncAPI document using the `bindings` attribute. By utilizing the `query` object from the WebSocket binding, you can outline the parameters needed for the connection and the conditions they must meet. 

```yaml
channels:
  root:
    address: /
    messages:
      hello:
        $ref: '#/components/messages/hello'
      reaction:
        $ref: '#/components/messages/reaction'
    bindings:
      ws:
        query:
          type: object
          description: Tokens are produced in the WebSocket URL generated from the [apps.connections.open](https://api.slack.com/methods/apps.connections.open) method from Slack’s API
          properties:
            ticket:
              type: string
              description: Temporary token generated when connection is initiated
              const: '13748dac-b866-4ea7-b98e-4fb7895c0a7f'
            app_id:
              type: string
              description: Unique identifier assigned to the Slack app
              const: 'fe684dfa62159c6ac646beeac31c8f4ef415e4f39c626c2dbd1530e3a690892f' 
```

## Define operations 
The `operation` property is all about defining specific tasks your application can perform. Essentially, it's how the `Heart-Counter` interacts with Slack.

In this example, the `helloListener` operation keeps an eye out for the message sent by the Slack server when a WebSocket connection is successfully established. On the other hand, the `reactionListener` is focused on the `reaction_added` event type.

Your Slack application is designed to be notified of events within your workspace. It subscribes to a specific event type and uses Slack's Event API. In this case, both operations' `action` property is set to `receive` events.

```yaml
operations:
  helloListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/hello'
  reactionListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/reaction' 
```

Congratulations, you've completed the tutorial! Putting these blocks together gives you an AsyncAPI document all ready to go.

```yaml
asyncapi: '3.1.0'
info:
  title: Create an AsyncAPI document for a Slackbot with WebSocket
  version: '1.0.0'
  description:  |
    The Heart-Counter manages popular messages in a Slack workspace by monitoring message reaction data.
servers:
  production:
    host: wss-primary.slack.com
    pathname: /link
    protocol: wss
    description: Slack's server in Socket Mode for real-time communication
channels:
  root:
    address: /
    messages:
      hello:
        $ref: '#/components/messages/hello'
      reaction:
        $ref: '#/components/messages/reaction'
    bindings:
      ws:
        query:
          type: object
          description: Tokens are produced in the WebSocket URL generated from the [apps.connections.open](https://api.slack.com/methods/apps.connections.open) method from Slack’s API
          properties:
            ticket:
              type: string
              description: Temporary token generated when connection is initiated
              const: '13748dac-b866-4ea7-b98e-4fb7895c0a7f'
            app_id:
              type: string
              description: Unique identifier assigned to the Slack app
              const: 'fe684dfa62159c6ac646beeac31c8f4ef415e4f39c626c2dbd1530e3a690892f'
operations:
  helloListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/hello'
  reactionListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/reaction'
components:
  messages:
    reaction:
      summary: Action triggered when the channel receives a new reaction-added event
      payload:
        $ref: '#/components/schemas/reaction'
    hello:
      summary: Action triggered when a successful WebSocket connection is established
      payload:
        $ref: '#/components/schemas/hello'
  schemas:
    hello:
      type: object
      properties:
        type:
          type: string
          description: A hello string confirming WebSocket connection
        connection_info:
          type: object
          properties:
            app_id:
              type: string
            num_connections:
              type: integer
            debug_info:
              type: object
              properties:
                host:
                  type: string
                started:
                  type: string
                build_number:
                  type: integer
                approximate_connection_time:
                  type: integer
    reaction:
      type: object
      properties:
        user:
          type: string
          description: User ID who performed this event
        reaction:
          type: string
          description: The only reaction that we need is a heart emoji
        item_user:
          type: string
          description: User ID that created the original item that has been reacted to
        item:
          type: object
          properties:
            channel:
              type: string
              description: Channel information of original message
            ts:
              type: string
              description: Timestamp information of original message
        event_ts:
          type: string
          description: Reaction timestamp 
```

## Summary
In this tutorial, you learned to create an AsyncAPI document for a Slackbot using WebSocket in Socket Mode. You gained practical insights into the functionality of operations, channels, messages, and schemas. Now you're equipped to handle real-world applications that facilitate bidirectional real-time data exchange, such as chatbots and live-streaming platforms.

---

# Implement Request/Reply in an AsyncAPI document for a Slack app
Source: https://www.asyncapi.com/docs/tutorials/websocket/websocket-request-reply.md

# Implement Request/Reply in an AsyncAPI document for a Slack app

> In this tutorial, you'll learn how to write an AsyncAPI document that implements the request/reply feature in a Slack application using the WebSocket protocol.

## Introduction
In the [Create an AsyncAPI Document for a Slackbot with WebSockets](https://www.asyncapi.com/docs/tutorials/websocket) tutorial, you learned how to write an AsyncAPI document for a Slackbot `Heart-Counter`  that actively monitored reactions associated with a message. In this lesson, let's go a step further. After receiving a reaction, `Heart-Counter` responds via a message back to the Slack server through WebSocket to confirm the event reception. 

The interaction where the Slackbot acknowledges the event and replies with a specific response sets the stage for the Request/Reply messaging pattern discussed in this context. 

> Refer to the [Request/Reply pattern tutorial](https://www.asyncapi.com/docs/tutorials/getting-started/request-reply) for an introduction to its implementation. 

```mermaid
sequenceDiagram
participant Heart-Counter
participant Slack Server (Socket Mode)
participant User

User-->>Slack Server (Socket Mode): Adds emoji to a message.

Slack Server (Socket Mode)->>Heart-Counter: Sending "reaction_added" payload
Note left of Heart-Counter: Event received
Heart-Counter->>Slack Server (Socket Mode): Sending acknowledgement
``` 

## Background context

The [Request-Reply Messaging Pattern](https://www.asyncapi.com/docs/concepts/asyncapi-document/reply-info) in AsyncAPI is an exciting and highly anticipated feature.  The messaging pattern mirrors a traditional conversation, where one "requester" entity initiates a query or request, and the "responder" entity provides a specific and expected response.
The messaging pattern can work in both synchronous and asynchronous environments and is very beneficial to decouple components by allowing them to operate independently in a distributed system. 

```mermaid
sequenceDiagram
  participant Client
  participant Server

  Client->>Server: Request
  note right of Client: Continue with other tasks

  Server-->>Client: Acknowledgment
  Server->>Server: Process Request
  Server-->>Client: Reply
```

## Define messages

In the `Heart-Counter` tutorial, you dealt with the `hello` event triggered when the WebSocket connection was established and the `reaction` event expected when a new reaction-added event was triggered.

In this tutorial, you'll add the `acknowledge` message to your AsyncAPI document to represent the acknowledgment sent by the Slack application back to the server to indicate that it has successfully received the message.

```yaml
components:
  messages:
    reaction:
      summary: Action triggered when the channel receives a new reaction-added event
      payload:
        $ref: '#/components/schemas/reaction'
    hello:
      summary: Action triggered when a successful WebSocket connection is established
      payload:
        $ref: '#/components/schemas/hello'
    acknowledge:
      summary: Acknowledgement response sent to Server
      payload:
        $ref: '#/components/schemas/acknowledge' 
```

## Define schemas

Previously, the `reaction` schema was simplified to include the `event` payload. However, in this instance, you will be able to elaborate on the schema for the complete request it is expected to receive.

> **Remember**
>
> The sample request and response payloads are extracted from <a href="https://api.slack.com/apis/connections/socket#events">Slack's official documentation</a>.

```yaml
  schemas:
    hello:
      type: object
      properties:
        type:
          type: string
          description: A hello string confirming WebSocket connection
        connection_info:
          type: object
          properties:
            app_id:
              type: string
        num_connections:
          type: integer
        debug_info:
          type: object
          properties:
            host:
              type: string
            started:
              type: string
            build_number:
              type: integer
            approximate_connection_time:
              type: integer
    reaction:
      type: object
      properties:
        envelope_id:
          type: string
          description: 'Unique ID assigned to payload'
        payload:
          type: object
          description: 'Payload of the reaction added event'
          properties:
            token:
              type: string
            team_id:
              type: string
            event:
              type: object
              properties:
                user:
                  type: string
                  description: User ID who performed this event
                reaction:
                  type: string
                  description: The only reaction that you need is a heart emoji
                item_user:
                  type: string
                  description: |
                    User ID that created the original item that has been reacted
                    to
                item:
                  type: object
                  properties:
                    channel:
                      type: string
                      description: Channel information of original message
                    ts:
                      type: string
                      description: Timestamp information of original message
                event_ts:
                  type: string
                  description: Reaction timestamp
        type:
          type: string
        accepts_response_payload:
          type: boolean 
```

Additionally, you will also be adding the `acknowledge` schema that makes use of the `envelope_id` attribute to send a reply back to Slack acknowledging that event has been received.

```yaml
    acknowledge:
      type: object
      properties:
        envelope_id:
          type: string
          description: 'Unique ID of acknowledged payload'
        payload:
          type: object
          description: 'Optional payload of event' 
```

## Define acknowledge message to channel
Extend the channel the `Heart-Counter` used to include the `acknowledge` message.

```yaml
channels:
  root:
    address: /
    messages:
      hello:
        $ref: '#/components/messages/hello'
      reaction:
        $ref: '#/components/messages/reaction'
      acknowledge:
        $ref: '#/components/messages/acknowledge' 
```

## Define operations

Now you've reached the most important part of the tutorial; it's time to represent the Request/Reply pattern. 

Both `helloListener` and `reactionListener` operations are set to `receive` events. However, in the case of `reactionListener`, you also want to represent the message sent back to the server. This is where the `reply` attribute comes into play. 

Since both the request and reply function happens over the same WebSocket URL, both `channel` values stay the same. However, you can differentiate each operation's message by specifying the messages sent or received. 
Thus, you can say that for a `reaction` message received over the `root` channel, the `reactionListener` operation will reply with the `acknowledge` message over the same channel.

```yaml
operations:
  helloListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/hello'
  reactionListener:
    action: receive
    channel: 
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/reaction'
    reply:
      messages:
        - $ref: '#/channels/root/messages/acknowledge'      
      channel: 
        $ref: '#/channels/root' 
```

Putting all this together, you have your AsyncAPI document ready to go!

```yaml
asyncapi: 3.1.0
info:
  title: Implement Request/Reply in an AsyncAPI document for a Slack app
  version: 1.0.0
  description: >
    The Heart-Counter manages popular messages in a Slack workspace by
    monitoring message reaction data. It also sends an acknowledgment message
    back to the Slack Server to indicate it has received the message.
servers:
  production:
    host: wss-primary.slack.com
    pathname: /link
    protocol: wss
    description: Slack's server in Socket Mode for real-time communication
channels:
  root:
    address: /
    messages:
      hello:
        $ref: '#/components/messages/hello'
      reaction:
        $ref: '#/components/messages/reaction'
      acknowledge:
        $ref: '#/components/messages/acknowledge'
    bindings:
      ws:
        query:
          type: object
          description: >-
            Tokens are produced in the WebSocket URL generated from the
            [apps.connections.open](https://api.slack.com/methods/apps.connections.open)
            method from Slack's API
          properties:
            ticket:
              type: string
              description: Temporary token generated when connection is initiated
              const: 13748dac-b866-4ea7-b98e-4fb7895c0a7f
            app_id:
              type: string
              description: Unique identifier assigned to the Slack app
              const: fe684dfa62159c6ac646beeac31c8f4ef415e4f39c626c2dbd1530e3a690892f
operations:
  helloListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/hello'
  reactionListener:
    action: receive
    channel:
      $ref: '#/channels/root'
    messages:
      - $ref: '#/channels/root/messages/reaction'
    reply:
      messages:
        - $ref: '#/channels/root/messages/acknowledge'
      channel:
        $ref: '#/channels/root'
components:
  messages:
    reaction:
      summary: Action triggered when the channel receives a new reaction-added event
      payload:
        $ref: '#/components/schemas/reaction'
    hello:
      summary: Action triggered when a successful WebSocket connection is established
      payload:
        $ref: '#/components/schemas/hello'
    acknowledge:
      summary: Acknowledgement response sent to Server
      payload:
        $ref: '#/components/schemas/acknowledge'
  schemas:
    hello:
      type: object
      properties:
        type:
          type: string
          description: A hello string confirming WebSocket connection
        connection_info:
          type: object
          properties:
            app_id:
              type: string
        num_connections:
          type: integer
        debug_info:
          type: object
          properties:
            host:
              type: string
            started:
              type: string
            build_number:
              type: integer
            approximate_connection_time:
              type: integer
    reaction:
      type: object
      properties:
        envelope_id:
          type: string
          description: 'Unique ID assigned to payload'
        payload:
          type: object
          description: 'Payload of the reaction added event'
          properties:
            token:
              type: string
            team_id:
              type: string
            event:
              type: object
              properties:
                user:
                  type: string
                  description: User ID who performed this event
                reaction:
                  type: string
                  description: The only reaction that you need is a heart emoji
                item_user:
                  type: string
                  description: |
                    User ID that created the original item that has been reacted
                    to
                item:
                  type: object
                  properties:
                    channel:
                      type: string
                      description: Channel information of original message
                    ts:
                      type: string
                      description: Timestamp information of original message
                event_ts:
                  type: string
                  description: Reaction timestamp
        type:
          type: string
        accepts_response_payload:
          type: boolean
    acknowledge:
      type: object
      properties:
        envelope_id:
          type: string
          description: 'Unique ID of acknowledged payload'
        payload:
          type: object
          description: 'Optional payload of event' 
```

## Summary
Great job getting to the end! In this tutorial, you learned how to create an AsyncAPI document for a use case that implemented the Request-Reply messaging pattern. Now, you can explore this pattern with sub-patterns to see how it works with real-life use cases.

---

# Create AsyncAPI document for applications consuming from Kafka
Source: https://www.asyncapi.com/docs/tutorials/kafka.md

# Create AsyncAPI document for applications consuming from Kafka

> A tutorial teaching how to configure an AsyncAPI document for Kafka messages.

## Introduction

In this tutorial, you will create a schema document for Kafka Messages using AsyncAPI. You will also learn about Event-Driven Architecture, the pub/sub model, and brokers concerning Kafka. 
  
Suppose you have a service publishing data to a Kafka topic whenever a new user signs up on your application.

You want to build a system that tracks users who have signed up for your application. As such, your application will have the following flow:

```mermaid
sequenceDiagram
    participant Your Application (Consumer)
    participant Kafka
    participant Service (Producer)
    participant User
    Your Application (Consumer)->> Kafka: Subscribes to "userSignedUp" topic
    User-->> Service (Producer): Signs Up
    Service (Producer)->> Kafka: Publishes Events
    Kafka->> Your Application (Consumer): Sends "user_signup" message
```    

## Background context

[Event-Driven Architecture (EDA)](/docs/tutorials/getting-started/event-driven-architectures.md) is a design pattern that revolves around the production, detection, and reaction to events over time. It consists of three main components: a message broker, event publishers, and subscribers, which together serve as the backbone for event exchange within different services. 

[Message brokers](/docs/tutorials/getting-started/event-driven-architectures.md#message-broker) facilitate asynchronous communications between services, meaning the sending service doesn't have to wait for the receiving service's response. Multiple services can talk to each other directly, even if they are written in different languages. 

A great example of such a message broker is Apache Kafka. [Apache Kafka](https://kafka.apache.org/) is a distributed event streaming platform thousands of companies use for their event-driven system. Here, a distributed event streaming platform is a system that operates on multiple nodes, providing high availability and fault tolerance.

[Publisher/Subscriber (Pub/Sub)](/docs/tutorials/getting-started/event-driven-architectures.md#publishersubscriber) is a typical model in EDAs, providing flexible coupling between publishers and subscribers. In this model, those who `send` event notifications act as publishers, while those who `receive` the notifications act as the corresponding subscribers.

## Create AsyncAPI document for Kafka messages  

In this section, you’ll create an AsyncAPI document to describe the `UserSignUp` API. The same document can be later used to generate code and documentation as per requirement.

Let's begin by analyzing the document. As you progress in the tutorial, we'll break down each segment, uncovering its purpose and functionality.

```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.

servers:
  centralKafkaServer:
    host: central.mykafkacluster.org:8092
    description: Kafka broker running in a central warehouse
    protocol: kafka
  westKafkaServer:
    host: west.mykafkacluster.org:8092
    description: Kafka broker running in the west warehouse
    protocol: kafka
  eastKafkaServer:
    host: east.mykafkacluster.org:8092
    description: Kafka broker running in the east warehouse
    protocol: kafka

operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'

channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'

components:
  messages:
    userSignedUp:
      payload:
        type: object
        properties:
          userId:
            type: integer
            description: This property describes the id of the user
          userEmail:
            type: string
            description: This property describes the email of the user
```

Let's now break it down into pieces.

### Define AsyncAPI version, API information, and server

First, you must describe your application, including the AsyncAPI version, the info about the document, and the server your application is based on.

```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  centralKafkaServer:
    host: central.mykafkacluster.org:8092
    description: Kafka broker running in a central warehouse
    protocol: kafka
  westKafkaServer:
    host: west.mykafkacluster.org:8092
    description: Kafka broker running in the west warehouse
    protocol: kafka
  eastKafkaServer:
    host: east.mykafkacluster.org:8092
    description: Kafka broker running in the east warehouse
    protocol: kafka
```

In the above snippet:

- The `asyncapi` field indicates that you use AsyncAPI version 3.1.0.
  
- The `info` field provides information about the API. Here the the APIs `title`, `version`, and `description` are being defined.
  
- The `server` field specifies the details of the server, including the `host`, `description`, and the `protocol` that is being used (i.e., Kafka). This section allows you to define multiple clusters or servers, as shown in the provided code block.

> **Remember**
>
> If an application has multiple servers hidden from the user behind a load balancer, then only the address of the load balancer must be included in the AsyncAPI document.

### Define channels

Next, let's move on to the `channels` section. The channel addresses are the topics in Kafka; they are the routes to which your API will send/receive messages. 

```
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
```

In the above code snippet:
  
- The `userSignedUp` object inside `channels` describes the Kafka topic where the application will receive the information and the associated message definition. 
- The `address` field represents the actual name of the Kafka topic and the `messages` field describes the expected messages in that topic.

### Define operations

Now, let's move on to the `operations` section. The `operations` property is used to describe how your application interacts with the defined channels.

```
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
```

In the above code snippet:

- The `onUserSignedUp` object specifies the operation's nature, which occurs when the user signs up. 
- The `action` property indicates that the application will receive the information.
- The `channel` property points to the channel where the operation occurs.

### Define messages and schemas

Finally, you'll define the messages and their payload. The payload defines how the event would look like when it's sent from the channel.

```
components:
  messages:
    userSignedUp:
      payload:
        type: object
        properties:
          userId:
            type: integer
            description: This property describes the ID of the user
          userEmail:
            type: string
            description: This property describes the Email of the user
```

In the above code snippet:

- The `userSignedUp` message is defined which describes the payload (content) of the message.
  
- The `payload` property defines the message content. Your message payload should contain a `userId`, an integer, a `userEmail` property, and a string property.

## Summary

The ability to generate an AsyncAPI document for Kafka is now in your toolkit. You generated an AsyncAPI document that defines the structure of the Kafka messages in a machine-readable format, which makes it easier to maintain event-driven architecture. Try adding your business logic and playing around with it.

## Next steps

Now that you know how to write an AsyncAPI document for Kafka messages using the default schema, let's learn how to create an [AsyncAPI document using Avro Schema instead](/docs/tutorials/kafka/configure-kafka-avro.md).

---

# Describe Kafka message payload using Avro Schema
Source: https://www.asyncapi.com/docs/tutorials/kafka/configure-kafka-avro.md

# Describe Kafka message payload using Avro Schema

> Explore configuring an AsyncAPI document for Kafka messages with Avro Schema.

## Introduction

The previous tutorial on [creating an AsyncAPI document for applications consuming from Kafka](/docs/tutorials/kafka.md) taught you about writing an AsyncAPI document for Kafka messages using the default schema. This tutorial will teach you to write the same document using Avro Schema.

While AsyncAPI schema can be the default choice for describing payloads, many prefer using Avro Schemas to define messages in Kafka. This tutorial teaches you to modify your existing AsyncAPI schema to add Avro schema into your document in both YAML and JSON formats.

## Background context

AsyncAPI is a specification for describing Event-Driven Architectures (EDAs) in a machine-readable format. AsyncAPI schema outlines the format and content specifications that enable a consistent representation of agreements for communication between services in an Event-Driven Architecture.

[Avro](https://avro.apache.org/) is a sophisticated tool in Apache Kafka that handles data communication efficiently. It provides a standardized method for organizing and transmitting data, ensuring that different parts of the system can understand each other effectively. With Avro, there's a common language for messages, promoting compatibility and smooth operation between various components. It's like having a shared rulebook that helps different system parts communicate and exchange information seamlessly.

## Define message payload with Avro Schema directly in AsyncAPI document

Defining message schema with the default schema is already covered in the [previous Kafka tutorial](/docs/tutorials/Kafka). The default choice was the AsyncAPI schema, a JSON Schema superset. Here's an example of what the AsyncAPI schema looks like: 

```
messages:
  userSignedUp:
    payload:
      type: object
      properties:
        userId:
          type: integer
          description: This property describes the ID of the user
        userEmail:
          type: string
          description: This property describes the email of the user
```

Now it's time to shift your focus to defining messages using Avro Schemas directly within your document. 

```
messages:
  userSignedUp:
    payload:
      schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
      schema:
        type: record
        name: UserSignedUp
        namespace: com.company
        doc: User sign-up information
        fields:
          - name: userId
            type: int
          - name: userEmail
            type: string
```

In the above code snippet: 
- The `userSignedUp` message is defined with Avro Schema, using the specified `schemaFormat` and the `schema`.
- Use the `schemaFormat` to indicate that you're using Avro and specify the version of Avro Schema by using a MIME type.
- The `schema` includes a `record` named `UserSignedUp` within the `com.company` namespace. It also describes two fields, `userId` and `userEmail,` defining their data types as `int` and `string`, respectively.

Now let's combine the above Avro Schema with the AsyncAPI document that you created in the previous tutorial. Check out below what an AsyncAPI document fully equipped with Avro Schema looks like!

```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
components:
  messages:
    userSignedUp:
      payload:
        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
        schema:
          type: record
          name: UserSignedUp
          namespace: com.company
          doc: User sign-up information
          fields:
            - name: userId
              type: int
            - name: userEmail
              type: string
```

## Reusing existing Avro Schemas

Occasionally, you might find yourself with an existing set of Avro Schemas. In such cases, instead of repeatedly defining these schemas in your AsyncAPI document, integrate them seamlessly by calling out existing files.

Assume you have a file named `userSchema.json` that encapsulates the Avro Schema that resembles the following:

```
// userSchema.json
{
  "type": "record",
  "name": "UserSignedUp",
  "namespace": "com.company",
  "doc": "User sign-up information",
  "fields": [
    { "name": "userId", "type": "int" },
    { "name": "userEmail", "type": "string" }
  ]
}
```

To seamlessly incorporate this existing Avro schema into your AsyncAPI document, you can use the `$ref` property to reference the path to the JSON file. This way, your AsyncAPI document will incorporate the Avro Schema from the external JSON file, ensuring consistency and interoperability in your Kafka ecosystem. 

```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
components:
  messages:
    userSignedUp:
      payload:
        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
        schema:
          $ref: './userSchema.json'
```

## Summary

In this tutorial, you smoothly updated from the default schema to utilize the capabilities of Avro Schema. The use of Avro Schema with AsyncAPI ensures improved communication in event-driven systems.  Now, you can further experiment by incorporating your business logic and experimenting with more advanced capabilities.

## Next Steps
Now that you know how to write an AsyncAPI document using Avro Schemas, let's learn how to use [Schema Registry with AsyncAPI](/docs/tutorials/kafka/managing-schemas-using-schema-registry.md).

---

# Managing schemas using Schema Registry
Source: https://www.asyncapi.com/docs/tutorials/kafka/managing-schemas-using-schema-registry.md

# Managing schemas using Schema Registry

> A tutorial teaching how to manage schemas using Schema Registry.

## Introduction
In the [previous Kafka and Avro configuration tutorial](/docs/tutorials/kafka/configure-kafka-avro.md), you learned how to add Apache Avro schemas to your AsyncAPI document. Now, you will learn how to save your schema in a central Schema Registry and reuse it.

## Background context
The need for schema management has become increasingly prevalent to handle the evolving complexity of modern Event-Driven Architecture. A Schema Registry is a centralized service that stores and maintains schemas for data exchanged between various components of a modern distributed system. Validating exchanged data maintains data consistency and compatibility. 

While several Schema Registry implementations exist, you will use the [Apicurio Registry](https://www.apicur.io/registry/) for this tutorial. Apicurio Registry is a popular open-source Schema Registry implementation that supports multiple serialization formats and facilitates schema management for diverse data in distributed systems. You will use Apicurio Registry combined with Avro, a language-neutral data serialization system.

## Prerequisites
[Install Docker](https://docs.docker.com/engine/install/) from the official website.

## AsyncAPI document with Avro Schema
The previous tutorial taught you how to write an AsyncAPI document for Kafka messages using the Avro schema. Here's an example of what an AsyncAPI document fully equipped with Avro schema looks like:
```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
components:
  messages:
    userSignedUp:
      payload:
        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
        schema:
          type: record
          name: UserSignedUp
          namespace: com.company
          doc: User sign-up information
          fields:
            - name: userId
              type: int
            - name: userEmail
              type: string
```

### Start Apicurio Registry
Start the Apicurio Registry locally with the following docker command:
   
```
docker run --env CORS_ALLOWED_ORIGINS='*' -it -p 8080:8080 apicurio/apicurio-registry-mem:2.5.8.Final
```

### Upload Avro schema
Once your local instance of Apicurio Registry is running, upload your Avro schema. Open a new terminal window and create an Avro schema artifact with the following command:
   
```
curl \
http://localhost:8080/apis/registry/v2/groups/my-group/artifacts \
-X POST  \
-H "Content-Type: application/json; artifactType=AVRO" \
-H "X-Registry-ArtifactId: UserSignedUp" \
--data @- << EOF
{
  "type": "record",
  "name": "UserSignedUp",
  "namespace": "com.company",
  "doc": "User sign-up information",
  "fields": [
    {
      "name": "userId",
      "type": "int"
    },
    {
      "name": "userEmail",
      "type": "string"
    }
  ]
}
EOF
```

> **Remember**
>
> Download your Avro schema by visiting the following URL: 
> http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp.

### Update schema reference
One alternative is to keep your schema in a separate file, as you learned in the previous tutorial, [describe Kafka message payload using Avro schema](/docs/tutorials/kafka/configure-kafka-avro.md). After uploading your Avro schema, remove the schema from your AsyncAPI document and add a `$ref` pointing to the previous step's URL.
```
$ref: http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp
```

```
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
components:
  messages:
    userSignedUp:
      payload:
        schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0'
        schema:
          $ref: http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp
```

## Summary
In this tutorial, you managed Avro schemas using a centralized schema registry that enables you to share schemas across multiple applications. The good news is that this approach is valid for various other schema types!

## Next steps
Now that you have learned how to manage schemas, check out the [bindings with Kafka tutorial](/docs/tutorials/kafka/bindings-with-kafka.md) to start sending messages between your services.

---

# Kafka bindings
Source: https://www.asyncapi.com/docs/tutorials/kafka/bindings-with-kafka.md

# Kafka bindings

> Learn how to configure Kafka bindings in your AsyncAPI document.

## Introduction

[You learned how to manage schemas with a schema registry in the previous tutorial](/docs/tutorials/kafka/managing-schemas-using-schema-registry.md). This tutorial teaches you how Kafka bindings function by defining Kafka messages and expanding your AsyncAPI document with protocol-specific details.

## Background context

Bindings are essential for event-driven applications because they provide protocol-specific details, abstracting the complexities of message handling from your application's core logic. They enhance the API's clarity and usability by offering setup options and context for different protocols. Bindings include the topics your application reads from or writes to, message formatting, and rules for interacting with multiple data or messages.

In an AsyncAPI document, bindings can be added to various sections like servers, channels, or messages. They contain protocol-specific details unique to each protocol. Binding definitions let you specify functionalities specific to the protocol, which are not covered by AsyncAPI's core features.

You can configure several objects using [Kafka bindings](https://github.com/asyncapi/bindings/tree/master/kafka#readme). However, for the scope of this tutorial, you will focus on four levels of bindings: server bindings, operations binding, channel bindings, and message bindings.

Using the code snippets from the previous tutorial, where you learned [how to manage Avro schemas using a centralized schema registry that enables you to share schemas across multiple applications](/docs/tutorials/kafka/managing-schemas-using-schema-registry.md), you will add configurations for server, operations, channel, and message bindings.

Below, you can find the updated schema reference file you'll use for this tutorial.

```yaml
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
components:
  messages:
    userSignedUp:
      payload:
        schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0'
        schema:
          $ref: http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp
```

## Add server bindings

Server bindings provide protocol-specific configuration details for connecting and interacting with a server. 

Server bindings allow you to specify a `schemaRegistryUrl`, which provides an API URL for a given server where a schema registry was used. A schema registry is a repository for managing and validating messages' schemas. To learn more about schema registry, read the [message validation guide for schema registry](https://www.asyncapi.com/docs/guides/message-validation#schema-registry-validation).

`schemaRegistryVendor` is used optionally to refer to vendors or platforms that provide the schema registry service, in this case, Apicurio Registry. Learn about other fields you can configure under [server bindings](https://github.com/asyncapi/bindings/tree/master/kafka#server-binding-object).

```yaml
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
    bindings:
      kafka:
        schemaRegistryUrl: 'http://localhost:8080/apis/registry/'
        schemaRegistryVendor: 'apicurio'
        bindingVersion: '0.5.0'
```

> Important: `bindingVersion` is the field version of a binding. It specifies the version of the binding specification that is used to describe how an API interacts with Kafka. The `bindingVersion` field is an optional field that is available for all bindings.  

## Add operation bindings

Operation bindings object contains information about the operation representation in Kafka (eg. the way to consume messages).

The operation binding object provides a structured way to describe how a particular operation (publish, subscribe) should behave on a Kafka topic. The `groupid`, for example, is the Id of the consumer group, while the `cliendID` is the Id of the consumer within a consumer group.	

These configurations are vital for distributed message consumption and load balancing among consumers. Learn more about other fields you can configure under [operations binding](https://github.com/asyncapi/bindings/tree/master/kafka#operation-binding-object).

```yaml
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
    bindings:
      kafka:
        bindingVersion: '0.5.0'
        groupId:
          type: string
          enum: ['myGroupId']
        clientId:
          type: string
          enum: ['myClientId']
```

## Add channel bindings

Channel bindings provide protocol-specific information for a particular channel.

These configurations may include information how the Kafka topic has been configured. The Channel Binding Object is part of AsyncAPI's wider bindings architecture, which specifies how the API interacts with the messaging system — in this case, Kafka.

In Kafka, you can specify a given topic's number of partitions or replicas therefore, enabling parallel processing of data or consumers. Learn more about other fields that you can configure under [channel bindings](https://github.com/asyncapi/bindings/tree/master/kafka#channel-binding-object).

```yaml
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
    bindings:
      kafka:
        bindingVersion: '0.5.0'
        partitions: 10
        replicas: 2
        topicConfiguration:
          cleanup.policy: ["delete", "compact"]
          retention.ms: 604800000
          retention.bytes: 1000000000
          delete.retention.ms: 86400000
          max.message.bytes: 1048588
```

## Add message bindings

Message bindings provide protocol-specific information for a specific message. For Kafka topics, this can include how message keys are used, and details about how serialized message data has been encoded. 

For example, the `schemaIdLocation` field, if specified is used to indicate where the schema identifier (ID) for the message payload's schema is located. It is useful for message serialization and deserialization, enabling consumers to understand how to interpret the message payload.

Learn more about other fields that you can configure under [message bindings](https://github.com/asyncapi/bindings/tree/master/kafka#message-binding-object)

```yaml
components:
  messages:
    userSignedUp:
      bindings:
        kafka:
            key:
              type: string
              enum: ['myKey']
            schemaIdLocation: 'payload'
            schemaIdPayloadEncoding: 'apicurio-new'
            schemaLookupStrategy: 'TopicIdStrategy'
            bindingVersion: '0.5.0'
      payload:
        schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0'
        schema:
          $ref: http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp
```

Congratulations, you've completed the tutorial! Putting these blocks together gives you an AsyncAPI document all ready to go.

```yaml
asyncapi: 3.1.0
info:
  title: User Signup API
  version: 1.0.0
  description: The API notifies you whenever a new user signs up in the application.
servers:
  kafkaServer:
    host: test.mykafkacluster.org:8092
    description: Kafka Server
    protocol: kafka
    bindings:
      kafka:
        schemaRegistryUrl: 'http://localhost:8080/apis/registry/'
        schemaRegistryVendor: 'apicurio'
        bindingVersion: '0.5.0'
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
    bindings:
      kafka:
        bindingVersion: '0.5.0'
        groupId:
          type: string
          enum: ['myGroupId']
        clientId:
          type: string
          enum: ['myClientId']
channels:
  userSignedUp:
    description: This channel contains a message per each user who signs up in our application.
    address: user_signedup
    messages:
      userSignedUp:
        $ref: '#/components/messages/userSignedUp'
    bindings:
      kafka:
        bindingVersion: '0.5.0'
        partitions: 10
        replicas: 2
        topicConfiguration:
          cleanup.policy: ["delete", "compact"]
          retention.ms: 604800000
          retention.bytes: 1000000000
          delete.retention.ms: 86400000
          max.message.bytes: 1048588
components:
  messages:
    userSignedUp:
      bindings:
        kafka:
          bindingVersion: '0.5.0'
          key:
            type: string
            enum: ['myKey']
          schemaIdLocation: 'payload'
          schemaIdPayloadEncoding: 'apicurio-new'
          schemaLookupStrategy: 'TopicIdStrategy'
      payload:
        schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0'
        schema:
          $ref: http://localhost:8080/apis/registry/v2/groups/my-group/artifacts/UserSignedUp          
```

## Summary

In this tutorial, you learned how to configure server, operation, message, and channel bindings. You also learned that bindings are essential when integrating Kafka with different systems, platforms, or protocols — especially in API specifications like AsyncAPI. 

## Next steps

Now that you have completed this tutorial, you can [learn more about other Kakfa bindings](https://github.com/asyncapi/bindings/tree/master/kafka) or [protocol-specific bindings](https://github.com/asyncapi/bindings).

---

# Overview
Source: https://www.asyncapi.com/docs/tools.md

# Overview

## Tools: the AsyncAPI tools ecosystem

Welcome to AsyncAPI **Tools**! Our Tools section documents the AsyncAPI tools ecosystem.

> **Remember**
>
> ## Contribute to AsyncAPI Tools
> Code isn't the only way to contribute to OSS; Dev Docs are a **huge** help that benefit the entire OSS ecosystem. At AsyncAPI, we value Doc contributions as much as every other type of contribution. ❤️
> 
> To get started as a Docs contributor:
> 
> 1. Familiarize yourself with our [project's Contribution Guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md).
> 2. Head over to our [AsyncAPI Docs Board](https://github.com/orgs/asyncapi/projects/12).
> 3. Pick an issue you would like to contribute to and leave a comment introducing yourself. This is also the perfect place to leave any questions you may have on how to get started.
> 4. If there is no work done in that Docs issue yet, feel free to open a PR and get started!
> 
> ### Docs contributor questions
> 
> Do you have a question about contributing to the docs or an issue with your pull request? [Join our Slack community](https://www.asyncapi.com/slack-invite) and ask in the `#docs` channel; the maintainers will get back to you.

___

## AsyncAPI Tools List

[Check out the complete list of AsyncAPI tools in our AsyncAPI Tools Dashboard](/tools).

**Would you like to add your AsyncAPI tool to the list?** [Read the docs for adding tools in our AsyncAPI Tools Dashboard.](https://www.asyncapi.com/docs/community/040-guides/add-new-asyncapi-tool-to-website).

---

# Introduction
Source: https://www.asyncapi.com/docs/tools/generator.md

# Introduction

The AsyncAPI generator is a tool that generates anything you want using the **[AsyncAPI Document](generator/asyncapi-document)** and **[Template](generator/template)** that are supplied as inputs to the AsyncAPI CLI. The generator was built with extensibility in mind; you can use the generator to generate anything you want, provided that it can be defined in a template, such as code, diagrams, markdown files, microservices, and applications. A number of [community-maintained templates](https://github.com/search?q=topic%3Aasyncapi+topic%3Agenerator+topic%3Atemplate) are now available for immediate usage.

> **Note:**
> If your primary objective is to generate models/classes for your event-driven architecture apps, use [AsyncAPI Modelina](/docs/tools/generator/model-generation.md), which is supported in the AsyncAPI CLI, instead of using the AsyncAPI Generator. Modelina is specifically designed for model generation and provides utilities for working with the AsyncAPI document.

### Generator use cases 
- **Generation of API documentation** - Transforms an AsyncAPI document into a human-readable website or Markdown where developers can visualize channels, operations, messages, and payload schemas, instead of reading the raw YAML/JSON definition.
- **Generation of APIs' client libraries (SDKs)** - Produces ready-to-use code packages for API consumers that abstract away the protocol/networking logic (connecting, subscribing, and publishing over Kafka, WebSocket, MQTT, and more), so developers interact with the API by calling functions rather than writing raw connection code.
- **Generation of APIs' boilerplate code** - Scaffolds the project skeleton for API providers: server configuration, directory structure, and connection logic, plus stub handler files, so you can skip the setup and focus immediately on business logic.
- **And anything else you can template** - The use cases above are just the popular ones. Because the output is driven entirely by the template, you can generate whatever your AsyncAPI document can describe: usage examples, test cases, Helm charts, config files, diagrams, and more.

### Generator advantages
- Quick to setup and easy to use on a regular basis
- Effortless generation of complex documents
- Number of community maintained AsyncAPI templates

### Generation process
1. The **Generator** receives the **[Template](generator/template)** and **[AsyncAPI Document](generator/asyncapi-document)** as inputs. 
2. The **Generator** sends to the **[Parser](generator/parser)** the **asyncapiString** which is a stringified version of the original **AsyncAPI Document**.
3. The **Parser** uses additional plugins such as the OpenAPI, RAML, or Avro schemas to validate custom schemas of message payloads defined in the **AsyncAPI Document**.
4. If the **Parser** determines that the original **AsyncAPI Document** is valid, it manipulates the document and returns a set of helper functions and properties and bundles them together into an **asyncapi** variable that is an instance of [**AsyncAPIDocument**](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#asyncapidocument). The **asyncapi** helper functions make it easier to access the contents of the AsyncAPI Document.
5. At this point, the **Generator** passes the **[asyncapi](generator/asyncapi-document#method-2-asyncapi-and-template)**, the **[originalAsyncAPI](generator/asyncapi-document#method-1-originalasyncapi-and-template)**, and the **params** which collectively make up the **[Template Context](generator/template-context)** to the **Render Engine**. 
6. AsyncAPI has a **Render Engine**([react](generator/react-render-engine)). The **Generator** passes both the **Template Files** and the **Template Context** to the **Render Engine**.
7. Once the **Render Engine** receives the **Template Files** and the **Template Context**, it injects all the dynamic values in your react based **Template Files** using the **Template Context**. As a result, the **Render Engine** generates **markdown**, **pdf**, **boilerplate code**, and **anything else** you specified to be generated as output.

> You can generate anything you want using the generator as long as it can be defined in a **Template**.

The diagram below depicts the entire process of passing the **Template** and **AsyncAPI Document** to the AsyncAPI generator tool, how the generator uses these inputs to generate the desired output, and example outputs you can get from the render engine.

``` mermaid
graph LR
    A[Template Context]
    B{Generator}
    C[Parser]
    D[Render Engine]
    E[AsyncAPI Document] --> B
    F[Template] --> B
  subgraph Generator Library
    B -->| asyncapiString | C
    C --> | asyncapi | A
    B--> | originalAsyncAPI | A
    B--> | params | A
    A --> D
    B --> | Template Files | D
  end
  D --> O[HTML]
  D --> M[Markdown]
  D --> N[Node.js]
  D --> J[Java Spring Boot]
  D --> K[Anything else]
  ```
**`params`** are template-specific options passed to the `asyncapi generate fromTemplate` CLI command to customize the generated output.

---

# Installation guide
Source: https://www.asyncapi.com/docs/tools/generator/installation-guide.md

# Installation guide

You can use the generator library to generate whatever you want in your event-driven architecture apps. Find your preferred method below:
- [AsyncAPI CLI](#asyncapi-cli)
- [Generator library in Node.js apps](#generator-library-in-nodejs-apps)
  
## Prerequisites
Before you install and use the AsyncAPI CLI and the generator library, ensure you meet the prerequisites below, then [install the CLI](https://www.asyncapi.com/docs/tools/cli/installation).
1. Node.js v18.12.0 or higher
2. Npm v8.19.0 or higher
   
To verify the versions of Node and Npm you have, run the following command on your terminal:
```
npm -v
```
```
node -v
```

If you don't have either Node or Npm installed, use the [official node.js installer](https://nodejs.org/en/download/).

If you have the correct versions installed, proceed to the CLI installation guide below. Otherwise, upgrading the Npm or Node version is lower than the recommended versions specified above.

## AsyncAPI CLI
The AsyncAPI CLI tool allows you to do many different things with the [AsyncAPI document](asyncapi-document). You can generate message-based API boilerplate code, documentation, or anything else you need as long as you specify it in your [template](template) or the existing template already supports it. To use the generator via the AsyncAPI CLI, you need to install the AsyncAPI CLI tool. For the latest installation instructions, visit the official AsyncAPI CLI [installation guide](https://www.asyncapi.com/docs/tools/cli/installation).

> :memo: **Note:**  To use the generator in your CI/CD pipeline to automate whatever you generate for your event-driven architecture apps, install the AsyncAPI CLI in your pipeline. If you are using GitHub Actions, use [Github Actions for Generator](https://github.com/marketplace/actions/asyncapi-cli-action).

## Generator library in Node.js apps
Use the generator library in your Node.js projects by installing it via the following command: `npm install @asyncapi/generator`.

> Don't include the `-g` flag in the installation command above since you're not installing the generator library globally but in your Node.js project.

---

# Usage
Source: https://www.asyncapi.com/docs/tools/generator/usage.md

# Usage

There are two ways to use the generator:
- [AsyncAPI CLI](#generator-cli)
- [Generator library](#using-as-a-modulepackage)

## AsyncAPI CLI

### `asyncapi generate fromTemplate ASYNCAPI TEMPLATE`

Generates whatever you want using templates compatible with AsyncAPI Generator. For complete command usage and options, refer to the official [AsyncAPI CLI documentation](https://www.asyncapi.com/docs/tools/cli/usage#asyncapi-generate-fromtemplate-asyncapi-template).

All templates are installable npm packages. Therefore, the value of `template` can be anything supported by `npm install`. Here's a summary of the possibilities:
```
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <git-host>:<git-user>/<repo-name>
npm install <git repo url>
npm install <tarball file>
npm install <tarball url>
npm install <folder>
```

### Global templates installed with `yarn` or `npm`

You can preinstall templates globally before installing the [AsyncAPI CLI](https://www.asyncapi.com/docs/tools/cli). The generator first tries to locate the template in local dependencies; if absent it checks where the global generator packages are installed.

```bash
npm install -g @asyncapi/html-template@0.16.0
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template
# The generator uses html-template version 0.16.0 and not the latest version.
```

### CLI usage examples

**The shortest possible syntax:**
```bash
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4
```

**Generating from a URL:**
```bash
asyncapi generate fromTemplate https://bit.ly/asyncapi @asyncapi/html-template@3.5.4 
```

**Specify where to put the result:**
```bash
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4 -o ./docs
```

**Passing parameters to templates:**
```bash
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4  -o ./docs -p title='Hello from param'
```

In the template you can use it like this: `{{ params.title }}`

**Disabling the hooks:**
```bash
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4 -o ./docs -d generate:before generate:after=foo,bar
```

The generator skips all hooks of the `generate:before` type and `foo`, `bar` hooks of the `generate:after` type.

**Installing the template from a folder:**
```bash
asyncapi generate fromTemplate asyncapi.yaml ~/my-template
```

It creates a symbolic link to the target directory (`~/my-template` in this case). 

**Installing the template from a git URL:**
```bash
asyncapi generate fromTemplate asyncapi.yaml https://github.com/asyncapi/html-template.git
```

**Map schema references from baseUrl to local folder:**
```bash
asyncapi generate fromTemplate test/docs/apiwithref.json @asyncapi/html-template@3.5.4 -o ./build/ --force-write --map-base-url https://schema.example.com/crm/:./test/docs/
```

The parameter `--map-base-url` maps external schema references to local folders.

### CLI usage with Docker

When using our docker image that we regularly update, you don't need to install Node.js or Npm, even though the generator is written with it since the Docker image has the generator installed.

Install [Docker](https://docs.docker.com/get-docker/) first, then use docker to pull and run the image using the following command:

```bash
docker run --rm -it \
--user=root \
-v [ASYNCAPI SPEC FILE LOCATION]:/app/asyncapi.yml \
-v [GENERATED FILES LOCATION]:/app/output \
asyncapi/cli # docker image [COMMAND HERE]

# Example that you can run inside the cli directory after cloning this repository. First, you specify the mount in the location of your AsyncAPI specification file and then you mount it in the directory where the generation result should be saved.
docker run --rm -it \
   --user=root \
   -v ${PWD}/test/fixtures/asyncapi_v1.yml:/app/asyncapi.yml \
   -v ${PWD}/output:/app/output \
   asyncapi/cli generate fromTemplate -o /app/output /app/asyncapi.yml @asyncapi/html-template@3.5.4 --force-write
```
Note: Use ``` ` ``` instead of `\` for Windows.

### CLI usage with `npx` instead of `npm`

[npx](https://www.npmjs.com/package/npx) is very useful when you want to run the generator in a CI/CD environment. In such a scenario, do not install the generator globally because most environments that provide Node.js and Npm, also provide npx out of the box. 

Use the following npx command on your terminal:

```bash
npx -p @asyncapi/cli asyncapi generate fromTemplate ./asyncapi.yaml @asyncapi/html-template@3.5.4 
```

## Using as a module/package
Once you install the generator in your project, you can use it to generate whatever you want. The following code snippet is an example of HTML generation using the official `@asyncapi/html-template` template and fetching the spec document from the server using:
```
https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0/examples/2.0.0/streetlights.yml
```

```js
const path = require('path');
const generator = new Generator('@asyncapi/html-template', path.resolve(__dirname, 'example'));

try {
  await generator.generateFromURL('https://raw.githubusercontent.com/asyncapi/asyncapi/2.0.0/examples/2.0.0/streetlights.yml');
  console.log('Done!');
} catch (e) {
  console.error(e);
}
```

See the [API documentation](api) for more examples and full API reference information.

---

# AsyncAPI document
Source: https://www.asyncapi.com/docs/tools/generator/asyncapi-document.md

# AsyncAPI document

The **AsyncAPI document** defines a standard, protocol-agnostic interface that describes message-based or event-driven APIs. The AsyncAPI document allows people or machines communicating with one another, to understand the capabilities of an event-driven API without requiring access to the source code, documentation, or inspecting the network traffic.

This document allows you to define your API structures and formats, including channels the end user can subscribe to and the message formats they receive.

The documents describing the message-driven API under the AsyncAPI specification are represented as JSON objects and conform to JSON standards. YAML, a superset of JSON, can also be used to represent an API.

> - To learn how to create an AsyncAPI document or refresh your knowledge about the syntax and structure of the AsyncAPI document, check out our [latest specification documentation](https://www.asyncapi.com/docs/reference/specification/latest).
> - You can develop, validate, and convert the AsyncAPI document to the latest version or preview your AsyncAPI document in a more readable way using the [AsyncAPI Studio](https://studio.asyncapi.com/).

In the following sections, you'll learn about the inner working of the generator, what happens once the AsyncAPI document is fed to the generator, and how you can access the content of the document in your template.

## AsyncAPI document generation process

1. The **Generator** receives the **AsyncAPI Document** as input.
2. The **Generator** sends to the **[Parser](parser)** the **asyncapiString** is a stringified version of the original **AsyncAPI Document** to validate and parse it.
3. The **Parser** validates the **AsyncAPI Document** using additional schema-related plugins, either the OpenAPI schema, RAML data types, or Avro schema.
4. If the **Parser** determines that the **AsyncAPI Document** is valid, it manipulates the original JSON/YAML document and provides a set of helper functions in return, bundling them together into an **asyncapi** variable that is an instance of [**AsyncAPIDocument**](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#asyncapidocument).
5. At this point, the **Generator** passes the **originalAsyncAPI** and the **asyncapi** which make up part of the **[Template Context](template-context)** to the **Render Engine**.
6. The **Template Context** is accessible to the template files that are passed to the [react](react-render-engine) **Render Engine**.

```mermaid
graph LR
    A[Template Context]
    B{Generator}
    C[Parser]
    D[Render Engine]
    E[AsyncAPI Document] --> B
  subgraph Generator
    B -->| asyncapiString | C
    C --> | asyncapi -> AsyncAPIDocument type | A
    B--> | originalAsyncAPI -> Stringified document | A
    A --> D
  end
```

The AsyncAPI document's content is accessible to you while writing your template in two distinct ways:

- The `originalAsyncAPI`, which is a stringified version of the AsyncAPI document provided as input, without any modifications.
- The `asyncapi` (`AsyncAPIDocument`) which is an object with a set of helper functions, that comes as a result of the `Parser` manipulating the `originalAyncAPI` .The `asyncapi` functions make it easier to access the contents of AsyncAPI documents in your templates.

In the following sections, you will learn how to use either the **originalAsyncAPI** or the **asyncapi** in your template.

### Method 1: `originalAsyncAPI` and template

One way of using the contents of the AsyncAPI document inside your template files is by using its stringified version that reflects the same contents as the AsyncAPI document provided as input to the generator. You can access it directly in your templates using the `originalAsyncAPI` variable. You also access it via the [hooks](hooks) `generator.originalAsyncAPI` because `originalAsyncAPI` is also a part of the generator instance that is passed to hooks.

```js
//example use case for using a stringified AsyncAPI document inside template hooks

const fs = require('fs');
const path = require('path');

function createAsyncapiFile(generator) {
  const asyncapi = generator.originalAsyncAPI;
  let extension;

  try {
    JSON.parse(asyncapi);
    extension = 'json';
  } catch (e) {
    extension = 'yaml';
  }

  const outputFileName = `asyncapi.${extension}`;

  const asyncapiOutputLocation = path.resolve('./', outputFileName);

  fs.writeFileSync(asyncapiOutputLocation, asyncapi);
}
```

### Method 2: `asyncapi` and template

A major advantage of using `asyncapi` (which is an instance of `AsyncAPIDocument`) is that it enables the developer to easily access the AsyncAPI documents' content by simply invoking a function.

Once the specification YAML or JSON document is passed as input to the generator, it is passed on to the [Parser](parser) library, which then manipulates the asyncAPI document to a more structured document called the `AsyncAPIDocument`. Once the parser returns the document to the generator, the generator passes it to the render engine. The render engine makes the `AsyncAPIDocument` object accessible to your template through the `asyncapi` variable.

For example, if you want to extract the version of your API from AsyncAPI document, you can do that by calling `asyncapi.version()`. You can say that this one is easy to access from JSON objects, but there are more complex scenarios. For example, to get access to all messages from all channels, you can call `asyncapi.allMessages()` instead of iterating through a complex JSON object on your own.

In the sample code snippet below, notice how you can access the contents of the AsyncAPI document in your template using `asyncapi` variable from the context:

```js
const apiName = asyncapi.info().title();
const channels = asyncapi.channels();
```

> To learn about the various instances you can use to access the documents' content, look at the API of the AsyncAPI JavaScript Parser and the structure of [AsyncAPIDocument](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#asyncapidocument)

---

# Template
Source: https://www.asyncapi.com/docs/tools/generator/template.md

# Template

## Template

A template is a project that specifies the generation process output by using the AsyncAPI Generator (generator) and an [AsyncAPI document](asyncapi-document). These files describe the generation results depending on the AsyncAPI document's content.

Examples outputs:

- Code
- Documentation
- Markdown diagrams
- Python and Java applications

Templates can be developed as standalone project. There is also a set of baked-in core templates that are available in the generator out of the box.

### Baked-in templates

> This is a new concept introduced in generator version 2.8. The number of templates is limited and solution is still in experimental phase

Baked-in templates are official AsyncAPI templates that are **developed, versioned, and shipped directly inside the `generator` repository and exposed with `@asyncapi/generator` library**. Source code of these templates live in the `packages/templates` directory of the `generator` repository. These templates and are managed alongside the generator’s core source code. Baked-in templates are always available “out of the box” when using the generator. No separate installation or network fetching is required.

Baked-in templates benefit from:
- **Tight integration** with the generator’s features and release cycle.
- **Instant availability:** They are bundled as part of every release, so you never need to install or fetch them separately.
- **Unified contributions:** Any improvements or changes to these templates happen through pull requests to the generator repository itself, keeping everything in sync. They share a lot of common parts which makes templates development faster.

In contrast, **standalone templates** (described below) are maintained as independent Node.js packages, may live in separate repositories, and can be managed or installed separately from the core generator.

Learn more from document [Baked-in Templates](baked-in-templates).

### Standalone templates

A standalone template is an independent Node.js project unrelated to the `generator` repository. AsyncAPI templates are managed, released, and published separately. You can also create templates and manage templates on your own.

The generator uses the official [Arborist](https://www.npmjs.com/package/@npmcli/arborist) NPM library. (This means templates do not have to be published to package managers to use them.) Arborist helps the generator fetch the template's source code and use it for the generation process. By default, this library pulls data from the default NPM registry, which is https://registry.npmjs.org. You can also configure the generator to fetch templates that are private or hosted in different NPM registry

You can store template projects on a local drive or as a `git` repository during the development process. 

## Template generation process

1. Template is provided as input to the **Generator**.
2. **asyncapi** (which is an instance of AsyncAPIDocument) is injected into your template file by default.
3. **params** are the parameters you pass to the AsyncAPI CLI. Later, you can also pass these **params** further to other components. 
4. The generator passes both the **asyncapi**, the **originalAsyncAPI**, and the **params** to the **Template Context**.
5. Concurrently, the generator passes **Template files** to the **Render engine** as well. AsyncAPI uses the _react_ render engine.
6. Once the Render Engine receives both the Template Files and the Template Context, it injects all the dynamic values into your react based Template Files using the Template Context.
7. The render engine generates whatever output you may have specified in your template. (i.e. code, documentation, diagrams, pdfs, applications, etc.)

```mermaid
graph LR
    A[Template Context]
    B{Generator}
    D[Render Engine]
    F[Template] --> B
  subgraph Generator Library
    B --> | asyncapi | A
    B--> | params | A
    A --> D
    B --> | Template Files | D
  end
```

## Standalone templates list

AsyncAPI has a list of available templates to enhance your generation process. Templates are stored as repositories on AsyncAPI's official GitHub profile.

<!-- templates list is validated with GitHub Actions do not remove list markers -->
<!-- TEMPLATES-LIST:START -->

Template Name | Description | Source code
---|---|---
`@asyncapi/nodejs-template` | (**archived**) Generates Node.js service that uses Hermes package | [Node.js template](https://github.com/asyncapi/nodejs-template)
`@asyncapi/nodejs-ws-template` | (**archived**) Generates Node.js service that supports WebSocket protocol only | [Node.js WebSocket template](https://github.com/asyncapi/nodejs-ws-template)
`@asyncapi/java-template` | Generates Java JMS application | [Java template](https://github.com/asyncapi/java-template)
`@asyncapi/java-spring-template` | (**archived**) Generates Java Spring service | [Java spring template](https://github.com/asyncapi/java-spring-template)
`@asyncapi/java-spring-cloud-stream-template` | Generates Java Spring Cloud Stream service | [Java spring cloud stream template](https://github.com/asyncapi/java-spring-cloud-stream-template)
`@asyncapi/python-paho-template` | (**archived**) Generates Python service that uses Paho library | [Python paho template](https://github.com/asyncapi/python-paho-template)
`@asyncapi/html-template` | Generates HTML documentation site | [HTML template](https://github.com/asyncapi/html-template)
`@asyncapi/markdown-template` | Generates documentation in Markdown file | [Markdown template](https://github.com/asyncapi/markdown-template)
`@asyncapi/ts-nats-template` | (**archived**) Generates TypeScript NATS client | [TypeScript/Node.js NATS template](https://github.com/asyncapi/ts-nats-template/)
`@asyncapi/go-watermill-template` | (**archived**) Generates Go client using Watermill | [GO watermill template](https://github.com/asyncapi/go-watermill-template)
`@asyncapi/dotnet-nats-template` | (**archived**) Generates .NET C# client using NATS | [.NET C# NATS template](https://github.com/asyncapi/dotnet-nats-template)

<!-- TEMPLATES-LIST:END -->

> [!NOTE]
> Templates marked **(archived)** live in the [`asyncapi-archived-repos`](https://github.com/asyncapi-archived-repos) organization and are no longer maintained. Consider the **[baked-in templates](https://www.asyncapi.com/docs/tools/generator/baked-in-templates)** for supported alternatives.

> Some of these templates are maintained by various third-party organizations. The README file usually contains this information and more, such as configuration options the user can pass to the template, usage, technical requirements, etc.

> Check out all our community [generator templates](https://github.com/search?q=topic%3Aasyncapi+topic%3Agenerator+topic%3Atemplate)

---

# Baked-in Templates
Source: https://www.asyncapi.com/docs/tools/generator/baked-in-templates.md

# Baked-in Templates

> This is a new concept introduced in generator version 2.8. The number of templates is limited and solution is still in experimental phase. It is not recommended to use them in production. Instead join us to help to improve them with your use cases and your AsyncAPI documents.

Baked-in templates are official AsyncAPI templates that are **developed, versioned, and shipped directly inside the `generator` repository and exposed with `@asyncapi/generator` library**.

AsyncAPI Generator supports a variety of baked-in template types for generating code, documentation, configs, and SDKs. All templates are managed under the `packages/templates` directory and follow a strict, opinionated directory structure for consistency and ease of maintenance.

> Check out the [list of baked-in templates](https://github.com/asyncapi/generator/blob/master/apps/generator/lib/templates/BakedInTemplatesList.json)

## Supported template types

Templates are grouped by **type**, which must be one of the following:

- `docs` (not yet implemented): Templates that generate documentation
- `client`: Templates that generate clients
- `sdk` (not yet implemented): Template that generate full sdk's
- `config` (not yet implemented): Template that generate configuration files

> **Note:**  
> The **directory name is always plural** (e.g., `clients`), but the **type recorded in metadata and package name is singular** (e.g., `client`), except for `docs`.

## Template directory structure

### General structure

All template directories must follow this convention:
```
packages/templates/{type}/[protocol]/[target]/[stack]
```

- `type`: One of `docs`, `clients`, `sdks`, or `configs`.
- `protocol`: (Only for `clients` and `sdks`) The protocol this template supports, e.g. `websocket`, `http`, `kafka`.
- `target`: The output language, markup, or format, e.g. `javascript`, `python`, `html`, `yaml`.
- `stack`: (Optional, for `clients` and `sdks`) Used for technology stack, e.g. `express`, `quarkus`.

#### Type-specific rules

- **docs/configs**:  
  Path must be `type/target` (e.g., `docs/html` or `configs/yaml`).
- **clients/sdks**:  
  Path must be `type/protocol/target` or `type/protocol/target/stack` (e.g., `clients/websocket/javascript`, `sdks/kafka/java/spring`).

### Required files

Every template directory **must include**:
- `.ageneratorrc`: Generator specific configuration, like for example parameters
- `package.json`: It contains template name. Version information should not be provided as it is versioned together with the generator.

## Metadata and naming conventions

Generator build runs a script that normalizes metadata for baked-in templates and their naming:
- Adds/updates metadata in `.ageneratorrc` file. You do not have to maintain it manually.
- Validates/updates template name in `package.json` file of given template. The name always starts with `core-template-` prefix.
- Generates JSON file with list of baked-in templates and stores the list inside the generator: `apps/generator/lib/templates/BakedInTemplatesList.json`

> **Note:**
> The `metadata` block in `.ageneratorrc` and the `name` in `package.json` are auto-generated from the template's folder path by [`apps/generator/scripts/build-templates.js`](https://github.com/asyncapi/generator/blob/master/apps/generator/scripts/build-templates.js), which runs on every `npm run build` and automatically before tests. Do not edit them manually — the build overwrites them, and any other comments you add to `.ageneratorrc` are dropped when the file is re-serialized. To change a template's metadata, rename or move its directory and run `npm run build`.

#### Example

Example information provided for template stored under `packages/templates/clients/websocket/javascript/express`

```yaml
# .ageneratorrc
metadata:
  type: client
  protocol: websocket
  target: javascript
  stack: express
```

Package name format:  `core-template-client-websocket-javascript-express`

Resulting entry in `apps/generator/lib/templates/BakedInTemplatesList.json`:
```json
  {
    "name": "core-template-client-websocket-javascript-express",
    "type": "client",
    "protocol": "websocket",
    "target": "javascript",
    "stack": "express"
  }
```

## How to add a new baked-in template

1. Create the directory in `packages/templates` using the correct structure.
   - For a docs template:  
     `packages/templates/docs/html`
   - For a clients template:  
     `packages/templates/clients/websocket/rust`
1. Add required files:  
   - `.ageneratorrc` (do not add `generator` config key as it is not needed)
   - `package.json`
1. Run generator's build command: `npm run build`

## Templates exposed through generator

Templates that are exposed as part of the generator are transpiled with the `react-sdk` and located in published library under `/lib/templates/bakedInTemplates`. This means that in case of baked-in templates, they are not picked by the generator from `node_modules`. This way the process of generation is faster and more efficient.

---

# Parser
Source: https://www.asyncapi.com/docs/tools/generator/parser.md

# Parser

## Parser

The AsyncAPI Parser is a package used to parse and validate the [AsyncAPI documents](asyncapi-document) in your Node.js or browser application. These documents can be either in YAML or JSON format.

The Parser validates these documents using dedicated schema-supported plugins.

Supported schemas:

- AsyncAPI schema (no plugin needed)
- OpenAPI schema
- JSON schema
- Avro schema
- RAML data-type schema

The Parser allows the template developer to easily access schemas provided in the above supported formats. This is because the JavaScript parser converts all of them into JSON schema.

If the document is valid, the Parser returns an `AsyncAPIDocument instance` with a set of helper functions that enable easier access to the contents of the AsyncAPI document. The parser provides dereferenced output. During the dereference process, the AsyncAPI parser substitutes a reference with a full definition. The dereferenced output is always in JSON format. The parser provides a message listing all errors if a document is invalid. The original AsyncAPI document is part of the [Template Context](template-context) as the generator also passes the original AsyncAPI document to the template context.

The following AsyncAPI document example has two channels: `channelOne` and `channelTwo`. Each channel has one operation and a single message:

```yaml
asyncapi: "2.5.0"
info:
  title: Demo API
  version: "1.0.0"
channels:
  channelOne:
    publish:
      summary: This is the first sample channel
      operationId: onMessage
      message:
        name: FirstMessage
        payload:
          id:
            type: integer
            minimum: 0
            description: Id of the channel
          sentAt:
            type: string
            format: date-time
            description: Date and time when the message was sent.
  channelTwo:
    publish:
      summary: This is the second sample channel
      operationId: messageRead
      message:
        name: SecondMessage
        payload:
          id:
            type: integer
            minimum: 0
            description: Id of the channel
          sentAt:
            type: string
            format: date-time
            description: Date and time when the message was sent.
```

We can use helper functions provided by the Parser to operate on the above JSON file. For example, we can use the helper method `asyncAPIDocument.channelNames()`, which returns an array of all channel names currently present in the AsyncAPI document. Another example where you can use a helper function is to list out messages present in your JSON file. Instead of fetching a single message one at a time, you can use the function `asyncAPIDocument.allMessages()` that returns the map of all messages in your AsyncAPI document.

```js
const channelNames = asyncAPIDocument.channelNames();
const messages = asyncAPIDocument.allMessages();
```

> The Parser gives you access to a number of these [helper functions](https://github.com/asyncapi/parser-api/blob/master/docs/api.md) that you can implement to access the contents of your AsyncAPI document.

## AsyncAPI document validation process

1. **AsyncAPI document** is fed as an input to the Generator.
1. Generator sends the AsyncAPI document to the Parser as **asyncapiString**; the stringified version of the original AsyncAPI document.
1. The Parser uses additional plugins such as the OpenAPI, RAML, or Avro schemas to validate custom schemas of message payloads defined in the AsyncAPI document.
1. If the AsyncAPI document is invalid, it throws an error based on the encountered failure type. For example, if the AsyncAPI document is not a string nor a JavaScript object, the Parser throws an `invalid-document-type` error.
   Similarly, you may encounter errors such as:
   - `invalid-json`
   - `invalid-yaml`
   - `impossible-to-convert-to-json`
1. If the document is valid, the Parser modifies the AsyncAPI document, returns a set of helper functions, and bundles them together into the **asyncapi** variable. These helper functions in the form of an **asyncapi** variable are passed to the **Template Context**.
1. The Template Context passes all of these values to the [**Render Engine**](react-render-engine) of your choice. Finally, the Render Engine generates whatever output you may have specified in your template. (i.e. code, documentation, diagrams, pdfs, applications, etc.)

```mermaid
graph TD
    A[AsyncAPI document] --> B
    B[Generator] -->|asyncapiString| C(Parser)
    C --> D{Validation}
    D -->|invalid| B
    D -->|asyncapi -> helper functions| E[Template Context]
    E --> F[Render Engine]
```

> To learn more about the Parser and access all of its features, check out the AsyncAPI [Parser’s GitHub repository](https://github.com/asyncapi/parser-js).

---

# Generator version vs template version
Source: https://www.asyncapi.com/docs/tools/generator/versioning.md

# Generator version vs template version

The generator tool generates whatever you want, as long as it can be defined in a template based on the [AsyncAPI document](asyncapi-document). On the other hand, a **template** is a file or group of files that specify the kind of output you expect from using the generator's features. For example, you may want to use the [NodeJS template](https://github.com/asyncapi/nodejs-template) to generate boilerplate code for your message-based APIs.

Templates are dependent on the generators' features. For example, the template you want to use may be compatible with the latest generator version but incompatible with the previous versions. Check the configuration file or ReadME of the template to see the version of the generator it supports. The generator has an `isTemplateCompatible` function that checks if the template is compatible with the version of the generator you want to use. If the template isn't compatible, you will see a terminal error output similar to the following:
```
Something went wrong:
Error: This template is not compatible with the current version of the generator (${generatorVersion}). This template is compatible with the following version range: ${generator}.`)
```

> Use the following command to check the version of the AsyncAPI CLI you have installed with all its dependencies, like AsyncAPI Generator;  `asyncapi config versions`

It is better to lock a specific version of the template and the generator if you plan to use the AsyncAPI CLI and a particular template in production. The differences between using the version of the AsyncAPI CLI you have installed and locking a certain version on production are demonstrated in the following code snippets.

Generate HTML with the latest AsyncAPI CLI using the html-template.
```
npm install -g @asyncapi/cli
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@3.5.4
```

Generate HTML using a particular version of the AsyncAPI CLI using the html-template.

```
npm install -g @asyncapi/cli@0.20.0
asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template@0.7.0 -o ./docs
```

> Before using newer versions of the template, always look at the [changelog](https://github.com/asyncapi/html-template/releases) first. If the generator's features are not important to you, just make sure to use a version compatible with your template.

---

# Library API
Source: https://www.asyncapi.com/docs/tools/generator/api.md

# Library API

Reference API documentation for AsyncAPI Generator library.
## Classes

<dl>
<dt><a href="#Generator">Generator</a></dt>
</dl>

## Members

<dl>
<dt><a href="#listBakedInTemplates">listBakedInTemplates</a> ⇒ <code>Array.&lt;Object&gt;</code></dt>
<dd><p>List core templates, optionally filter by type, stack, protocol, or target.
Use name of returned templates as input for the `generate` method for template generation. Such core templates code is part of the @asyncapi/generator package.</p></dd>
</dl>

<a name="Generator"></a>

## Generator
**Kind**: global class  

* [Generator](#Generator)
    * [new Generator(templateName, targetDir, options)](#new_Generator_new)
    * _instance_
        * [.compile](#Generator+compile) : `Boolean`
        * [.registry](#Generator+registry) : `Object`
        * [.templateName](#Generator+templateName) : `String`
        * [.targetDir](#Generator+targetDir) : `String`
        * [.entrypoint](#Generator+entrypoint) : `String`
        * [.noOverwriteGlobs](#Generator+noOverwriteGlobs) : `Array.<String>`
        * [.disabledHooks](#Generator+disabledHooks) : `Object.<String, (Boolean|String|Array.<String>)>`
        * [.output](#Generator+output) : `String`
        * [.forceWrite](#Generator+forceWrite) : `Boolean`
        * [.debug](#Generator+debug) : `Boolean`
        * [.install](#Generator+install) : `Boolean`
        * [.templateConfig](#Generator+templateConfig) : `Object`
        * [.hooks](#Generator+hooks) : `Object`
        * [.mapBaseUrlToFolder](#Generator+mapBaseUrlToFolder) : `Object`
        * [.templateParams](#Generator+templateParams) : `Object`
        * [.generate(asyncapiDocument, [parseOptions])](#Generator+generate) ⇒ `Promise.<void>`
        * [.validateAsyncAPIDocument(asyncapiDocument)](#Generator+validateAsyncAPIDocument)
        * [.setupOutput()](#Generator+setupOutput)
        * [.setupFSOutput()](#Generator+setupFSOutput) ⇒ `Promise.<void>`
        * [.setLogLevel()](#Generator+setLogLevel) ⇒ `void`
        * [.installAndSetupTemplate()](#Generator+installAndSetupTemplate) ⇒ `Promise.<{templatePkgName: string, templatePkgPath: string}>`
        * [.configureTemplateWorkflow(parseOptions)](#Generator+configureTemplateWorkflow) ⇒ `Promise.<void>`
        * [.handleEntrypoint()](#Generator+handleEntrypoint) ⇒ `Promise.<void>`
        * [.executeAfterHook()](#Generator+executeAfterHook) ⇒ `Promise.<void>`
        * [.parseInput()](#Generator+parseInput)
        * [.configureTemplate()](#Generator+configureTemplate)
        * [.generateFromURL(asyncapiURL)](#Generator+generateFromURL) ⇒ `Promise.<(TemplateRenderResult|undefined)>`
        * [.generateFromFile(asyncapiFile)](#Generator+generateFromFile) ⇒ `Promise.<(TemplateRenderResult|undefined)>`
        * [.installTemplate([force])](#Generator+installTemplate)
    * _static_
        * [.getTemplateFile(templateName, filePath, [templatesDir])](#Generator.getTemplateFile) ⇒ `Promise`

<a name="new_Generator_new"></a>

### new Generator
Instantiates a new Generator object.

**Params**

- templateName `String` - Name of the template to generate.
- targetDir `String` - Path to the directory where the files will be generated.
- options `Object`
    - [.templateParams] `Object.<string, string>` - Optional parameters to pass to the template. Each template define their own params.
    - [.entrypoint] `String` - Name of the file to use as the entry point for the rendering process. Use in case you want to use only a specific template file. Note: this potentially avoids rendering every file in the template.
    - [.noOverwriteGlobs] `Array.<String>` - List of globs to skip when regenerating the template.
    - [.disabledHooks] `Object.<String, (Boolean|String|Array.<String>)>` - Object with hooks to disable. The key is a hook type. If key has "true" value, then the generator skips all hooks from the given type. If the value associated with a key is a string with the name of a single hook, then the generator skips only this single hook name. If the value associated with a key is an array of strings, then the generator skips only hooks from the array.
    - [.output] `String` ` = 'fs'` - Type of output. Can be either 'fs' (default) or 'string'. Only available when entrypoint is set.
    - [.forceWrite] `Boolean` ` = false` - Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir. Default is set to false.
    - [.install] `Boolean` ` = false` - Install the template and its dependencies, even when the template has already been installed.
    - [.debug] `Boolean` ` = false` - Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive.
    - [.compile] `Boolean` ` = true` - Whether to compile the template or use the cached transpiled version provided by template in '__transpiled' folder
    - [.mapBaseUrlToFolder] `Object.<String, String>` - Optional parameter to map schema references from a base url to a local base folder e.g. url=https://schema.example.com/crm/  folder=./test/docs/ .
    - [.registry] `Object` - Optional parameter with private registry configuration
        - [.url] `String` - Parameter to pass npm registry url
        - [.auth] `String` - Optional parameter to pass npm registry username and password encoded with base64, formatted like username:password value should be encoded
        - [.token] `String` - Optional parameter to pass npm registry auth token that you can grab from .npmrc file

**Example**  
```js
const path = require('path');
const generator = new Generator('@asyncapi/html-template', path.resolve(__dirname, 'example'));
```
**Example** *(Passing custom params to the template)*  
```js
const path = require('path');
const generator = new Generator('@asyncapi/html-template', path.resolve(__dirname, 'example'), {
  templateParams: {
    sidebarOrganization: 'byTags'
  }
});
```

<a name="Generator+compile"></a>

* generator.compile : `Boolean`** :
Whether to compile the template or use the cached transpiled version provided by template in '__transpiled' folder.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+registry"></a>

* generator.registry : `Object`** :
Npm registry information.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+templateName"></a>

* generator.templateName : `String`** :
Name of the template to generate.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+targetDir"></a>

* generator.targetDir : `String`** :
Path to the directory where the files will be generated.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+entrypoint"></a>

* generator.entrypoint : `String`** :
Name of the file to use as the entry point for the rendering process. Use in case you want to use only a specific template file. Note: this potentially avoids rendering every file in the template.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+noOverwriteGlobs"></a>

* generator.noOverwriteGlobs : `Array.<String>`** :
List of globs to skip when regenerating the template.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+disabledHooks"></a>

* generator.disabledHooks : `Object.<String, (Boolean|String|Array.<String>)>`** :
Object with hooks to disable. The key is a hook type. If key has "true" value, then the generator skips all hooks from the given type. If the value associated with a key is a string with the name of a single hook, then the generator skips only this single hook name. If the value associated with a key is an array of strings, then the generator skips only hooks from the array.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+output"></a>

* generator.output : `String`** :
Type of output. Can be either 'fs' (default) or 'string'. Only available when entrypoint is set.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+forceWrite"></a>

* generator.forceWrite : `Boolean`** :
Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir. Default is set to false.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+debug"></a>

* generator.debug : `Boolean`** :
Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+install"></a>

* generator.install : `Boolean`** :
Install the template and its dependencies, even when the template has already been installed.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+templateConfig"></a>

* generator.templateConfig : `Object`** :
The template configuration.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+hooks"></a>

* generator.hooks : `Object`** :
Hooks object with hooks functions grouped by the hook type.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+mapBaseUrlToFolder"></a>

* generator.mapBaseUrlToFolder : `Object`** :
Maps schema URL to folder.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+templateParams"></a>

* generator.templateParams : `Object`** :
The template parameters. The structure for this object is based on each individual template.

**Kind**: instance property of [`Generator`](#Generator)  

<a name="Generator+generate"></a>

### generator.generate
Generates files from a given template and an AsyncAPIDocument object.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<void>` - A Promise that resolves when the generation is completed.  
**Params**

- asyncapiDocument `AsyncAPIDocument` | `string` - AsyncAPIDocument object to use as source.
- [parseOptions] `Object` ` = {}` - AsyncAPI Parser parse options.
  Check out [@asyncapi/parser](https://www.github.com/asyncapi/parser-js) for more information.
  Remember to use the right options for the right parser depending on the template you are using.

**Example**  
```js
await generator.generate(myAsyncAPIdocument);
console.log('Done!');
```
**Example**  
```js
generator
  .generate(myAsyncAPIdocument)
  .then(() => {
    console.log('Done!');
  })
  .catch(console.error);
```
**Example** *(Using async/await)*  
```js
try {
  await generator.generate(myAsyncAPIdocument);
  console.log('Done!');
} catch (e) {
  console.error(e);
}
```

<a name="Generator+validateAsyncAPIDocument"></a>

### generator.validateAsyncAPIDocument
Validates the provided AsyncAPI document.

**Kind**: instance method of [`Generator`](#Generator)  
**Throws**:

- `Error` Throws an error if the document is not valid.

**Since**: 10/9/2023 - 4:26:33 PM  
**Params**

- asyncapiDocument `*` - The AsyncAPI document to be validated.

<a name="Generator+setupOutput"></a>

* generator.setupOutput()** :
Sets up the output configuration based on the specified output type.

**Kind**: instance method of [`Generator`](#Generator)  
**Throws**:

- `Error` If 'output' is set to 'string' without providing 'entrypoint'.

**Example**  
```js
const generator = new Generator();
await generator.setupOutput();
```

<a name="Generator+setupFSOutput"></a>

* generator.setupFSOutput() ⇒ `Promise.<void>`** :
Sets up the file system (FS) output configuration.

This function creates the target directory if it does not exist and verifies
the target directory if forceWrite is not enabled.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<void>` - A promise that fulfills when the setup is complete.  
**Throws**:

- `Error` If verification of the target directory fails and forceWrite is not enabled.

<a name="Generator+setLogLevel"></a>

* generator.setLogLevel() ⇒ `void`** :
Sets the log level based on the debug option.

If the debug option is enabled, the log level is set to 'debug'.

**Kind**: instance method of [`Generator`](#Generator)  

<a name="Generator+installAndSetupTemplate"></a>

* generator.installAndSetupTemplate() ⇒ `Promise.<{templatePkgName: string, templatePkgPath: string}>`** :
Installs and sets up the template for code generation.

This function installs the specified template using the provided installation option,
sets up the necessary directory paths, loads the template configuration, and returns
information about the installed template.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<{templatePkgName: string, templatePkgPath: string}>` - A promise that resolves to an object containing the name and path of the installed template.  

<a name="Generator+configureTemplateWorkflow"></a>

### generator.configureTemplateWorkflow
Configures the template workflow based on provided parsing options.

This function performs the following steps:
1. Parses the input AsyncAPI document using the specified parse options.
2. Validates the template configuration and parameters.
3. Configures the template based on the parsed AsyncAPI document.
4. Registers filters, hooks, and launches the 'generate:before' hook if applicable.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<void>` - A promise that resolves when the configuration is completed.  
**Params**

- parseOptions `*` - Options for parsing the AsyncAPI document.

<a name="Generator+handleEntrypoint"></a>

* generator.handleEntrypoint() ⇒ `Promise.<void>`** :
Handles the logic for the template entrypoint.

If an entrypoint is specified:
- Resolves the absolute path of the entrypoint file.
- Throws an error if the entrypoint file doesn't exist.
- Generates a file or renders content based on the output type.
- Launches the 'generate:after' hook if the output is 'fs'.

If no entrypoint is specified, generates the directory structure.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<void>` - A promise that resolves when the entrypoint logic is completed.  

<a name="Generator+executeAfterHook"></a>

* generator.executeAfterHook() ⇒ `Promise.<void>`** :
Executes the 'generate:after' hook.

Launches the after-hook to perform additional actions after code generation.

**Kind**: instance method of [`Generator`](#Generator)  
**Returns**: `Promise.<void>` - A promise that resolves when the after-hook execution is completed.  

<a name="Generator+parseInput"></a>

* generator.parseInput()** :
Parse the generator input based on the template `templateConfig.apiVersion` value.

**Kind**: instance method of [`Generator`](#Generator)  

<a name="Generator+configureTemplate"></a>

* generator.configureTemplate()** :
Configure the templates based the desired renderer.

**Kind**: instance method of [`Generator`](#Generator)  

<a name="Generator+generateFromURL"></a>

### generator.generateFromURL
Generates files from a given template and AsyncAPI file stored on external server.

**Kind**: instance method of [`Generator`](#Generator)  
**Params**

- asyncapiURL `String` - Link to AsyncAPI file

**Example**  
```js
generator
  .generateFromURL('https://example.com/asyncapi.yaml')
  .then(() => {
    console.log('Done!');
  })
  .catch(console.error);
```
**Example** *(Using async/await)*  
```js
try {
  await generator.generateFromURL('https://example.com/asyncapi.yaml');
  console.log('Done!');
} catch (e) {
  console.error(e);
}
```

<a name="Generator+generateFromFile"></a>

### generator.generateFromFile
Generates files from a given template and AsyncAPI file.

**Kind**: instance method of [`Generator`](#Generator)  
**Params**

- asyncapiFile `String` - AsyncAPI file to use as source.

**Example**  
```js
generator
  .generateFromFile('asyncapi.yaml')
  .then(() => {
    console.log('Done!');
  })
  .catch(console.error);
```
**Example** *(Using async/await)*  
```js
try {
  await generator.generateFromFile('asyncapi.yaml');
  console.log('Done!');
} catch (e) {
  console.error(e);
}
```

<a name="Generator+installTemplate"></a>

### generator.installTemplate
Downloads and installs a template and its dependencies

**Kind**: instance method of [`Generator`](#Generator)  
**Params**

- [force] `Boolean` ` = false` - Whether to force installation (and skip cache) or not.

<a name="Generator.getTemplateFile"></a>

### Generator.getTemplateFile
Returns the content of a given template file.

**Kind**: static method of [`Generator`](#Generator)  
**Params**

- templateName `String` - Name of the template to generate.
- filePath `String` - Path to the file to render. Relative to the template directory.
- [templatesDir] `String` ` = DEFAULT_TEMPLATES_DIR` - Path to the directory where the templates are installed.

**Example**  
```js
const Generator = require('@asyncapi/generator');
const content = await Generator.getTemplateFile('@asyncapi/html-template', 'partials/content.html');
```
**Example** *(Using a custom &#x60;templatesDir&#x60;)*  
```js
const Generator = require('@asyncapi/generator');
const content = await Generator.getTemplateFile('@asyncapi/html-template', 'partials/content.html', '~/my-templates');
```

<a name="listBakedInTemplates"></a>

## listBakedInTemplates
List core templates, optionally filter by type, stack, protocol, or target.
Use name of returned templates as input for the `generate` method for template generation. Such core templates code is part of the @asyncapi/generator package.

**Kind**: global variable  
**Returns**: `Array.<Object>` - Array of template objects matching the filter.  
**Params**

- [filter] `Object` - Optional filter object.
    - [.type] `string` - Filter by template type (e.g., 'client', 'docs').
    - [.stack] `string` - Filter by stack (e.g., 'quarkus', 'express').
    - [.protocol] `string` - Filter by protocol (e.g., 'websocket', 'http').
    - [.target] `string` - Filter by target language or format (e.g., 'javascript', 'html').

---

# Reusable Components API
Source: https://www.asyncapi.com/docs/tools/generator/api_components.md

# Reusable Components API

## Components

* [CloseConnection](#CloseConnection) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket close connection method with optional pre- and post-execution logic.

* [Connect](#Connect) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket connection method for the specified programming language.

* [DependencyProvider](#DependencyProvider) ⇒ `JSX.Element`<br/>
  
  Renders the top-of-file dependency statements for the selected programming language.

* [Close](#Close) ⇒ `JSX.Element`<br/>
  
  Renders the `client.close()` invocation line for the runnable example
script in the chosen language. Sibling of `OpenConnection`; meant to
be embedded inside the `finally` block of the example script.

* [Handlers](#Handlers) ⇒ `JSX.Element`<br/>
  
  Renders the message/error handler definitions block for the runnable
example script. JavaScript and Dart render a static pair of placeholder
handlers; Python renders one per-receive-operation handler plus a custom
error handler.

* [Imports](#Imports) ⇒ `JSX.Element`<br/>
  
  Renders the top-of-file imports block for the runnable example script.

* [OpenConnection](#OpenConnection) ⇒ `JSX.Element`<br/>
  
  Renders the `client.connect()` invocation line for the runnable example
script in the chosen language. Sibling of `Close` and
`SendInvocations`; meant to be embedded inside the example script.

* [OutgoingProcessor](#OutgoingProcessor) ⇒ `JSX.Element`<br/>
  
  Renders an example outgoing message processor function for the runnable
example script. The body is a starter implementation; users customize it
after generation.

* [SendInvocations](#SendInvocations) ⇒ `JSX.Element`<br/>
  
  Renders the send-invocations loop for the runnable example script: a fixed
5-iteration loop that invokes each send operation in turn, with sample
payloads resolved from the AsyncAPI message examples (or `TODO:` placeholders
when no example is present).

Returns `null` when `sendOps` is missing or empty so the caller can render
nothing without conditional wrapping.

* [FileHeaderInfo](#FileHeaderInfo) ⇒ `JSX.Element`<br/>
  
  Renders a file header with metadata information such as title, version, protocol, host, and path.

* [HandleError](#HandleError) ⇒ `JSX.Element`<br/>
  
  Renders the `handleError` (or framework-equivalent) method body that dispatches
an error to registered handlers (or logs it when none are registered).

* [HandleMessage](#HandleMessage) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket message handler method with optional pre- and post-execution logic.

* [MethodGenerator](#MethodGenerator) ⇒ `JSX.Element`<br/>
  
  Renders a language-specific formatted method definition.

* [Models](#Models) ⇒ `Array.<File>`<br/>
  
  Renders an array of model files based on the AsyncAPI document.

* [OnClose](#OnClose) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket onClose event handler for the specified programming language.

* [OnError](#OnError) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket onError event handler for the specified programming language.

* [OnMessage](#OnMessage) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket onMessage event handler for the specified programming language.

* [OnOpen](#OnOpen) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket onOpen event handler for the specified programming language.

* [QueryParamsVariables](#QueryParamsVariables) ⇒ `Array.<JSX.Element>`<br/>
  
  Renders query parameter variables code blocks.

* [AvailableOperations](#AvailableOperations) ⇒ `JSX.Element`<br/>
  
  Renders a list of AsyncAPI operations with their headers and message examples.

* [CoreMethods](#CoreMethods) ⇒ `JSX.Element`<br/>
  
  Renders a list of core WebSocket client methods for a given target language.

* [Installation](#Installation) ⇒ `JSX.Element`<br/>
  
  Renders the Installation Command for a given language.

* [MessageExamples](#MessageExamples) ⇒ `JSX.Element`<br/>
  
  Renders Message Examples of a given AsyncAPI operation.

* [OperationHeader](#OperationHeader) ⇒ `JSX.Element`<br/>
  
  Renders a header section for a single AsyncAPI operation.

* [Overview](#Overview) ⇒ `JSX.Element`<br/>
  
  Renders an overview section for a WebSocket client. Displays the API description, version, and server URL.

* [Readme](#Readme) ⇒ `JSX.Element`<br/>
  
  Renders a README.md file for a given AsyncAPI document. Composes multiple sections (overview, installation, usage, core methods, and available operations) into a single File component based on the provided AsyncAPI document, generator parameters, and target language.

* [Usage](#Usage) ⇒ `JSX.Element`<br/>
  
  Renders a usage example snippet for a generated WebSocket client in a given language.

* [RegisterErrorHandler](#RegisterErrorHandler) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket error handler registration method with optional pre- and post-execution logic.

* [RegisterMessageHandler](#RegisterMessageHandler) ⇒ `JSX.Element`<br/>
  
  Renders a WebSocket message handler registration method with optional pre- and post-execution logic.

* [RegisterOutgoingProcessor](#RegisterOutgoingProcessor) ⇒ `JSX.Element`<br/>
  
  Renders the client method that registers an outgoing message processor.
Registered processors are stored on the client instance and run in sequence
on each message before it is sent.

* [SendOperations](#SendOperations) ⇒ `Array.<JSX.Element>`<br/>
  
  Renders WebSocket send operation methods. Generates both static and instance methods for sending messages through WebSocket connections.

* [createError](#createError) ⇒ `Error`<br/>
  
  Creates an error with a specific error code for programmatic handling

<a name="CloseConnection"></a>
### CloseConnection()
Renders a WebSocket close connection method with optional pre- and post-execution logic.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Programming language used for method formatting. |
| props.framework | `string` | Framework used, if any (e.g., &#x27;quarkus&#x27; for Java). |
| props.methodName | `string` | Name of the method to generate. |
| props.methodParams | `Array.<string>` | List of parameters for the method. |
| props.preExecutionCode | `string` | Code to insert before the main function logic. |
| props.postExecutionCode | `string` | Code to insert after the main function logic. |
| props.indent | `number` | Indentation level for the method block. |

**Returns**

- `JSX.Element` - A Text component that contains method block with appropriate formatting.

**Example**

```js
import { CloseConnection } from "@asyncapi/generator-components";
const language = "java";
const framework = "quarkus";
const methodName = "terminateConnection";
const methodParams = ["String reason"];
const preExecutionCode = "// About to terminate connection";
const postExecutionCode = "// Connection terminated";
const indent = 2;

function renderCloseConnection() {
  return (
    
  );
}

renderCloseConnection();
```

<a name="Connect"></a>
### Connect()
Renders a WebSocket connection method for the specified programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to generate connection code. |
| props.title | `string` | The title of the WebSocket server. |

**Returns**

- `JSX.Element` - A Text component containing the generated WebSocket connection code for the specified language.

**Example**

```js
import { Connect } from "@asyncapi/generator-components";
const language = "python";
const title = "HoppscotchEchoWebSocketClient";

function renderConnect() {
  return(
   
  )
}

renderConnect();
```

<a name="DependencyProvider"></a>
### DependencyProvider()
Renders the top-of-file dependency statements for the selected programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to render dependency statements. |
| props.framework | `string` | The framework (e.g., &#x27;quarkus&#x27; for Java). |
| props.role | `string` | The role (e.g., &#x27;client&#x27;, &#x27;connector&#x27; for Java). |
| props.additionalDependencies | `Array.<string>` | Optional additional dependencies to include. |

**Returns**

- `JSX.Element` - A Text component that contains list of import/require statements.

**Example**

```js
import { DependencyProvider } from "@asyncapi/generator-components";
const language = "java";
const framework = "quarkus";
const role = "client";
const additionalDependencies = ["import java.util.concurrent.CompletableFuture;", "import java.time.Duration;"];

function renderDependencyProvider() {
  return (
    
  )
}
renderDependencyProvider();
```

<a name="Close"></a>
### Close()
Renders the &#x60;client.close()&#x60; invocation line for the runnable example
script in the chosen language. Sibling of &#x60;OpenConnection&#x60;; meant to
be embedded inside the &#x60;finally&#x60; block of the example script.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |
| props.instanceName | `string` | The client instance variable name (e.g. &#x60;echoClient&#x60;, &#x60;echo_client&#x60;). |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the close invocation line.

**Example**

```js
import { Close } from "@asyncapi/generator-components";

function renderClose() {
  return (
    
  );
}

renderClose();
```

<a name="Handlers"></a>
### Handlers()
Renders the message/error handler definitions block for the runnable
example script. JavaScript and Dart render a static pair of placeholder
handlers; Python renders one per-receive-operation handler plus a custom
error handler.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |
| props.receiveOps | `Array.<object>` | Python-only: the AsyncAPI receive operations to generate handler definitions for. Defaults to an empty array. Ignored for JavaScript and Dart. |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the handler definitions.

**Example**

```js
import { Handlers } from "@asyncapi/generator-components";

function renderHandlers() {
  return (
    
  );
}

renderHandlers();
```

<a name="Imports"></a>
### Imports()
Renders the top-of-file imports block for the runnable example script.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |
| props.clientFileName | `string` | The generated client file name (e.g. &#x60;myClient.js&#x60;, &#x60;my_client.py&#x60;, &#x60;my_client.dart&#x60;). |
| props.clientName | `string` | The generated client class/symbol name. Required for JavaScript/Python; unused for Dart. |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the imports block.

**Example**

```js
import { Imports } from "@asyncapi/generator-components";

function renderImports() {
  return (
    
  );
}

renderImports();
```

<a name="OpenConnection"></a>
### OpenConnection()
Renders the &#x60;client.connect()&#x60; invocation line for the runnable example
script in the chosen language. Sibling of &#x60;Close&#x60; and
&#x60;SendInvocations&#x60;; meant to be embedded inside the example script.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |
| props.instanceName | `string` | The client instance variable name (e.g. &#x60;echoClient&#x60;, &#x60;echo_client&#x60;). |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the connect invocation line.

**Example**

```js
import { OpenConnection } from "@asyncapi/generator-components";

function renderOpenConnection() {
  return (
    
  );
}

renderOpenConnection();
```

<a name="OutgoingProcessor"></a>
### OutgoingProcessor()
Renders an example outgoing message processor function for the runnable
example script. The body is a starter implementation; users customize it
after generation.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the processor function definition.

**Example**

```js
import { OutgoingProcessor } from "@asyncapi/generator-components";

function renderOutgoingProcessor() {
  return (
    
  );
}

renderOutgoingProcessor();
```

<a name="SendInvocations"></a>
### SendInvocations()
Renders the send-invocations loop for the runnable example script: a fixed
5-iteration loop that invokes each send operation in turn, with sample
payloads resolved from the AsyncAPI message examples (or &#x60;TODO:&#x60; placeholders
when no example is present).

Returns &#x60;null&#x60; when &#x60;sendOps&#x60; is missing or empty so the caller can render
nothing without conditional wrapping.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |
| props.instanceName | `string` | The client instance variable name. |
| props.sendOps | `Array.<object>` | AsyncAPI send operations to invoke. When empty or missing, the component renders nothing. |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the loop, or &#x60;null&#x60; when there are no send operations.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { SendInvocations } from "@asyncapi/generator-components";

async function renderSendInvocations() {
  const parser = new Parser();
  const fixture = path.resolve(__dirname, "../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml");
  const parseResult = await fromFile(parser, fixture).parse();
  const sendOps = parseResult.document.operations().filterBySend();

  return (
    
  );
}

renderSendInvocations().catch(console.error);
```

<a name="FileHeaderInfo"></a>
### FileHeaderInfo()
Renders a file header with metadata information such as title, version, protocol, host, and path.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.info | `Object` | Info object from the AsyncAPI document. |
| props.server | `Object` | Server object from the AsyncAPI document. |
| props.language | `Language` | Programming language used for comment formatting. |

**Returns**

- `JSX.Element` - A Text component that contains file header.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { FileHeaderInfo } from "@asyncapi/generator-components";

async function renderFileHeader() {
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, "../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml");
  const language = "javascript";
  
  // Parse the AsyncAPI document 
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;
  
  return (
    
  )
}

renderFileHeader().catch(console.error);
```

<a name="HandleError"></a>
### HandleError()
Renders the &#x60;handleError&#x60; (or framework-equivalent) method body that dispatches
an error to registered handlers (or logs it when none are registered).

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` |  |
| props.language | `Language` | Target programming language. |
| props.framework | `string` | Framework discriminator (required for languages with multiple frameworks, e.g. &#x60;java&#x60; → &#x60;quarkus&#x60;). |

**Returns**

- `JSX.Element` - A &#x60;&lt;Text&gt;&#x60; block containing the rendered method.

**Example**

```js
import { HandleError } from '@asyncapi/generator-components';

function renderHandleError() {
  return ;
}
```

<a name="HandleMessage"></a>
### HandleMessage()
Renders a WebSocket message handler method with optional pre- and post-execution logic.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Programming language used for method formatting. |
| props.methodName | `string` | Name of the method to generate. |
| props.methodParams | `Array.<string>` | List of parameters for the method. |
| props.preExecutionCode | `string` | Code to insert before the main function logic. |
| props.postExecutionCode | `string` | Code to insert after the main function logic. |
| props.customMethodConfig | `Object` | Optional overrides for default method configuration. |

**Returns**

- `JSX.Element` - A Text component that contains method block with appropriate formatting.

**Example**

```js
import { HandleMessage } from "@asyncapi/generator-components";
const language = "javascript";
const methodName = "handleMessage";
const methodParams = ["message","cb"];
const preExecutionCode = "// Pass the incoming message to all registered message handlers.";
const postExecutionCode = "// Passed the incoming message to all registered message handlers.";
const customMethodConfig = {
  javascript: {
    methodDocs: "// Method to handle message with callback",
    methodLogic: "if (cb) cb(message);"
  }
};

function renderHandleMessage() {
  return (
    
  )
}

renderHandleMessage();
```

<a name="MethodGenerator"></a>
### MethodGenerator()
Renders a language-specific formatted method definition.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Programming language used for method formatting. |
| props.methodName | `string` | Name of the method (non-empty string required). |
| props.methodParams | `Array.<string>` | Method parameters. |
| props.methodDocs | `string` | Optional documentation string. |
| props.methodLogic | `string` | Core method logic. |
| props.preExecutionCode | `string` | Code before main logic. |
| props.postExecutionCode | `string` | Code after main logic. |
| props.indent | `number` | Indentation for the method block (must be &gt;&#x3D; 0). |
| props.newLines | `number` | Number of new lines after method. |
| props.customMethodConfig | `Object` | Optional custom syntax configuration for the current language. |
| props.methodConfig | `Object` | Language-level or framework-level configuration. |
| props.framework | `string` | Framework name for nested configurations (e.g., &#x27;quarkus&#x27; for Java). |

**Returns**

- `JSX.Element` - A Text component that contains method block with appropriate formatting.

**Example**

```js
import { MethodGenerator } from "@asyncapi/generator-components";
const language = "java";
const methodName = "registerHandler";
const methodParams = ["Handler handler"];
const methodDocs = "// Process the input data.";
const methodLogic = "// TODO: implement";
const preExecutionCode = "// Before handler registration";
const postExecutionCode = "// After handler registration";
const customMethodConfig={ openingTag: "{", closingTag: "}", indentSize: 6 };
const methodConfig = {"java" : {"quarkus": {methodDocs : methodDocs, methodLogic: methodLogic }}};
const framework = "quarkus";

function renderMethodGenerator() {
  return (
    
  )
}

renderMethodGenerator();
```

<a name="Models"></a>
### Models()
Renders an array of model files based on the AsyncAPI document.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.asyncapi | `AsyncAPIDocumentInterface` | Parsed AsyncAPI document object. |
| props.language | `Language` | Target programming language for the generated models. |
| props.format | `Format` | Naming format for generated files. |
| props.presets | `Object` | Custom presets for the generator instance. |
| props.constraints | `Object` | Custom constraints for the generator instance. |

**Returns**

- `Array.<File>` - Array of File components with generated model content.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { Models } from "@asyncapi/generator-components";

async function renderModel() {
   const parser = new Parser();
   const asyncapi_v3_path = path.resolve(__dirname, "../__fixtures__/asyncapi-v3.yml");

    // Parse the AsyncAPI document
   const parseResult = await fromFile(parser, asyncapi_v3_path).parse();
   const parsedAsyncAPIDocument = parseResult.document;
   
   const language = "java";
   
   return (
     
   )
}

renderModel().catch(console.error);
```

<a name="OnClose"></a>
### OnClose()
Renders a WebSocket onClose event handler for the specified programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to generate onClose handler code. |
| props.framework | `string` | Framework variant; required for framework-specific languages (e.g., &#x27;quarkus&#x27; for java). |
| props.title | `string` | The title of the WebSocket server. |

**Returns**

- `JSX.Element` - A Text component containing the onClose handler code for the specified language.

**Example**

```js
import { OnClose } from "@asyncapi/generator-components";
const language = "java";
const framework = "quarkus";
const title = "HoppscotchEchoWebSocketClient";

function renderOnClose() {
 return (
   
 )
}

renderOnClose();
```

<a name="OnError"></a>
### OnError()
Renders a WebSocket onError event handler for the specified programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to generate onError handler code. |

**Returns**

- `JSX.Element` - A Text component containing the onError handler code for the specified language.

**Example**

```js
import { OnError } from "@asyncapi/generator-components";
const language = "javascript";

function renderOnError() {
  return (
    
  )
}

renderOnError();
```

<a name="OnMessage"></a>
### OnMessage()
Renders a WebSocket onMessage event handler for the specified programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to generate onMessage handler code. |

**Returns**

- `JSX.Element` - A Text component containing the onMessage handler code for the specified language.

**Example**

```js
import { OnMessage } from "@asyncapi/generator-components";
const language = "javascript";

function renderOnMessage() {
  return (
    
  )
}

renderOnMessage();
```

<a name="OnOpen"></a>
### OnOpen()
Renders a WebSocket onOpen event handler for the specified programming language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The programming language for which to generate onOpen handler code. |
| props.framework | `string` | Optional framework variant (e.g., &#x27;quarkus&#x27; for java). |
| props.title | `string` | The title of the WebSocket server. |

**Returns**

- `JSX.Element` - A Text component containing the onOpen handler code for the specified language.

**Example**

```js
import { OnOpen } from "@asyncapi/generator-components";
const language = "java";
const framework = "quarkus";
const title = "HoppscotchEchoWebSocketClient";

function renderOnOpen() {
  return (
    
  )
}

renderOnOpen();
```

<a name="QueryParamsVariables"></a>
### QueryParamsVariables()
Renders query parameter variables code blocks.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The target programming language. |
| props.framework | `string` | Optional framework for the language. |
| props.queryParams | `Array.<Array.<string>>` | Array of query parameters, each represented as [paramName, paramType?]. |

**Returns**

- `Array.<JSX.Element>` - Array of Text components for each query parameter, or null if queryParams is invalid.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { getQueryParams } from "@asyncapi/generator-helpers";
import { QueryParamsVariables } from "@asyncapi/generator-components";

async function renderQueryParamsVariable(){
   const parser = new Parser();
   const asyncapi_v3_path = path.resolve(__dirname, "../__fixtures__/asyncapi-v3.yml");
   
   // Parse the AsyncAPI document
   const parseResult = await fromFile(parser, asyncapi_v3_path).parse();
   const parsedAsyncAPIDocument = parseResult.document;
   
   const channels = parsedAsyncAPIDocument.channels();
   const queryParamsObject = getQueryParams(channels);
   const queryParamsArray = queryParamsObject ? Array.from(queryParamsObject.entries()) : [];
   
   const language = "java";
   const framework = "quarkus";
   
   return (
     
   )
}

renderQueryParamsVariable().catch(console.error);
```

<a name="AvailableOperations"></a>
### AvailableOperations()
Renders a list of AsyncAPI operations with their headers and message examples.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component Props |
| props.operations | `Array.<Object>` | Array of AsyncAPI Operation objects. |

**Returns**

- `JSX.Element` - A Component containing rendered operations, or null if no operations are provided

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { AvailableOperations } from "@asyncapi/generator-components";

async function renderAvailableOperations(){
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, '../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml');

  //parse the AsyncAPI document
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;

  return (
   
  )    
}

renderAvailableOperations().catch(console.error);
```

<a name="CoreMethods"></a>
### CoreMethods()
Renders a list of core WebSocket client methods for a given target language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props |
| props.language | `Language` | Target language used to select method names. |

**Returns**

- `JSX.Element` - A Text component that contains a list of core client methods.

**Example**

```js
import { CoreMethods } from "@asyncapi/generator-components";
const language = "javascript";

function renderCoreMethods() {
  return (
    
  )
}

renderCoreMethods();
```

<a name="Installation"></a>
### Installation()
Renders the Installation Command for a given language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props |
| props.language | `Language` | The programming language for which to generate Installation Command. |

**Returns**

- `JSX.Element` - A Text component that contains Installation Command.

**Example**

```js
import { Installation } from "@asyncapi/generator-components";
const language = "javascript";

function renderInstallation() {
  return (
    
  )
}

renderInstallation()
```

<a name="MessageExamples"></a>
### MessageExamples()
Renders Message Examples of a given AsyncAPI operation.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component Props |
| props.operation | `Object` | An AsyncAPI Operation object. |

**Returns**

- `JSX.Element` - A Text component that contains message examples, or null when no examples exist.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { MessageExamples } from "@asyncapi/generator-components";

async function renderMessageExamples(){
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, '../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml');

  //parse the AsyncAPI document
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;
  const operations = parsedAsyncAPIDocument.operations().all();

  return operations.map((operation) => {
     return (
       
     )    
  });
}

renderMessageExamples().catch(console.error);
```

<a name="OperationHeader"></a>
### OperationHeader()
Renders a header section for a single AsyncAPI operation.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component properties. |
| props.operation | `Object` | An AsyncAPI Operation object. |

**Returns**

- `JSX.Element` - A Text component that contains formatted operation header.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { OperationHeader } from "@asyncapi/generator-components";

async function renderOperationHeader(){
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, '../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml');

  //parse the AsyncAPI document
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;
  const operations = parsedAsyncAPIDocument.operations().all();

  return operations.map((operation) => {
     return (
       
     )    
  });
}

renderOperationHeader().catch(console.error);
```

<a name="Overview"></a>
### Overview()
Renders an overview section for a WebSocket client. Displays the API description, version, and server URL.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props |
| props.info | `Object` | Info object from the AsyncAPI document. |
| props.title | `string` | Title from the AsyncAPI document. |
| props.serverUrl | `string` | ServerUrl from a specific server from the AsyncAPI document. |

**Returns**

- `JSX.Element` - A Text component that contains the Overview of a Websocket client.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { getServer, getServerUrl } from '@asyncapi/generator-helpers';
import { Overview } from "@asyncapi/generator-components";

async function renderOverview(){
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, '../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml');

  //parse the AsyncAPI document
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;

  const info = parsedAsyncAPIDocument.info();
  const title = info.title();
  const server = getServer(parsedAsyncAPIDocument.servers(), 'withoutPathName');
  const serverUrl = getServerUrl(server);

  return (
     
  )
}

renderOverview().catch(console.error);
```

<a name="Readme"></a>
### Readme()
Renders a README.md file for a given AsyncAPI document. Composes multiple sections (overview, installation, usage, core methods, and available operations) into a single File component based on the provided AsyncAPI document, generator parameters, and target language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props |
| props.asyncapi | `AsyncAPIDocumentInterface` | Parsed AsyncAPI document instance. |
| props.params | `Object` | Generator parameters used to customize output |
| props.language | `Language` | Target language used to render language-specific sections. |

**Returns**

- `JSX.Element` - A File component representing the generated README.md.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { buildParams } from '@asyncapi/generator-helpers';
import { Readme } from "@asyncapi/generator-components";

async function renderReadme(){
  const parser = new Parser();
  const asyncapi_websocket_query = path.resolve(__dirname, '../../../helpers/test/__fixtures__/asyncapi-websocket-query.yml');

  // parse the AsyncAPI document
  const parseResult = await fromFile(parser, asyncapi_websocket_query).parse();
  const parsedAsyncAPIDocument = parseResult.document;
  const language = "javascript";
  const config = { clientFileName: 'myClient.js' };
  const params = buildParams('javascript', config, 'echoServer');
  
  return (
    
  )
}

renderReadme().catch(console.error);
```

<a name="Usage"></a>
### Usage()
Renders a usage example snippet for a generated WebSocket client in a given language.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props |
| props.clientName | `string` | The exported name of the client. |
| props.clientFileName | `string` | The file name where the client is defined. |
| props.language | `Language` | The target language for which to render the usage snippet |

**Returns**

- `JSX.Element` - A Text component containing a formatted usage example snippet.

**Example**

```js
import { Usage } from "@asyncapi/generator-components";
const clientName = "MyClient";
const clientFileName = "myClient.js";
const language = "javascript";

function renderUsage(){
  return (
    
  )
}

renderUsage();
```

<a name="RegisterErrorHandler"></a>
### RegisterErrorHandler()
Renders a WebSocket error handler registration method with optional pre- and post-execution logic.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Programming language used for method formatting. |
| props.methodName | `string` | Name of the method to generate. |
| props.methodParams | `Array.<string>` | List of parameters for the method. |
| props.preExecutionCode | `string` | Code to insert before the main function logic. |
| props.postExecutionCode | `string` | Code to insert after the main function logic. |
| props.customMethodConfig | `Object` | Optional overrides for default method configuration. |

**Returns**

- `JSX.Element` - A Text component that contains method block with appropriate formatting.

**Example**

```js
import { RegisterErrorHandler } from "@asyncapi/generator-components";
const language = "python";
const methodName = "registerErrorHandler";
const methodParams = ["self", "handler"];
const preExecutionCode = "# Pre-register operations";
const postExecutionCode = "# Post-register operations";
const customMethodConfig = { returnType: "int", openingTag: "{", closingTag: "}", indentSize: 2};

function renderRegisterErrorHandler() {
 return (
   
 )
}

renderRegisterErrorHandler();
```

<a name="RegisterMessageHandler"></a>
### RegisterMessageHandler()
Renders a WebSocket message handler registration method with optional pre- and post-execution logic.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Programming language used for method formatting. |
| props.methodName | `string` | Name of the method to generate. |
| props.methodParams | `Array.<string>` | List of parameters for the method. |
| props.preExecutionCode | `string` | Code to insert before the main function logic. |
| props.postExecutionCode | `string` | Code to insert after the main function logic. |

**Returns**

- `JSX.Element` - A Text component that contains method block with appropriate formatting.

**Example**

```js
import { RegisterMessageHandler } from "@asyncapi/generator-components";
const language = "python";
const methodName = "registerMessageHandler";
const methodParams = ["self", "handler"];
const preExecutionCode = "# Pre-register operations";
const postExecutionCode = "# Post-register operations";

function renderRegisterMessageHandler(){
  return (
     
  )
}

renderRegisterMessageHandler();
```

<a name="RegisterOutgoingProcessor"></a>
### RegisterOutgoingProcessor()
Renders the client method that registers an outgoing message processor.
Registered processors are stored on the client instance and run in sequence
on each message before it is sent.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | Target programming language. |

**Returns**

- `JSX.Element` - A &#x60;Text&#x60; component containing the registration method definition.

**Example**

```js
import { RegisterOutgoingProcessor } from "@asyncapi/generator-components";

function renderRegisterOutgoingProcessor() {
  return (
    
  );
}

renderRegisterOutgoingProcessor();
```

<a name="SendOperations"></a>
### SendOperations()
Renders WebSocket send operation methods. Generates both static and instance methods for sending messages through WebSocket connections.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| props | `Object` | Component props. |
| props.language | `Language` | The target programming language. |
| props.sendOperations | `Array.<Object>` | Array of send operations from AsyncAPI document. |
| props.clientName | `string` | The name of the client class. |

**Returns**

- `Array.<JSX.Element>` - Array of Text components for static and non-static WebSocket send operation methods, or null if no send operations are provided.

**Example**

```js
import path from "path";
import { Parser, fromFile } from "@asyncapi/parser";
import { SendOperations } from "@asyncapi/generator-components";

async function renderSendOperations(){
   const parser = new Parser();
   const asyncapi_v3_path = path.resolve(__dirname, '../__fixtures__/asyncapi-v3.yml');
   
   // Parse the AsyncAPI document
   const parseResult = await fromFile(parser, asyncapi_v3_path).parse();
   const parsedAsyncAPIDocument = parseResult.document;
   
   const language = "javascript";
   const clientName = "AccountServiceAPI";
   const sendOperations = parsedAsyncAPIDocument.operations().filterBySend();
   
   return (
      
   )
}

renderSendOperations().catch(console.error);
```

<a name="createError"></a>
### createError()
Creates an error with a specific error code for programmatic handling

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| code | `string` | The error code (from ERROR_CODES) |
| message | `string` | The error message |

**Returns**

- `Error` - An error object with an attached code property

---

# Template development
Source: https://www.asyncapi.com/docs/tools/generator/template-development.md

# Template development

> **Note**
> It is advised against attempting to manually template types and models from scratch using the AsyncAPI templating engines such as the React render engine. Instead, it is recommended to use [AsyncAPI Modelina](/docs/tools/generator/model-generation.md) a dedicated library for model generation.

## Minimum template requirements

Let's break down the minimum template requirements: the `template` directory and a `package.json` file.

> You can also check [Template for Generator Templates](https://github.com/asyncapi/template-for-generator-templates) project to see show-case template based on the AsyncAPI Generator.

### `template` directory

The `template` directory holds all the files that will be used for generating the output. The generator will process all the files stored in this directory.

The following code is an example of an `index.js` file inside the `template` folder.
```js
import { File, Text } from "@asyncapi/generator-react-sdk";

export default function ({ asyncapi, params, originalAsyncAPI }) {
  return (
    
      My application's markdown file.
      App name: **{asyncapi.info().title()}**
    
  );
}
```

The above example will produce an `asyncapi.md` file where usage of the AsyncAPI document information (i.e. the `title`) is demonstrated.

### `package.json` file

Before the generation process begins, the generator installs the template into its dependencies. A `package.json` file is necessary to identify the template name.

The following block shows an example `package.json` file that points to the [React Render Engine](react-render-engine) and necessary dependencies:

```json
{
  "name": "myTemplate",
  "generator": {},
  "dependencies": {
    "@asyncapi/generator-react-sdk": "^0.2.25"
  }
}
```

Every template must depend on the [`@asyncapi/generator-react-sdk` package](https://github.com/asyncapi/generator-react-sdk), which contains a template file's basic components.

## Additional configuration options

You must configure the generator's `package.json` file to contain JSON objects with the required parameters for template configuration, such as:

|Name|Type|Description|
|---|---|---|
|`supportedProtocols`| [String] | A list with all the protocols this template supports.
|`parameters`| Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`.
|`parameters[param].description`| String | A user-friendly description about the parameter.
|`parameters[param].default`| Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters.
|`parameters[param].required`| Boolean | Whether the parameter is required or not.

The above table lists some configuration options that help the generator achieve a specific set of tasks throughout the generation process. The `generator` property from 'package.json' contains all the configuration information. To learn more about template configuration and various supported parameters, read the [generator configuration file](configuration-file).

> Whenever you make a change to the package.json, make sure you perform an update by running `npm install`;  this command synchronizes with the `package-lock.json` and validates the file.

### `package.json` configuration options 

The following examples show some advanced configurations that we can use in our `package.json` file:

```json
{
  "name": "myTemplate",
  "generator": {
    "supportedProtocols": [
      "mqtt"
    ]
  },
  "dependencies": {
    "@asyncapi/generator-react-sdk": "^0.2.25"
  }
}
```
The above `package.json` file has a newly added configuration called `supportedProtocols` which is set to a list containing only `mqtt`. This configuration displays all the protocols that this template supports. You can have multiple supported protocols in our template. 

For example, if you want to generate an output using the above template, you need to have an AsyncAPI document with servers that use `mqtt` to generate your desired output. If your AsyncAPI document has server connections with `kafka`, the generation process will be terminated since the only supported protocol mentioned is `mqtt`. 

### Accessing template parameters

Additionally, we can also have a configuration called `parameters`, which is an object with all the parameters that can be passed when generating the template:

```json
{
  "name": "myTemplate",
  "generator": {
    "supportedProtocols": [
      "mqtt"
    ],
    "parameters": {
        "version": {
          "description": "Overrides application version under `info.version` in the AsyncAPI document.",
          "required": false
        }
    }
  },
  "dependencies": {
    "@asyncapi/generator-react-sdk": "^0.2.25"
  }
}
```

The default version of your application is always fetched from your AsyncAPI document. The above configuration helps the template user override the existing version with a new one on the command line.

The changes done in the template will be as follows:

Original:

```js
App name: **{ asyncapi.info().title() }**
```

Newer:

```js
App name: **{ asyncapi.info().title() }**
Version is: **{params.version || asyncapi.info.version()}**
```

Now that you have added all the configuration options, you can start the generation process using the AsyncAPI CLI. You can pass these parameters via the CLI: `--param name=value or -p name=value`.
The above configuration helps template users override the existing version with a new version on the command line. (Example: `-p version=2.0.0`)

## Hooks

[Hooks](hooks) enable templates to perform multiple tasks. You can add Hooks to your template as fractions of code. In the template, you must store it in the `hooks` directory under the template directory. You can also store it in other modules and external libraries or configure it inside the template. The generation process can perform multiple actions.

**Templates** can perform multiple actions _before_ or _after_ the generation process with the help of **hooks**.

Hooks help you change the specification version with the new `version` that you can pass before the generation process even begins:

```js
module.exports = {
  'generate:before': ({ asyncapi, templateParams = {} }) => {
    const version = templateParams.version || asyncapi.info().version();
    asyncapi._json.info.version = version;
  }
};
```
This can be an even better alternative to overriding the `version` parameter we discussed in the previous section. A markdown document will be generated, and the AsyncAPI document passed to the generator will be returned with the overwritten version.

The updated template looks like the following:

```js
App name: **{ asyncapi.info().title() }**
Version: **{asyncapi.info.version()}**
```

---

# Configuration file
Source: https://www.asyncapi.com/docs/tools/generator/configuration-file.md

# Configuration file

You can configure your AsyncAPI Generator template using either a dedicated `.ageneratorrc` YAML file or through the `generator` property in your `package.json` file. Previously, generator configuration had to be defined in the `package.json` file. Now, you can define the configuration in a separate `.ageneratorrc` file. The configuration defined in the `.ageneratorrc` file will override any configuration defined in `package.json`. The generator will first check for the `.ageneratorrc` file in the template's root directory, and if not found, it will look for the generator config in `package.json`.

> **Note:** The `metadata` object is **required** for all baked-in templates (templates developed and shipped as part of the Generator repository) and is used by the generator’s build system to index, categorize, and load these templates.  
> The `metadata` section is **not used or required** for standalone templates (external npm packages or repositories).

## Configuration methods

### Option 1: using `.ageneratorrc` file (Recommended)

Create a `.ageneratorrc` file in the root of your template with YAML syntax. This approach keeps your template configuration separate from package metadata:

```yaml
metadata:
  type: client
  protocol: websocket
  target: javascript
  stack: express

apiVersion: v3
supportedProtocols:
  - amqp
  - mqtt

parameters:
  server:
    description: The server you want to use in the code.
    required: true
  dummyParameter:
    description: Example of parameter with default value.
    default: just a string
    required: false

conditionalFiles:
  path/to/file/that/is/relative/to/template/dir/test-amqp.js:
    subject: server.protocol
    validation:
      const: amqp
  path/to/file/that/is/relative/to/template/dir/support.html:
    subject: info.contact
    validation:
      required:
        - url

conditionalGeneration:
  conditionalOnFile.js:
    parameter: singleFile
    validation:
      not:
        const: true
  conditionOnFolderInfo:
    subject: info.contact.name
    validation:
      const: API Support

nonRenderableFiles:
  - src/api/middlewares/*.*
  - lib/lib/config.js

generator: "<2.0.0"

filters:
  - my-package-with-filters

hooks:
  '@asyncapi/generator-hooks': hookFunctionName
  my-custom-hooks-package:
    - myHook
    - andAnotherOne
```

### Option 2: using `package.json`

Alternatively, you can include your configuration in the `generator` property of your `package.json` file:

```json
"generator": {
  "metadata": {
    "type": "client",
    "protocol": "websocket",
    "target": "javascript",
    "stack": "express"
  },
  "apiVersion": "v3",
  "supportedProtocols": ["amqp", "mqtt"],
  "parameters": {
    "server": {
      "description": "The server you want to use in the code.",
      "required": true
    },
    "dummyParameter": {
      "description": "Example of parameter with default value.",
      "default": "just a string",
      "required": false
    }
  },
  "conditionalGeneration": {
     "conditionalOnFile.js": { 
       "parameter": "singleFile", 
       "validation": {
          "not": { "const": "true" } 
      }
    },
     "conditionOnFolder": {
       "parameter": "singleFolder", 
       "validation": {
          "not": { "const": "true" } 
      }
    },
     "conditionOnFolderInfo": {
       "subject": "info.contact.name",
       "validation": {
            "const": "API Support"
        }
    }
  },
  "nonRenderableFiles": [
    "src/api/middlewares/*.*",
    "lib/lib/config.js"
  ],
  "generator": "<2.0.0",
  "filters": [
    "my-package-with-filters"
  ],
  "hooks": {
    "@asyncapi/generator-hooks": "hookFunctionName",
    "my-custom-hooks-package": ["myHook", "andAnotherOne"]
  }
}
```

> **Note:** If both `.ageneratorrc` file and the `generator` property in `package.json` exist, the configuration from `.ageneratorrc` will override the `package.json` configuration.

## Configuration options reference

The following table describes all available configuration options for templates.

The `generator` property from `package.json` file must contain a JSON object and the `ageneratorrc` file must contain a YAML object that may have the following information:

| Name | Type | Description |
|------|------|-------------|
| `metadata` | Object | **(Required for baked-in templates)**. Template identification and classification. Contains `type`, `protocol`, `target`, and optional `stack`. See below. |
| `metadata.type` | String | **Required**. The type of template. Allowed values: `client`, `sdk`, `docs`, `config`. |
| `metadata.protocol` | String | **Required for `client`/`sdk`**. The protocol this template targets (e.g., `websocket`, `kafka`). Not used for `docs`/`config`. |
| `metadata.target` | String | **Required**. The output language or format (e.g., `javascript`, `html`, `yaml`). |
| `metadata.stack` | String | Optional. The stack or framework (e.g., `express`, `quarkus`). Only for `client`/`sdk`. |
| `apiVersion` | String | Determines which **major** version of the [Parser-API](https://github.com/asyncapi/parser-api) the template uses. For example, `v2` for `v2.x.x`. If not specified, the Generator assumes the template is not compatible with the Parser-API so it will use the [Parser-JS v1 API](https://github.com/asyncapi/parser-js/tree/v1.18.1#api-documentation). For templates that need to support AsyncAPI specification v3 make sure to use `v3` [Parser-API](https://github.com/asyncapi/parser-api). If the template uses a version of the Parser-API that is not supported by the Generator, the Generator will throw an error. |
| `supportedProtocols` | [String] | A list with all the protocols this template supports. |
| `parameters` | Object[String, Object] | An object with all the parameters that can be passed when generating the template. When using the command line, it's done by indicating `--param name=value` or `-p name=value`. |
| `parameters[param].description` | String | A user-friendly description about the parameter. |
| `parameters[param].default` | Any | Default value of the parameter if not specified. Shouldn't be used for mandatory `required=true` parameters. |
| `parameters[param].required` | Boolean | Whether the parameter is required or not. |
| `conditionalFiles` | Object[String, Object] | An object containing all the file paths that should be conditionally rendered. Each key represents a file path and each value must be an object with the keys `subject` and `validation`. The file path should be relative to the `template` directory inside the template. **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
| `conditionalFiles[filePath].subject` | String | The `subject` is a [JMESPath](http://jmespath.org/) query to grab the value you want to apply the condition to. It queries an object with the whole AsyncAPI document and, when specified, the given server. The object looks like this: `{ asyncapi: { ... }, server: { ... } }`. If the template supports the `server` parameter, you can access server details, for example, `server.protocol`. During validation with `conditionalFiles`, only the server that the template user selected is available in the specification file. For more information about `server` parameter [read about special parameters](#special-parameters). **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
| `conditionalFiles[filePath].validation` | Object | The `validation` is a JSON Schema Draft 07 object. This JSON Schema definition will be applied to the JSON value resulting from the `subject` query. If validation doesn't have errors, the condition is met, and therefore the given file will be rendered. Otherwise, the file is ignored. Check [JSON Schema Validation](https://json-schema.org/draft-07/json-schema-validation.html#rfc.section.6) for a list of all possible validation keywords. **Note: It is deprecated and will be removed with future releases. Use `conditionalGeneration` instead.** |
| `conditionalGeneration` | Object[String, `{ subject?: String, parameter?: String, validation: Object }`] | An object containing all the file paths or directory names that should be conditionally rendered. Each key represents a file path or directory name and each value must be an object with the keys `subject`, `parameter` and `validation`. You can use either subject or parameter according to the use case. The path should be relative to the `template` directory inside the template. **Note: conditionalGeneration and conditionalFile are mutually exclusive, which means both cannot be configured at the same time in the template**. |
| `conditionalGeneration[filePath/directoryName].subject` | String | The `subject` is a [JMESPath](http://jmespath.org/) query to grab the value you want to apply the condition to. It queries an object with the whole AsyncAPI document and, when specified, the given server. The object looks like this: `{ asyncapi: { ... }, server: { ... } }`. If the template supports the `server` parameter, you can access server details like, for example, protocol this way: `server.protocol`. During validation with `conditionalGeneration`, only the server that the template user selected is available in the specification file. For more information about the `server` parameter [read about special parameters](#special-parameters). |
| `conditionalGeneration[filePath/directoryName].parameter` | String | The `parameter` is the name of a custom template parameter passed through `templateParams` that controls whether a specific file or folder should be included in the generated output. You must define a `validation` rule using a JSON Schema fragment to apply the condition. For example, if you define `"parameter": "includeDocs"` with `"validation": { "const": true }`, the corresponding folder (e.g., `docs/`) will only be generated when the user passes `{ includeDocs: true }`. If `includeDocs` is `false`, it will be skipped. When you rely on a parameter here, make sure its default value declared in the `parameters` section uses the same data type your validation expects; mismatched types lead to failing conditions even when the defaults should allow generation. |
| `conditionalGeneration[filePath/directoryName].validation` | Object (JSON Schema fragment) | The validation defines the condition under which the file or directory will be generated. It must be a valid JSON Schema fragment that validates the value of the parameter. For example, if you want to include a folder only when includeDocs is true, use "validation": `{ "const": true }`. You can also use more complex validation logic, like "enum": ["yes", "true"] or "type": "string" with a "pattern" constraint. If the parameter fails validation, the file or folder will not be included in the generated output. This allows for powerful and flexible control over template generation based on user input. |
| `nonRenderableFiles` | [String] | A list of file paths or [globs](https://en.wikipedia.org/wiki/Glob_(programming)) that must be copied "as-is" to the target directory, i.e., without performing any rendering process. This is useful when you want to copy binary files. |
| `generator` | [String] | A string representing the generator version-range the template is compatible with. This value must follow the [semver](https://nodejs.dev/learn/semantic-versioning-using-npm) syntax. E.g., `>=1.0.0`, `>=1.0.0 <=2.0.0`, `~1.0.0`, `^1.0.0`, `1.0.0`, etc. [Read more about semver](https://docs.npmjs.com/about-semantic-versioning). |
| `hooks` | Object[String, String] or Object[String, Array[String]] | A list of modules containing hooks, except for the ones you keep locally in your template in the default location. For each module you must specify the exact name of the hook that should be used in the template. For a single hook, you can specify it as a string; for more hooks, you must pass an array of strings. In the case of external modules, remember they need to be added as a dependency in `package.json` of your template. There is also [an official hooks library](hooks#official-library) always included in the generator. As this is a library of multiple hooks, you still need to explicitly specify in the configuration which one you want to use. Use `@asyncapi/generator-hooks` as the library name. |

## Special parameters

There are some template parameters that have a special meaning:

| Name | Description |
|------|-------------|
| `server` | It is used to let the template know which server from the AsyncAPI specification file you want to use. In some cases, this may be required. For instance, when generating code that connects to a specific server. Use this parameter in case your template relies on users' information about what server from the specification file they want to use during generation. You also need this parameter if you want to use `server.protocol` notation within `conditionalGeneration` configuration option. Once you decide to specify this parameter for your template, it is recommended you make it a mandatory parameter otherwise a feature like `conditionalGeneration` is not going to work if your users do not use this parameter obligatory.

---

# Template context
Source: https://www.asyncapi.com/docs/tools/generator/template-context.md

# Template context

While using the generator tool, you may want dynamic values populated to your templates and rendered in the output. The generator can achieve that using the **template context**.
The **template context** allows you to access the contents of the [AsyncAPI document](asyncapi-document) and inject dynamic values to the template files passed to the asyncAPI CLI during the generation process. The render engine then displays these dynamically assigned values in the output.

## Generation process
1. The **Generator** receives **Template** and **params** as input.
2. The **Generator** sends to the **Parser** the **asyncapiString** which is a stringified version of the original **AsyncAPI document**. 
3. The **Parser** validates the format of the **asyncapiString** using OpenAPI, RAML, or Avro schemas.
4. If the **asyncapiString** is valid, the **parser** manipulates it, returns a set of helper functions and properties, and bundles them into an **asyncapi** variable. The **asyncapi** variable is an instance of the **AsyncAPI document**. The helper functions and properties make it easier to access the contents of the **AsyncAPI document** in the template.
5. The **Generator** then passes the **params**, which are template-specific options used to customize the output, the **Template files**, and the **asyncapi** which collectively make up the **Template Context**.
6. The **Template Context** is then passed to the **Render Engine**. The **Render Engine** then injects all the dynamic values from the **Template Context** into the **Template files**.
   
``` mermaid
graph LR
    A[Template Context]
    B{Generator}
    C[Parser]
    D[Render Engine]
    E[Template] --> B
    F[Params] --> B
    G[AsyncAPI Document] --> B
  subgraph Generator
    B -->| params | A
    B--> | asyncapiString| C
    B -->| originalAsyncAPI | A
    C --> | asyncapi -> AsyncAPIDocument type | A
    B--> | Template Files | D
    A --> D
  end
```

## Template context
The extra context passed to the render engine during the generation process and made accessible in the templates includes:

- **`originalAsyncAPI`** is a stringified version of the original AsyncAPI document that the user passed to the Generator.
- **`asyncapi`** is a parsed AsyncAPI document with helper functions and properties. You should use it to access document contents e.g `asyncapi.title`.
- **`params`** is an object with all the parameters passed to the Generator by the user.

---

# React render engine
Source: https://www.asyncapi.com/docs/tools/generator/react-render-engine.md

# React render engine

[React](https://reactjs.org) is the only  render engine supported by the AsyncAPI generator.

* It enables the possibility of debugging your template.
* It provides better error stack traces.
* Provides better support for separating code into more manageable chunks/components.
* The readability of the template is much better.
* Better tool support for development.
* Introduces testability of components.

When writing React templates you decide whether to use CommonJS, ES5, or ES6 modules since everything is bundled together before the rendering process takes over. We use our own React renderer which can be found in the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk). 
There you can find information about how the renderer works or how we transpile your template files.

Your React template always requires `@asyncapi/generator-react-sdk` as a dependency. `@asyncapi/generator-react-sdk` is required to access the `File` component which is required as a root component for a file to be rendered. Furthermore, it provides some common components to make your development easier, like `Text` or `Indent`.

Let's consider a basic React template as the one below called `MyTemplate.js`:

```js
import { File, Text } from "@asyncapi/generator-react-sdk";

export default function({ asyncapi, params, originalAsyncAPI }) {
  return (
    
      Some text that should render as is
    
  );
}
```

The exported default function returns a `File` component as a root component which the generator uses to determine what file should be generated. In our case, we overwrite the default functionality of saving the file as `MyTemplate.js` but instead use the filename `asyncapi.md`. It is then specified that we should render `Some text that should render as is\n` within that file. Notice the `\n` character at the end, which is automatically added after the `Text` component. 

For further information about components, props, etc, see the [Generator React SDK](https://github.com/asyncapi/generator-react-sdk)

### Common assumptions

1. Generator renders all files located in the `template` directory if they meet the following conditions:
    - `File` is the root component
    - The file is not in the list of `nonRenderableFiles` in the template configuration
1. New lines are automatically added after each `Text` component.
1. The props you have access to in the rendering function are:
   - `asyncapi` which is a parsed spec file object. Read the [API](https://github.com/asyncapi/parser-api/blob/master/docs/api.md#asyncapidocument) of the Parser to understand what structure you have access to in this parameter.
   - `originalAsyncAPI` which is an original spec file before it is parsed. 
   - `params` that contain the parameters provided when generating.
1. All the file templates are supported where the variables are provided after the default props as listed above.

---

# Hooks
Source: https://www.asyncapi.com/docs/tools/generator/hooks.md

# Hooks

Hooks are functions called by the generator on a specific moment in the generation process. Hooks can be anonymous functions but you can also add function names. These hooks can have arguments provided to them or being expected to return a value.

## Types

The following types of hooks are currently supported:

|Hook type|Description| Return type | Arguments 
|---|---|---|---|
| `generate:before` | Called after registration of all filters and before the generator starts processing of the template. | void : Nothing is expected to be returned. | [The generator instance](api)
| `generate:after` | Called at the very end of the generation. | void : Nothing is expected to be returned. | [The generator instance](api)
| `setFileTemplateName` | Called right before saving a new file generated by [file template](file-templates). | string : a new filename for the generator to use for the file template. | [The generator instance](api) and object in the form of `{ "originalFilename" : string }`

## Location

The generator parses:
- All the files in the `.hooks` directory inside the template.
- All modules listed in the template configuration and triggers only hooks whose names were added to the config. You can use an [official hooks library](#official-library) that is bundled together with the generator. To learn how to add hooks to configuration [read more about the configuration file](configuration-file).

## Examples

> Some of the examples have names of hook functions provided and some not. Keep in mind that hook functions kept in template in default location do not require a name. Name is required only if you keep hooks in non default location or in a separate library, because such hooks need to be explicitly configured in the configuration file. For more details on hooks configuration [read more about the configuration file](configuration-file).

Most basic modules with hooks look like this:
```js
module.exports = {
  'generate:after': generator => console.log('This runs after generation is complete')
}
```

Below you have an example Hook that after generation creates an AsyncAPI file.

```js
const fs = require('fs');
const path = require('path');

module.exports = {
  'generate:after': generator => {
    const asyncapi = generator.originalAsyncAPI;
    let extension;

    try {
      JSON.parse(asyncapi);
      extension = 'json';
    } catch (e) {
      extension = 'yaml';
    }

    fs.writeFileSync(path.resolve(generator.targetDir, `asyncapi.${extension}`), asyncapi);
  }
};
```
And here an example Hook that before generation switches `publish` and `subscribe` operations for each channel.

```js
module.exports = {
  'generate:before': function switchOperations(generator) {
    const asyncapi = generator.asyncapi;
    for (let [key, value] of Object.entries(asyncapi.channels())) {
      let publish = value._json.publish;
      value._json.publish = value._json.subscribe;
      value._json.subscribe = publish;
      if (!value._json.subscribe) {
        delete value._json.subscribe;
      }
      if (!value._json.publish) {
        delete value._json.publish;
      }
    }
  };
};
```

Example hook for changing the filename of a template file. Replaces all '-' characters with '_'.
```js
module.exports = {
	'setFileTemplateName': (generator, hookArguments) => {
		const currentFilename = hookArguments.originalFilename ;
		return currentFilename.replace('-', '_')
	};
};
```

## Official library

It is a library of reusable hooks that you can use in your templates. You only have to add its name to the configuration: `@asyncapi/generator-hooks` and specify which hook you want to enable.

This library consists of the following hooks:
|Hook name|Hook type|Description|
|---|---|---|
| `createAsyncapiFile` | `generate:after` | It creates an AsyncAPI file with the content of the spec file passed to the generator. If the spec was loaded from a file on disk, external `$ref`s (e.g. `$ref: './commons/servers.yml#/...'`) are bundled via [`@asyncapi/bundler`](https://github.com/asyncapi/bundler) into a single self-contained file; otherwise, or if bundling fails, the original spec is written unchanged. By default, it creates the file in the root of the generation output directory. This hook also supports custom parameters that the user can pass to template generation. The parameter called `asyncapiFileDir` allows the user to specify the location where the spec file should be created. To make your template users use this parameter, you need to add it to the configuration of your template like other parameters |

> **Limitation:** refs are only resolved relative to the source file's own directory, so a `$ref` reachable only through another path (e.g. a symlink) won't bundle and falls back to the unresolved source.

1. In your template configuration in `package.json` specify you want to use this library and what hook exactly:
    ```json
    {
      "generator": {
          "hooks": {
              "@asyncapi/generator-hooks": "createAsyncapiFile"
          }
      }
    }
    ```
1. Some hooks support custom parameters that template's user can use to specify different behaviour of the hook. To enable these, you need to also add them to the list of your template's parameters:
    ```json
    {
      "generator": {
          "parameters": {
            "asyncapiFileDir": {
                "description": "This template by default also outputs the AsyncAPI document that was passed as input. You can specify with this parameter what should be the location of this AsyncAPI document, relative to specified template output."
            }
        }
      }
    }
    ```

---

# File templates
Source: https://www.asyncapi.com/docs/tools/generator/file-templates.md

# File templates

## Generating files with the React render engine

The React render engine allows for a more generic way to render multiple files by returning an array of `File` components in the rendering component. This can be particularly useful for complex templates or when you need to generate a large number of files with varying content.

### Example 1: Rendering hardcoded files

The following is a simple hardcoded example of how to render multiple files using the React render engine:

```tsx
import { File} from "@asyncapi/generator-react-sdk";

export default function({ asyncapi }) {
  return [
    Content,
    Content
  ]
}
```

### Example 2: Rendering files based on the AsyncAPI Schema

In practice, to render the multiple files, that are generated from the data defined in your AsyncAPI, you'll iterate over the array of schemas and generate a file for each schema as shown in the example below:

```js
import { File} from "@asyncapi/generator-react-sdk";

/*
 * To render multiple files, it is enough to return an array of `File` components in the rendering component, like in following example.
 */
export default function({ asyncapi }) {
  const schemas = asyncapi.allSchemas();
  const files = [];
  // schemas is an instance of the Map
  schemas.forEach((schema) => {
    
    files.push(
      // We return a react file component and each time we do it, the name of the generated file will be a schema name
      // Content of the file will be a variable representing schema
      
        const { schema.id() } = { JSON.stringify(schema._json, null, 2) }
      
    );
  });
  return files;
}
```

### Example 3: Rendering files for each channel

Additionally, you can generate multiple files for each channel defined in your AsyncAPI specification using the React render engine as shown in the example below:

```js
import { File, Text } from "@asyncapi/generator-react-sdk";

export default function ({ asyncapi }) {
  const files = [];

  // Generate files for channels
  asyncapi.channels().forEach((channel) => {
    const channelName = channel.id();

    files.push(
      
        # Channel: {channelName}
        
          {channel.hasDescription() && `${channel.description()}`}
        
      
    );
  });
  return files;
}
```
The code snippet above uses the `Text` component to write file content to the `.md` markdown file. The `newline` property is used to ensure that the content isn't all rendered in one line in the markdown file. In summary, the code snippet above is a practical guide on generating properly formatted multiline Markdown files for each channel in an AsyncAPI document.

> You can see an example of a file template that uses the React render engine [here](https://github.com/asyncapi/template-for-generator-templates/blob/master/template/schemas/schema.js).

---

# TypeScript support
Source: https://www.asyncapi.com/docs/tools/generator/typescript-support.md

# TypeScript support

The AsyncAPI generator has TypeScript support for [hooks](hooks). Assumptions:

- Installing the `typescript` package and creating the `tsconfig.json` file isn't necessary.
- Source code of the hook/filter must have `.ts` extension.
- Each package related to the typings for TypeScript like `@types/node` must be installed in the template under `dependencies` array. This is because the Generator transpiles the TypeScript code on-the-fly while rendering the template, and cannot use packages under `devDependencies`.
- Each template should have `@types/node` package installed to enable support for typings for Node.

---

# Special file names
Source: https://www.asyncapi.com/docs/tools/generator/special-file-names.md

# Special file names

We use NPM behind the scenes to download and install the templates. Since NPM will not fetch files like `.gitignore`, you should name them differently. Luckily, the Generator will take care of renaming them back for you. The following is a table of the special file names:

|Special file name|Output file name|
|---|---|
|`{.gitignore}`|`.gitignore`|
|`{.npmignore}`|`.npmignore`|

---

# Creating a template - Python
Source: https://www.asyncapi.com/docs/tools/generator/generator-template.md

# Creating a template - Python

This tutorial teaches you how to create a simple generator template using a Python MQTT client. You'll use the AsyncAPI document and the template you develop to generate Python code. Additionally, you'll create template code with a reusable component to reuse the custom functionality you create and test your code using an MQTT client.

Suppose you can only sleep when the AC in your bedroom is set to 22 °C, and you can't sleep when the temperature drops or rises above that. You can install a smart monitor in your bedroom that keeps track of the temperature and notifies you to adjust it to your optimum temperature when it fluctuates. You will create a template to alert you when the bedroom's temperature fluctuates from 22 °C.

In this tutorial:

- You'll use the [Eclipse Mosquitto](https://test.mosquitto.org) **MQTT broker**, which you'll connect to subscribe and publish messages using an MQTT client.
- You'll use [Python Paho-MQTT](https://pypi.org/project/paho-mqtt/) as the **MQTT client** in this project.
- You'll create a React template that will use the MQTT broker to allow you to monitor your bedroom's temperature and notify you when the temperature drops or rises above 22 °C.
- Lastly, create a reusable component for the output code's `sendTemperatureDrop` and `sendTemperatureRise` functions.

## Prerequisites

Before you begin, make sure you have the following set up:

- **Basic Programming Knowledge** – Familiarity with JavaScript and Python.
- **NPM & PIP** – Required for installing dependencies. Install NPM from the [official guide](https://nodejs.org/en/download) and PIP from the [official guide](https://pip.pypa.io/en/stable/installation).
- **AsyncAPI CLI** – Used for code generation, install using [CLI installation guide](https://www.asyncapi.com/docs/tools/cli/installation).
- **Docker** - Required for running MQTT CLI. Install it from the official [Docker](https://docs.docker.com/) website.
- **Code Editor (VS Code recommended)** – A good code editor is essential for development and debugging.
- **Knowledge of Template Development** – Review the [Template Development Guide](template-development) to understand the structure and minimum requirements for templates.

> **Note:** In this tutorial, we are using `test.mosquitto.org` as the public broker. However, sometimes it may not be reachable. If you experience any difficulty connecting to it, you can run a broker on your localhost instead.  
>  
> If you choose to run the broker on localhost, then in the further steps, replace all occurrences of `test.mosquitto.org` with `localhost` and run the following Docker command:  
>  
> ```sh
> docker run -d --name mosquitto -p 1883:1883 eclipse-mosquitto
> ```
>  
> This starts an Eclipse Mosquitto broker locally on your machine, listening on port 1883.  
>  
> If you don’t want to use Docker, you can install Mosquitto manually. Follow the [official installation guide](https://mosquitto.org/download/) for your operating system.

## Background context

There is a list of [community maintained templates](https://www.asyncapi.com/docs/tools/generator/template#generator-templates-list), but what if you do not find what you need? In that case, you'll create a user-defined template that generates custom output from the generator.
Before you create the template, you'll need to have an [AsyncAPI document](https://www.asyncapi.com/docs/tools/generator/asyncapi-document) that defines the properties you want to use in your template to test against. In this tutorial, you'll use the following template saved in the **test/fixtures/asyncapi.yml** file in your template project directory.

``` yml

asyncapi: 3.0.1

info:
  title: Temperature Service
  version: 1.0.0
  description: This service is in charge of processing all the events related to temperature.

servers:
  dev:
    host: test.mosquitto.org #in case you're using local mosquitto instance, change this value to localhost.
    protocol: mqtt

channels:
  temperatureChanged:
    address: temperature/changed
    messages:
      temperatureChange:
        description: Message that is being sent when the temperature in the bedroom changes.
        payload:
          $ref: '#/components/schemas/temperatureId'
    description: Updates the bedroom temperature in the database when the temperatures drops or goes up.

operations:
  temperatureChange:
    action: receive
    summary: Message sent to the broker when the temperature is changed.
    channel:
      $ref: '#/channels/temperatureChanged'

components:
  schemas:
    temperatureId:
      type: object
      additionalProperties: false
      properties:
        temperatureId:
          type: string
```

## Overview of steps

1. Create a new directory for your template named **python-mqtt-client-template**.
2. Install the AsyncAPI CLI using the command `npm install -g @asyncapi/cli`.
3. Create a new folder **test/fixtures** with a file named **asyncapi.yml** in your fixtures directory. This file is used to define the **structure** of your template. You can copy the above example and paste it in your **asyncapi.yml** document.
4. Create a new file named **package.json** in your **python-mqtt-client-template** directory. This file is used to define the **dependencies** for your template. Make sure to include `@asyncapi/generator` alongside your other dependencies here.
5. Create a new folder **python-mqtt-client-template/template**. Create a new file named **index.js** in your **template** directory. This file is used to define the **logic** for your template.
6. Navigate into your template directory and run a single installation command to install all defined dependencies locally (this is required for the CLI to execute template commands):
   ```bash
   cd python-mqtt-client-template
   npm install
Now your directory should look like this:

```text
python-mqtt-client-template
├── template
│   └── index.js
├── test
│   └── fixtures
│       └── asyncapi.yml
└── package.json
```

Lets break it down:

### package.json file

The **package.json** file is used to define the dependencies for your template. Add the following code snippet to your **package.json** file:

``` json
{
  "name": "python-mqtt-client-template",
  "version": "0.0.1",
  "description": "A template that generates a Python MQTT client using MQTT.",
  "generator": {
    "apiVersion": "v3",
    "generator": ">=2.0.0 <4.0.0",
    "supportedProtocols": ["mqtt"]
  },
  "dependencies": {
    "@asyncapi/generator-react-sdk": "^0.2.25"
  },
  "devDependencies": {
    "rimraf": "^5.0.0"
  }
}
```

Here's what is contained in the code snippet above:

- **name** -the name of your template.
- **version** - the current version of your template.
- **description** - a description of what your template does.
- **generator** - specify generator [specific configuration](https://www.asyncapi.com/docs/tools/generator/configuration-file).
  - **apiVersion** - specifies which major version of the [Parser-API](https://github.com/asyncapi/parser-api) your template will use.
  - **generator** - a string representing the generator version-range your template is compatible with.
  - **supportedProtocols** - A list that specifies which protocols are supported by your template.
- **dependencies** - specifies which version of [`@asyncapi/generator-react-sdk`](https://github.com/asyncapi/generator-react-sdk) should be used.

Navigate to the **python-mqtt-client-template** directory. Run the command `npm install` on your terminal to install the dependencies specified in **package.json**.

### index.js file

The **index.js** file is used to define the logic for your template. Inside the template folder, create an **index.js** file and add the code snippet below:

```js
//1
import { File } from '@asyncapi/generator-react-sdk'
//2
export default function ({ asyncapi }) {
//3
  return {asyncapi.info().title()}
}
```

The code snippet above does the following:

1. Import the `generator-react-sdk` dependency.
2. The `asyncapi` argument is an instance of the [AsyncAPI Parser](https://www.asyncapi.com/docs/tools/generator/parser). It will allow you to access the content of the AsyncAPI document in your template using helper functions.
3. The `asyncapi.info().title()` is using the info() helper function to return the info object from the AsyncAPI document illustrated in the code snippet below:

``` json
info:
  title: Temperature Service
  version: 1.0.0
  description: This service is in charge of processing all the events related to temperature.
```

The `asyncapi.info().title()` returns `Temperature Service`.

### Test using AsyncAPI CLI

To see this in action, navigate to the **python-mqtt-client-template** directory. Then, run `asyncapi generate fromTemplate test/fixtures/asyncapi.yml ./ -o test/project` command on your terminal. If successful, you'll see the message below on your terminal:

``` cmd
Generation in progress. Keep calm and wait a bit... done
Check out your shiny new generated files at test/project.
```

Navigating to the **test/project** directory. You should see a **client.py** file; the only content is `Temperature Service`.

Let's break down the previous command:

- `asyncapi generate fromTemplate` is how you use AsyncAPI generator via the AsyncAPI CLI.
- `test/fixtures/asyncapi.yml` points to your AsyncAPI document.
- `./` specifies the location of your template.
- `-o` specifies where to output the result.

## Creating a template

You will create an MQTT-supported template that will generate a Python client from the template and the AsyncAPI document above.

In this section, you'll:

1. Write the MQTT client code.
2. Write code to test the client works.
3. Update the template to use the client code.
4. Setup a script to help you run this code.
5. Template your code.

### 1. Create the client

Here is the sample code to be pasted in the client.py you generated above running the `asyncapi generate fromTemplate test/fixtures/asyncapi.yml ./ -o test/project` command. It uses the `paho-mqtt` package.

``` python
# 1
import paho.mqtt.client as mqtt
# 2
mqttBroker = "test.mosquitto.org"

class TemperatureServiceClient:
    def __init__(self):
      # 3 
        self.client = mqtt.Client()
      # 4
        self.client.connect(mqttBroker)

    def sendTemperatureChange(self, id):
      # 5
        topic = "temperature/changed"
      # 6 
        self.client.publish(topic, id)
```

Make sure you have the Paho-MQTT library installed. You can install it using pip with the `pip install paho-mqtt==1.6.1` command. Please note that this tutorial is based on Paho-MQTT version 1.6.1. The Paho-MQTT library has since been updated to version 2.0.0, which includes changes that are not covered in this tutorial. To ensure compatibility and to follow along without any issues, please install version 1.6.1 of the Paho-MQTT library.

Let's break down the previous code snippet:

1. Imports the MQTT module from the Paho package, which provides the MQTT client functionality.
2. Assigns the MQTT broker address `test.mosquitto.org` to the variable MQTT broker. This specifies the location where the MQTT client will connect to.
3. Defines an instance of the MQTT client object. This object will be used to establish a connection with the MQTT broker and perform MQTT operations.
4. Defines that on client instance creation, it connects to the broker.
5. The `sendTemperatureChange` is a function the client user invokes to publish a message to the broker, and its specific topic.

In summary, this code sets up an MQTT client using the Paho-MQTT library. It connects to the `test.mosquitto.org` MQTT broker, and the `sendTemperatureChange()` method publishes temperature change information to the `temperature/changed` topic whenever called.

### 2. Test the client

You'll interact with the Temperature Service using the client module you created above. You'll create an instance of the client using `client = TemperatureServiceClient()` and then use `client.sendTemperatureChange` function to publish messages that Temperature Service is subscribed to.
Create a **test/project/test.py** file in your project and add the code snippet below:

Now your directory should look like this:

```
python-mqtt-client-template
├── template
│   └── index.js
└── test
    ├── fixtures
    │   └── asyncapi.yml
    └── project
        ├── client.py
        └── test.py
```

``` python
from client import TemperatureServiceClient
from random import randrange
import time

client = TemperatureServiceClient()

id_length = 8
min_value = 10**(id_length-1)  # Minimum value with 8 digits (e.g., 10000000)
max_value = 10**id_length - 1  # Maximum value with 8 digits (e.g., 99999999)

while True:
    randomId = randrange(min_value, max_value + 1)
    client.sendTemperatureChange(randomId)
    print("New temperature detected " + str(randomId) + " sent to temperature/changed")
    time.sleep(1)

```

Navigate to the **python-mqtt-client-template/test/project** directory. Run the command `python test.py` on your terminal. You should see output similar to the snippet below logged on your terminal:

``` cmd
New temperature detected 64250266 sent to temperature/changed
New temperature detected 36947728 sent to temperature/changed
New temperature detected 72955029 sent to temperature/changed
```

To make sure your **test.py** and client code works check if the broker really receives temperature-related messages. You can do it using an [MQTT CLI](https://hivemq.github.io/mqtt-cli/) using docker. Run the command `docker run hivemq/mqtt-cli sub -t temperature/changed -h test.mosquitto.org` in your terminal. It will download the image if you don't have it locally, then the CLI will connect to the broker, subscribe to the `temperature/changed` topic and then output the temperature ids on the terminal.

> For testing against a local Docker broker, route to the host machine:

```bash
docker run hivemq/mqtt-cli sub -t temperature/changed -h host.docker.internal
```

### 3. Update the template with client code

Open [**index.js**](#indexjs-file) and copy the content of [**client.py**](#1-create-the-client) and replace `{asyncapi.info().title()}` with it. It should look like the code snippet below now:

``` js
import { File } from '@asyncapi/generator-react-sdk';

export default function ({ asyncapi }) {
  return (
    
      {`import paho.mqtt.client as mqtt

mqttBroker = "test.mosquitto.org"

class TemperatureServiceClient:
    def __init__(self):
        self.client = mqtt.Client()
        self.client.connect(mqttBroker)

    def sendTemperatureChange(self, id):
        topic = "temperature/changed"
        self.client.publish(topic, id)`}
    
  )
}
```

### 4. Write script to run the test code

In **package.json** you can have the scripts property that you invoke by calling `npm run <your_script>`. After adding these scripts in **package.json**, it will look like the following code snippet:

``` json
    {
      "name": "python-mqtt-client-template",
      "version": "0.0.1",
      "description": "A template that generates a Python MQTT client using MQTT.",
      "scripts": {
        "test:clean": "rimraf test/project/client.py",
        "test:generate": "asyncapi generate fromTemplate test/fixtures/asyncapi.yml ./ --output test/project --force-write",
        "test:start": "python test/project/test.py",
        "test": "npm run test:clean && npm run test:generate && npm run test:start"
      },
      "generator": {
        "apiVersion": "v3",
        "generator": ">=2.0.0 <4.0.0",
        "supportedProtocols": ["mqtt"]
      },
      "dependencies": {
        "@asyncapi/generator-react-sdk": "^0.2.25"
      },
      "devDependencies": {
        "rimraf": "^5.0.0"
      }
    }
```

The 4 scripts added in **package.json** do the following:

1. `test:clean`: This script uses the `rimraf` package to remove the old version of the file **test/project/client.py** every time you run your test.
2. `test:generate`: This script uses the AsyncAPI CLI to generate a new version of **client.py**.
3. `test:start`: This script runs the python code using **client.py**.
4. `test`: This script runs all the other scripts in proper order.

Run `npm test` on your terminal to ensure everything works as expected.

### 5. Template your code

#### 5a. Add parameters to the configuration file

You often have different runtime environments in programming, e.g., development and production. You will use different servers to spin both of these instances. You'll have two broker versions, one for production and the other for development. You have defined a dev server in the AsyncAPI document:

```yml
servers:
  dev:
    host: test.mosquitto.org
    protocol: mqtt
```

This will allow you to also define the broker you will use in production in the servers section above.
Therefore, we can template the code `mqttBroker = 'test.mosquitto.org'` in **index.js** so the value is populated dynamically at runtime depending on the specified server environment.

The generator has a **parameters** object used to define parameters you use to dynamically modify your template code at runtime. It also supports the **server** parameter that defines the server configuration value. Navigate to **package.json** and add the snippet below:

```json
    "generator": {
        # ...(redacted for brevity)
        "parameters": {
            "server": {
              "description": "The server you want to use in the code.",
              "required": true
            }
        }
    }
```

`"required": true`: makes the parameter mandatory and once user forgets to add it to the cli command, a proper error message is yielded.
You'll pass the server to be used to generate your code using `--param server=dev` in the AsyncAPI CLI command. Failure to which you'll get an error:

```cmd
Generator Error: This template requires the following missing params: server.
```

Update your `test:generate` script in **package.json** to include the server param

```json
"test:generate": "asyncapi generate fromTemplate test/fixtures/asyncapi.yml ./ --output test/project --force-write --param server=dev"
```

You can now replace the static broker from `mqttBroker = 'test.mosquitto.org'` to `mqttBroker = "${asyncapi.servers().get(params.server).host()}"` in **index.js**.

Now the template code looks like this:

``` js
import { File } from '@asyncapi/generator-react-sdk';

// notice that now the template not only gets the instance of parsed AsyncAPI document but also the parameters
export default function ({ asyncapi, params }) {
 
  return (
    
      {`import paho.mqtt.client as mqtt

mqttBroker = "${asyncapi.servers().get(params.server).host()}"

class TemperatureServiceClient:
    def __init__(self):
        self.client = mqtt.Client()
        self.client.connect(mqttBroker)

    def sendTemperatureChange(self, id):
        topic = "temperature/changed"
        self.client.publish(topic, id)`}
    
  )
}
```

Run `npm test` to validate that your code still works as expected.

#### 5b. Templating index.js with React

Python takes indentation very seriously, and our generated output will be Python code. We, therefore, need to make sure the indentation in **index.js** looks right so the generated code is indented correctly. After templating the code in **index.js**, it will look like the following code snippet:

```js
// 1
import { File, Text } from '@asyncapi/generator-react-sdk'
export default function ({ asyncapi, params }) {
  return (
    
    // 2
      import paho.mqtt.client as mqtt
    // 3
      mqttBroker = "{asyncapi.servers().get(params.server).host()}"
    // 4
      class {asyncapi.info().title().replaceAll(' ', '')}Client:
    // 5
      
        {`def __init__(self):
            self.client = mqtt.Client()
            self.client.connect(mqttBroker)`}
      
      
  )
}
```

1. Import the **Text** component that will wrap strings so they are indented properly in the output. Your import statement should now look like this: `import { File, Text } from '@asyncapi/generator-react-sdk'`.
2. When the Paho module import is rendered in **client.py** file, it will add two extra new lines.
3. The broker url is templated in a `Text` component removing the `$` from the string template.
4. Dynamically get the class name **TemperatureServiceClient** from the AsyncAPI document from the **info** object using the Parser API using the code: `asyncapi.info().title()` . It will return `Temperature Service`, then remove the spaces and add `Client` as a suffix.
5. There is no templating needed in the `__init__` function, there is only hardcoded information.

> If you're on the fence about which templating engine you should use in your template, check out the [React render engine](https://www.asyncapi.com/docs/tools/generator/react-render-engine) documentation.
In the next section, you'll refactor your template to use React.

#### 5c. Creating a reusable component

Suppose you have two [channels](https://www.asyncapi.com/docs/concepts/channel), one to watch if the temperature drop below 22 °C and one to check if the temperature is above 22 °C, the generated output code would look like this:

```python
import paho.mqtt.client as mqtt

mqttBroker = "test.mosquitto.org"

class TemperatureServiceClient:

  def __init__(self):
              self.client = mqtt.Client()
              self.client.connect(mqttBroker)

  def sendTemperatureDrop(self, id):
          topic = "temperature/dropped"
          self.client.publish(topic, id)
  def sendTemperatureRise(self, id):
          topic = "temperature/risen"
          self.client.publish(topic, id)

```

You'll then need a template to dynamically generate `sendTemperatureDrop` and `sendTemperatureRise` functions in the generated code based off the AsyncAPI document content. The goal is to write template code that returns functions for operations marked with `action: receive`, using their associated channels. The template code to generate these functions will look like this:

```js

  

```

It's recommended to put reusable components outside the template directory in a new directory called components. You'll create a component that will dynamically generate functions in the output for as many operations as there are in your AsyncAPI document that are marked with `action: receive`. Add the following code in the **python-mqtt-client-template/components/TopicFunction.js** file, after creating the **python-mqtt-client-template/components/** directory:

```js
/*
 * This component returns a block of functions that user can use to send messages to specific topic.
 * As input it requires a list of Operation models from the parsed AsyncAPI document marked with `action: receive`.
 */
export function TopicFunction({ operations }) {
  const topicsDetails = getTopics(operations);
  let functions = '';

  topicsDetails.forEach((t) => {
    functions += `def send${t.name}(self, id):
        topic = "${t.topic}"
        self.client.publish(topic, id)\n`
  });

  return functions;
}

/*
 * This function returns a list of objects, one for each channel with two properties, name and topic
 * name - holds information about the operationId provided in the AsyncAPI document
 * topic - holds information about the address of the topic
 *
 * As input it requires a list of Channel models from the parsed AsyncAPI document
 */
function getTopics(operations) {
  let topicsDetails = [];

  operations.forEach((op) => {
    const channels = op.channels().all();
    if (!channels.length) return;

    const channel = channels[0];
    const operationId = op.operationId() || op.id();
    
    topicsDetails.push({
      name: operationId.charAt(0).toUpperCase() + operationId.slice(1),
      topic: channel.address()
    });
  });
  
  return topicsDetails;
}
```

`{ operations }`: the `TopicFunction` component accepts a custom prop called operations and in your template code 
`getTopics(operations)`: Returns a list of objects, one for each operation with two properties; name and topic. The **name** holds information about the `operationId` provided in the AsyncAPI document (or a generated ID if operationId is not set) while the **topic** holds information about the address of the topic from the operation's associated channel.

Import the `TopicFunction` component in your template code in **index.js** and add the template code to generate the functions to topics that the `Temperature Service` application is subscribed to. In your case, the final version of your template code should look like this:

```js
import { File, Text } from '@asyncapi/generator-react-sdk'
import { TopicFunction } from '../components/TopicFunction'

export default function ({ asyncapi, params }) {
  return (
    
      import paho.mqtt.client as mqtt

      mqttBroker = "{asyncapi.servers().get(params.server).host()}"

      class {asyncapi.info().title().replaceAll(' ', '')}Client:

      
        {`def __init__(self):
            self.client = mqtt.Client()
            self.client.connect(mqttBroker)`}
      

      
        
      
    
  )
}

```

Now your directory should look like this:

```
python-mqtt-client-template
├── components
│   └── TopicFunction.js
├── template
│   └── index.js
└── test
    ├── fixtures
    │   └── asyncapi.yml
    └── project
        ├── client.py
        └── test.py
```

Run `npm test` on your terminal to ensure everything works as expected.

In the next section, you'll add another channel to **asyncapi.yml** file called `temperatureDropped` and `temperatureRisen` then run the template again to make sure it still works as expected.

#### 5d. Update AsyncAPI document

Update the AsyncAPI document to use two channels:

```yml
channels:
  temperatureDropped:
    address: temperature/dropped
    messages:
      temperatureDrop:
        description: Message that is being sent when the temperature drops past a certain point.
        payload:
          $ref: '#/components/schemas/temperatureId'
    description: Notifies the user when the temperature drops past a certain point.
  temperatureRisen:
    address: temperature/risen
    messages:
      temperatureRise:
        description: Message that is being sent when the temperature rises past a certain point.
        payload:
          $ref: '#/components/schemas/temperatureId'
    description: Notifies the user when the temperature rises past a certain point.

operations:
  temperatureDrop:
    action: receive
    summary: Message sent to the broker when the temperature is dropped.
    channel:
      $ref: '#/channels/temperatureDropped'
  temperatureRise:
    action: receive
    summary: Message sent to the broker when the temperature is risen.
    channel:
      $ref: '#/channels/temperatureRisen'
```

And update your test script in test.py to test the two functions as below:

```py
    client.sendTemperatureDrop(randomId)
    print("Temperature drop detected " + str(randomId) + " sent to temperature/dropped")
    client.sendTemperatureRise(randomId)
    print("Temperature rise detected " + str(randomId) + " sent to temperature/risen")
```

Run `npm test` to validate that everything works as expected. You should see logs similar to the snippet below in your terminal:

```cmd
Temperature drop detected 49040460 sent to temperature/dropped
Temperature rise detected 49040460 sent to temperature/risen
Temperature drop detected 66943992 sent to temperature/dropped
Temperature rise detected 66943992 sent to temperature/risen
```

## Where to go from here?

Great job completing this tutorial! You have learnt how to use an AsyncAPI file to create a Python MQTT template and used it with the Paho-MQTT library in Python to connect to an MQTT broker and publish messages.😃

If you want to tinker with a completed template and see what it would look like in production, check out the [Paho-MQTT template](https://github.com/Harsh16gupta/asyncapi-v3-template-final).

You can also check out the [MQTT beginners guide](https://medium.com/python-point/mqtt-basics-with-python-examples-7c758e605d4) tutorial to learn more about asynchronous messaging using MQTT.

---

# Using private templates
Source: https://www.asyncapi.com/docs/tools/generator/using-private-template.md

# Using private templates

Generator allows fetching the template from private repositories like Verdaccio, Nexus, npm, etc.   
By default, the generator fetches the template from the public npm registry configured in the npm configuration.   
To fetch the template from a private registry, you need to provide the registry URL and authentication details in the .npmrc. For more information [read the docs](https://docs.npmjs.com/cli/v9/configuring-npm/npmrc).   
However, you can override the default behavior by providing the registry URL and authentication details as arguments of the commandline.

## Private registry using .npmrc:
```bash
npm config set registry http://verdaccio:4873
npm config set //verdaccio:4873/:_auth=$(echo -n 'username:password' | base64)
```
* **npm config set registry** : Provide the registry URL that points to the registry URL.
* **npm config set _auth** : Provide the base64 encoded value that represents the username and password for basic auth.
* **npm config set _authToken** : Provide the access token generated by the registry.

## Private registry overriding arguments:

* **registry.url**: The URL of the registry where the private template is located. Defaults to `registry.npmjs.org`.
* **registry.auth**: An optional parameter to pass the npm registry username and password encoded with base64, formatted as `username:password`. For example, if the username and password are `admin` and `nimda`, you need to encode them with the base64 value like `admin:nimda` which results in `YWRtaW46bmltZGE=`.
* **registry.token**: An optional parameter to pass to the npm registry authentication token. To get the token, you can first authenticate with the registry using `npm login` and then grab the generated token from the `.npmrc` file.

## Pulling private template using library:

```javascript
const generator = new Generator('@asyncapi/html-template', 'output',
      { 
        debug: true,
        registry: {
          url: 'http://verdaccio:4873',  
          auth: 'YWRtaW46bmltZGE=' 
            // base64 encoded username and password 
            // represented as admin:nimda
          
        }
      });
```
Assuming you host `@asyncapi/html-template` in a private package registry like Verdaccio. To pull this template, you need to provide `registry.url` option that points to the registry URL and `registry.auth` as a base64 encoded value that represents the username and password. Instead of username and password, you can also pass `registry.token`.

---

# Creating a template - Java
Source: https://www.asyncapi.com/docs/tools/generator/generator-template-java.md

# Creating a template - Java

This tutorial teaches you how to create a simple generator template using a Java MQTT client. You'll use the AsyncAPI document and the template you develop to generate Java code. Additionally, you'll create template code with a reusable component to reuse the custom functionality you create and test your code using an MQTT client.

This section guides you through creating a flexible MQTT-supported template that will generate a **Java** client from the template and the AsyncAPI document referenced above. The following steps are similar to the [Creating a template - Python](https://www.asyncapi.com/docs/tools/generator/generator-template) but with a few differences and Java flair. This will help developers practice with AsyncAPI generator tool using statically typed language **Java**.

## Prerequisites

To run it, ensure you have Java JDK 8 or higher, Gradle, and the AsyncAPI generator.
- **Gradle** - Get gradle at https://gradle.org/install/ 
- **JDK** - Get jdk at https://www.oracle.com/ca-en/java/technologies/downloads/

## Overview of Java Template

In this section, you'll:

1. Create a new directory to run Java code.
2. Create the Java client.
3. Test the Java Client
4. Output Java template code.
5. Create more channels

### 1. Create a new directory to run Java code

Create a new directory called **java-mqtt-client-template** at the root of your project. This is where all your Java templating work will go.

Once that is done, you should create some new sub-directories to begin building your Java client.
  1. Create a new subdirectory called `src`
  2. Change into `src` and create two new subdirectories: `fixtures` and `main/java`.
  3. Create a file named `asyncapi.yml` in your fixtures directory and paste the `asyncapi.yml` document mentioned [here](https://www.asyncapi.com/docs/tools/generator/generator-template#background-context) into it.
  4. Create a new file named **package.json** in your **java-mqtt-client-template** directory. This file is used to define the **dependencies** for your template.
  5. Create a new file called **build.gradle** in your **java-mqtt-client-template** directory. This file is used to build your generated java code for your template.
  6. Create a new file named **index.js** in a `template` folder from root directory. This file is used to define the **logic** for your template.

Now your directory should look like this:

```
java-mqtt-client-template 
├── src
|   └── fixtures
|       └── asyncapi.yml
│   └── main/java
├── template
|   └── index.js
└── package.json
└── build.gradle
```

Note: The `client.java` code must be in your `src/main/java` directory, or else Gradle won't build your application.

### Java - package.json file
Add the following code snippet to your package.json file:

```json
{
    "name": "java-mqtt-client-template",
    "version": "0.0.1",
    "description": "A template that generates a Java MQTT client using MQTT.",
    "generator": {
      "apiVersion": "v1",
      "generator": ">=1.10.0 <2.0.0",
      "supportedProtocols": ["mqtt"]
    },
    "dependencies": {
      "@asyncapi/generator-react-sdk": "^0.2.25"
    },
    "devDependencies": {
      "rimraf": "^5.0.0"
    }
}
```

Navigate to the `java-mqtt-client-template` directory and run the command `npm install` on your terminal to install the dependencies specified in `package.json`.

### Java - index.js file

The **index.js** file is used to define the logic for your template. Inside the template folder, create an **index.js** file and add the code snippet below:

```js
//1
import { File } from '@asyncapi/generator-react-sdk'
//2
export default function ({ asyncapi }) {
//3
  return {asyncapi.info().title()}
}
```

To see this in action, navigate to the `java-mqtt-client-template` directory. Then, run `asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java` command in your terminal. You should get  a sucess message as shown below and a `Client.java` file in `src/main/java`.

``` cmd
Generation in progress. Keep calm and wait a bit... done
Check out your shiny new generated files at test/project.
```

### 2. Create the Java client

  #### 2a. Setting up Gradle
The first step in creating the Java client to send messages using the MQTT protocol is to ensure that your `build.gradle` file includes the correct dependencies. Add the code snippet below into your `build.gradle` file.

```groovy
plugins {
    id 'java'
    id 'application'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
}

application{
    mainClass = project.hasProperty('mainClass') ? project.mainClass : 'Client'  // Default to 'Client' if no property is passed
}
```

Here's what is contained in the code snippet above:

- **plugins** - This section defines the plugins applied to the Gradle project.
  - **id 'java'** - This applies the Java plugin, which allows you to compile and run Java code.
  - **id 'application'** - This plugin is used to support building and running applications. It helps with creating an executable JAR.
- **repositories** - This section tells you app to fetch dependencies from Maven Central to retrieve the MQTT client library.
- **dependencies** - This specifies that the project depends on the Eclipse Paho MQTT client version 1.2.5, which is needed to compile and run.
- **application** - This section defines how the application should be executed. **mainClass** specifies the main class to be executed in a Java application. It can be specified via the command line else it defaults to the **Client.java** file.

Navigate to the `java-mqtt-client-template` directory. Run the command `gradle build` in your terminal to build your Java application. **Note**: Every time you update the `build.gradle` file, you must recompile it to get the new changes. 

  #### 2b. Beefing up Client.java

Here is the sample code to pasted into the `Client.java` file you generated above running the `asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java` command. 

```java
import org.eclipse.paho.client.mqttv3.*;

public class Client {
    private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
    private static final String TOPIC = "temperature/changed";

    private MqttClient client;

    public Client() {
        try {
            // Generate a unique client ID
            String clientId = MqttClient.generateClientId();
                    
            // Create and connect the MQTT client
            client = new MqttClient(BROKER_URL, clientId);
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
                    
            client.connect(options);
            System.out.println("Connected to MQTT broker: " + BROKER_URL);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
     public void sendTemperatureChange(String id) {
        try {
            // Publish the message with the temperature change
            MqttMessage message = new MqttMessage(id.getBytes());
            client.publish(TOPIC, message);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}
```

### 3. Test the Java Client
Create a **src/main/java/TestClient.java** file in your project and add the code snippet below.

Your directory should now look like this:

```
java-mqtt-client-template 
├── src
|   └── fixtures
|       └── asyncapi.yml
│   └── main/java
|       └── Client.java
|       └── TestClient.java
├── template
|   └── index.js
└── package.json
└── build.gradle
```

```java
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class TestClient {
    public static void main(String[] args) {
        Client client = new Client();
        Random random = new Random();

        int idLength = 8;
        int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
        int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
        System.out.println("Validating generated generated Client.java");
        System.out.println("Running tests in TestClient.java");
        System.out.println("Sending temperature changes to the broker...");
        System.err.println("\n");
        while (true) {
            int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
            client.sendTemperatureChange(String.valueOf(randomId));
            System.out.println("New temperature detected " + randomId + " sent to temperature/changed");

            try {
                TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
```
Run the command `gradle run -PmainClass=TestClient` to run your Java program with Gradle on your terminal. You should see output similar to the snippet below logged on your terminal:

``` cmd
New temperature detected 64250266 sent to temperature/changed
New temperature detected 36947728 sent to temperature/changed
New temperature detected 72955029 sent to temperature/changed
```
### 4. Output Java template code.
Open **index.js** and copy the content below so your file looks like the code snippet below:

```js
//1
import { File } from '@asyncapi/generator-react-sdk'
//2
export default function ({ asyncapi }) {
//3
  return 
  {`

import org.eclipse.paho.client.mqttv3.*;
public class Client {
    private static final String BROKER_URL = "tcp://test.mosquitto.org:1883";
    private static final String TOPIC = "temperature/changed";

    private MqttClient client;

    public Client() {
        try {
            // Generate a unique client ID
            String clientId = MqttClient.generateClientId();
                    
            // Create and connect the MQTT client
            client = new MqttClient(BROKER_URL, clientId);
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
                    
            client.connect(options);
            System.out.println("Connected to MQTT broker: " + BROKER_URL);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
     public void sendTemperatureChange(String id) {
        try {
            // Publish the message with the temperature change
            MqttMessage message = new MqttMessage(id.getBytes());
            client.publish(TOPIC, message);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}`
  }
}
```
#### 4a. Write the script to run the test code
In **package.json** define a script property that you invoke by calling `npm run <your_script>`. After adding these scripts in **package.json**, it will look like the following code snippet:

``` json
   {
    "name": "java-mqtt-client-template",
    "version": "0.0.1",
    "description": "A template that generates a Java MQTT client using MQTT.",
    "generator": {
      "apiVersion": "v1",
      "generator": ">=1.10.0 <2.0.0",
      "supportedProtocols": ["mqtt"],
      "parameters": {
            "server": {
              "description": "The server you want to use in the code.",
              "required": true
            }
        }
    },
    "scripts": {
        "test:clean": "rimraf src/main/java/Client.java",
        "test:generate": "asyncapi generate fromTemplate src/fixtures/asyncapi.yml ./ --output src/main/java --force-write --param server=dev",
        "test:start": "gradle run -PmainClass=TestClient",
        "test": "npm run test:clean && npm run test:generate && npm run test:start"
    },
    "dependencies": {
      "@asyncapi/generator-react-sdk": "^0.2.25"
    },
    "devDependencies": {
      "rimraf": "^5.0.0"
    }
  }
```
Run `npm test` to see if everything is working.
### 5. Create more channels

#### 5a. Creating more reusable components

Similar to the previous `TopicFunction` function we will create a function to make reusable components regardless of the number of channels in the asyncAPI document. 

Create a **components** directory at the root of your project and create a file named `TopicFunction.js` and add the code snippet below:

```js
/*
 * This component returns a block of functions that users can use to send messages to specific topics.
 * As input it requires a list of Channel models from the parsed AsyncAPI document.
 */
export function TopicFunction({ channels }) {
  const topicsDetails = getTopics(channels);
  let functions = '';

  topicsDetails.forEach((t) => {
    functions += `
    public void send${t.name}(String id) {
        String topic = "${t.topic}";
        try {
            MqttMessage message = new MqttMessage(id.getBytes());
            client.publish(topic, message);
            System.out.println("${t.name} change sent: " + id);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }\n`;
  });

  return functions;
}
  
  /*
   * This function returns a list of objects, one for each channel, each containing two properties: `name` and `topic`.
   * name - holds information about the `operationId` definedin the AsyncAPI document
   * topic - holds information about the topic's address.
   *
   * It requires as input, a list of Channel models from the parsed AsyncAPI document.
   */
  function getTopics(channels) {
    const channelsCanSendTo = channels
    let topicsDetails = []
  
    channelsCanSendTo.forEach((ch) => {
      const topic = {}
      const operationId = ch.operations().filterByReceive()[0].id()
      topic.name = operationId.charAt(0).toUpperCase() + operationId.slice(1)
      topic.topic = ch.address()
  
      topicsDetails.push(topic)
    })
  
    return topicsDetails
  }

```

Import the `TopicFunction` component in your template code in **index.js** and add the template code to generate the functions for the topics which the `Temperature Service` application is subscribed to. In your case, the final version of your template code should look like this:

```js
import { File, Text } from '@asyncapi/generator-react-sdk';
import { TopicFunction } from '../components/TopicFunction'

export default function ({ asyncapi, params }) {
    let channels = asyncapi.channels().filterByReceive();  // Get all the channels that receive messages

    // Generate Java code for each topic dynamically using TopicFunction
    const topicMethods = TopicFunction({ channels });  // This will return Java methods as text
    
    return (
    
    {
      
`import org.eclipse.paho.client.mqttv3.*;

public class Client {
    private static final String BROKER_URL = "${asyncapi.servers().get(params.server).url()}";
    private static final String TOPIC = "temperature/changed";

    private MqttClient client;

    public Client() {
        try {
            // Generate a unique client ID
            String clientId = MqttClient.generateClientId();
                    
            // Create and connect the MQTT client
            client = new MqttClient(BROKER_URL, clientId);
            MqttConnectOptions options = new MqttConnectOptions();
            options.setCleanSession(true);
                    
            client.connect(options);
            System.out.println("Connected to MQTT broker: " + BROKER_URL);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    ${topicMethods}

    public static void main(String[] args) {
        Client serviceClient = new Client();
                
        // Simulate sending a temperature change
        //serviceClient.sendTemperatureDrop("Sensor-1: 25°C");
    }
}`
    }
    
  );
}
```

Now your directory should look like this:

```
java-mqtt-client-template 
├── components
|   └── TopicFunction.js
├── src
|   └── fixtures
|       └── asyncapi.yml
│   └── main/java
|       └── Client.java
|       └── TestClient.java
├── template
|   └── index.js
└── package.json
└── build.gradle
```

#### 5b. Update AsyncAPI document with more channels

Add the following AsyncAPI document to have more channels:

```yaml
asyncapi: 2.6.0

info:
  title: Temperature Service
  version: 1.0.0
  description: This service is in charge of processing all the events related to temperature.

servers:
  dev:
    url: tcp://test.mosquitto.org:1883
    protocol: mqtt

channels:
  temperature/dropped:
    description:  Notifies the user when the temperature drops past a certain point.
    publish:
      operationId: temperatureDrop
      message:
        description: Message that is being sent when the temperature drops past a certain point.
        payload:
          type: object
          additionalProperties: false
          properties:
            temperatureId:
              type: string

  temperature/risen:
    description: Notifies the user when the temperature rises past a certain point.
    publish:
      operationId: temperatureRise
      message:
        description: Message that is being sent when the temperature rises past a certain point.
        payload:
          type: object
          additionalProperties: false
          properties:
            temperatureId:
              type: string

components:
  schemas:
    temperatureId:
      type: object
      additionalProperties: false
      properties:
        temperatureId:
          type: string

```
#### 5c. Update TestClient.java
We must now update the **TestClient.java** file to test the different channels in the AsyncAPI document above. The tests will be similar to the previous ones you performed earlier. Paste the following code snippet into your **TestClient.java** file:

```java
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class TestClient {
    public static void main(String[] args) {
        Client client = new Client();
        Random random = new Random();

        int idLength = 8;
        int minValue = (int) Math.pow(10, idLength - 1); // Minimum 8-digit number (e.g., 10000000)
        int maxValue = (int) Math.pow(10, idLength) - 1; // Maximum 8-digit number (e.g., 99999999)
        System.out.println("Validating generated generated Client.java");
        System.out.println("Running tests in TestClient.java");
        System.out.println("Sending temperature changes to the broker...");
        System.err.println("\n");
        while (true) {
            int randomId = random.nextInt(maxValue - minValue + 1) + minValue;
            client.sendTemperatureDrop(String.valueOf(randomId));
            System.out.println("Temperature drop detected " + randomId + " sent to temperature/dropped");
            
            client.sendTemperatureRise(String.valueOf(randomId));
            System.out.println("Temperature risen detected " + randomId + " sent to temperature/risen");

            try {
                TimeUnit.SECONDS.sleep(1); // Sleep for 1 second
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
```

Run `npm test` to validate that everything works as expected. You should see logs similar to the snippet below in your terminal:

```cmd
Connected to MQTT broker: tcp://test.mosquitto.org:1883

Validating generated generated Client.java
Running tests in TestClient.java
Sending temperature changes to the broker...
TemperatureDrop change sent: 43289900
Temperature drop detected 43289900 sent to temperature/dropped
TemperatureRise change sent: 43289900
Temperature risen detected 43289900 sent to temperature/risen
```

## Where to go from here?

Great job completing this tutorial! You have learnt how to use an AsyncAPI file to create a Java MQTT template and used it with the Paho-MQTT library in Java to connect to an MQTT broker and publish messages.😃

If you want to tinker with a completed template and see what it would look like in production, check out the [Java-MQTT-client-template](https://github.com/ssala034/Java-MQTT-client-template). You can also check out the accompanying [article about creating MQTT client code](https://www.brainfart.dev/blog/asyncapi-codegen-python).

You can also check out the [MQTT beginners guide](https://medium.com/python-point/mqtt-basics-with-python-examples-7c758e605d4) tutorial to learn more about asynchronous messaging using MQTT.

---

# Adding models generation in template
Source: https://www.asyncapi.com/docs/tools/generator/model-generation.md

# Adding models generation in template

This guide will walk you through the process of enabling models/types generation in a template by using [Modelina](https://www.asyncapi.com/tools/modelina).

Modelina is an AsyncAPI library designed for generating data models using inputs such as [AsyncAPI](asyncapi-document), OpenAPI, or JSON schema inputs. Its functionality revolves around creating data models from the provided AsyncAPI document and the model template, which defines message payloads. It is better to use Modelina in your template to handle model generation rather than providing custom templates.

You can integrate the work shown in this guide into a template by following the [tutorial about creating a template](https://www.asyncapi.com/docs/tools/generator/generator-template).

In this guide, you'll learn how to use Modelina in a template code to enable support for Python data model generation.

## Add Modelina dependency

Install Modelina in your project using npm: `npm install --save @asyncapi/modelina`.

Ensure your template's `package.json` file now contains Modelina pointing to its latest version:

 ```json
 "dependencies": {
    // ...
    "@asyncapi/modelina": "^2.0.5"
    // ...
  }
```

## Create a models.js file

Create a new directory in the **template** directory named **src/models** and create a **models.js** file within it. In the **models.js** file, add the following code:

```python
// 1
import { File } from '@asyncapi/generator-react-sdk';
// 2
import { PythonGenerator, FormatHelpers } from '@asyncapi/modelina';

/**
 * @typedef RenderArgument
 * @type {object}
 * @property {AsyncAPIDocument} asyncapi document object received from the generator.
 */

/**
 * Render all schema models
 * @param {RenderArgument} param0 
 * @returns 
 */
// 3
export default async function schemaRender({ asyncapi }) {
  // 4 
  const pythonGenerator = new PythonGenerator();
  // 5
  const models = await pythonGenerator.generate(asyncapi);
  // 6
  const files = [];
  // 7
  for (const model of models) {
    // 8
    const modelFileName = `${FormatHelpers.toPascalCase(model.modelName)}.py`;
    // 9
    files.push({model.result});
  }
  return files;
}
```

Let's break it down. The code snippet above does the following:

1. The `File` component from the [generator react SDK](https://github.com/asyncapi/generator-react-sdk) is needed to handle the further rendering of generated models into files.
2. The `PythonGenerator` generator is the core needed for model generation. Additionally, you can import [FormatHelpers](https://github.com/asyncapi/modelina/blob/master/src/helpers/FormatHelpers.ts) that provides a set of helpers making it easier to modify model names to match your required case.
3. You can change the name `schemaRender` to anything else like `modelRenderer`. More importantly, this must be an `async` function and a default export. This function is invoked during generation process and should contain the logic behind models generation.
4. First, create an instance of the `PythonGenerator` model generator. If you decide to use present functionality from Modelina, you need to pass your presets here during instance creation.
5. The actual model generation is one line of code, and as a result you get an array of models that later you need to turn into files.
6. You need to define an array that must be returned from `schemaRender` function. The array must contain React components, and in this case, the `<File>` component.
7. Iterate over generated models and use their content to create proper definitions of `<File>` components.
8. Notice how using Modelina helpers, in this case the  `toPascalCase` function, let's you make sure that the filename of your model follows specific case pattern.
9. Each component must be added into the `files` array that you later return from the default function. Notice the definition of the `<File>` component that enables you to provide the name of resulting file and the content of the model. Notice also `model.result` that shows that initially generated array with models did not contain raw models content but a set of output objects that contain not only `result` but also other info, like for example `modelName`.

With such a model template that uses Modelina, as a result of generation process you would receive a set of model files in `$OUTPUT_DIR/src/models` directory.

## Conclusion

Modelina provides a flexible and powerful way to generate data models from AsyncAPI, OpenAPI, or JSON Schema documents. By integrating Modelina you can much faster enable models generation in your template.

---

# Community - Contributing
Source: https://www.asyncapi.com/docs/tools/generator/contributing.md

# Community - Contributing

We love your input! We want to make contributing to this project as easy and transparent as possible.

## Contribution Recognition

We use [All Contributors](https://allcontributors.org/docs/en/specification) specification to handle recognitions. For more details read [this](https://github.com/asyncapi/community/blob/master/docs/010-contribution-guidelines/recognize-contributors.md) document.

## Guidelines for New Contributors

1. **Watch the Onboarding Webinar** - Before diving into code, watch our [Generator onboarding webinar](https://www.youtube.com/watch?v=Mkd7FgKOMNE) to understand the architecture and design decisions.
2. Read the [generator docs](/docs/tools/generator.md) to get an overview of what the project is about.
3. While reading through the docs one might identify issues (e.g., broken links, text formatting issues, etc.).
4. Some concepts in the documentation might not be presented clearly, so contributors can suggest improvements (e.g., adding more examples or code snippets to make the documentation easy to understand).
5. Familiarize yourself with the project's structure by reviewing the source code and understanding the roles of different files and components.
6. Testing is one of the areas where new contributors can contribute, as running tests reveals uncovered lines in a particular file (e.g., a **test coverage report**).
7. You can then try to add tests for those uncovered lines (e.g., a function within a file might not be covered). For reference, you can check out this [PR](https://github.com/asyncapi/generator/pull/1379).
8. Instead of creating entirely new tests, consider enhancing existing ones by adding more edge cases to include additional test scenarios.
9. We encourage contributors to help improve code quality by reviewing reported issues on [SonarCloud](https://sonarcloud.io/project/issues?issueStatuses=OPEN%2CCONFIRMED&id=asyncapi_generator) and suggesting improvements, identifying false reported issues that may need to be removed, and proposing fixes for valid issues.
10. See the [Development setup guide](/docs/tools/generator/development-setup.md) for more details on what you'll learn during onboarding.

## Few Tips for Effective Contributions

1. **Join the AsyncAPI Slack Workspace** - Connect with maintainers and fellow contributors in the `#generator` channel on [AsyncAPI Slack](https://www.asyncapi.com/slack-invite) to ask questions, share ideas, and get help. Also, consider attending the **weekly Knowledge Sharing meetings held every Wednesday**. Details are shared in the channel.
2. Understanding how the Generator works is key to making valuable contributions. You can start by actively following along and executing the steps given in the [generator template tutorial](/docs/tools/generator/generator-template.md). Hands-on practice will provide you with a comprehensive understanding of how the Generator processes templates and allow you to experiment with customization.
3. **PATIENCE** is crucial. Focus on creating meaningful contributions rather than rushing to submit a PR that adds little or no value to the project.
4. Adding entirely new features might be challenging because most features are already well-established. You may need to spend more time understanding the repository to identify areas for improvement.
5. You should research on Google regarding the @asyncapi/generator and related repositories (e.g., @asyncapi/parser or any of the template repositories) to identify potential improvements. AI can be a helpful assistant, but always double-check the information it provides with Google or StackOverflow.
6. Follow **Issue First, PR Later** - Always check if there's an existing issue before creating a new one, and raise your PR once the issue is confirmed/approved by any of the maintainers.
7. Keep **PRs small and focused** – A small PR with a well-defined scope is easier to review and merge. Avoid bundling multiple changes into one PR.
8. Collaborate with Other Contributors – If someone else has already raised an issue and you are interested in contributing to it, please communicate with them and collaborate instead of raising a separate PR independently. Working together leads to better contributions and avoids duplication of efforts. Open source is driven by **collaboration, not competition**.
9. **Respond to Maintainer Reviews Promptly** - If a maintainer requests changes or provides feedback on your PR, please try to address them within **7 days**. If you're unable to respond by then, the PR may be closed. Contributors are always welcome to open a new PR once they're ready to continue.

## Summary of the Contribution Flow

The following is a summary of the ideal contribution flow. Please, note that Pull Requests can also be rejected by the maintainers when appropriate.

```
    ┌───────────────────────┐
    │                       │
    │    Open an issue      │
    │  (a bug report or a   │
    │   feature request)    │
    │                       │
    └───────────────────────┘
               ⇩
    ┌───────────────────────┐
    │                       │
    │  Open a Pull Request  │
    │   (only after issue   │
    │     is approved)      │
    │                       │
    └───────────────────────┘
               ⇩
    ┌───────────────────────┐
    │                       │
    │   Your changes will   │
    │     be merged and     │
    │ published on the next │
    │        release        │
    │                       │
    └───────────────────────┘
```

## Code of Conduct

AsyncAPI has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://github.com/asyncapi/generator/blob/master/CODE_OF_CONDUCT.md) so that you can understand what sort of behaviour is expected.

## Our Development Process

We use Github to host code, to track issues and feature requests, as well as accept pull requests.

## Issues

[Open an issue](https://github.com/asyncapi/asyncapi/issues/new) **only** if you want to report a bug or a feature. Don't open issues for questions or support, instead join our [Slack workspace](https://www.asyncapi.com/slack-invite) and ask there. Don't forget to follow our [Slack Etiquette](https://github.com/asyncapi/community/blob/master/docs/060-meetings-and-communication/slack-etiquette.md) while interacting with community members! It's more likely you'll get help, and much faster!

### Issue Approval Process

Every newly opened issue is automatically labelled **`Awaiting Approval`**. This label signals that a core maintainer still needs to review and triage the issue before any work should begin.

#### How approval works

1. **A core maintainer reviews the issue** and, if it is valid and ready for work, posts a comment containing the `/approve` command.
2. The automation removes the `Awaiting Approval` label, adds the **`Approved Issue`** label, and posts a comment with contribution instructions.
3. Contributors can now pick up the issue, comment to claim it, and open a pull request.

> **Who can approve?** Only the core maintainers listed on the catch-all (`*`) line of the [`CODEOWNERS`](https://github.com/asyncapi/generator/blob/master/CODEOWNERS) file. Bot accounts are excluded. If anyone else uses `/approve`, a comment is posted explaining they are not authorized.

#### PR gating

Pull requests that reference an issue still carrying the `Awaiting Approval` label (via `Closes #N`, `Fixes #N`, or `Resolves #N`) are **automatically closed**. This ensures no work is merged for issues that have not been vetted. PRs that do not reference any issue at all are also automatically closed.

#### Commands reference

| Command | Who can use it | Effect |
|---------|---------------|--------|
| `/approve` | Core maintainers (from `CODEOWNERS`) | Removes `Awaiting Approval`, adds `Approved Issue`, posts contribution instructions |

## Bug Reports and Feature Requests

Please use our issues templates that provide you with hints on what information we need from you to help you out.

## Pull Requests

**Please, make sure you open an issue before starting with a Pull Request, unless it's a typo or a really obvious error.** Pull requests are the best way to propose changes to the specification. Get familiar with our document that explains [Git workflow](https://github.com/asyncapi/community/blob/master/docs/010-contribution-guidelines/git-workflow.md) used in our repositories.

## AI-Assisted Contributions

You may use generative AI and AI-assisted tooling to help you contribute, but you remain the author of and are fully accountable for everything you submit. Before submitting AI-assisted work, review it thoroughly, verify it meets our standards, remove unrelated changes, and confirm it does not violate any licenses.

If a contribution was materially AI-assisted, you **must** disclose it: add a `Generated-by: <tool + model version>` line to your pull request description (the PR template includes a dedicated section), or check the "No AI assistance" box. A CI check verifies that one of the two is present.

Read the full [AI Usage Policy](/docs/tools/generator/ai-policy.md) for details, including the functions that are off-limits for automation.

The project also runs AI tools on your PRs and issues (CodeRabbit reviews, Dosu Q&A). See the [AI tooling guide](/docs/tools/generator/ai-tooling.md) for what they do and how to work with them.

## Conventional Commits

Our repositories follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification. Releasing to GitHub and NPM is done with the support of [semantic-release](https://semantic-release.gitbook.io/semantic-release/).

Pull requests should have a title that follows the specification, otherwise, merging is blocked. If you are not familiar with the specification simply ask maintainers to modify. You can also use this cheatsheet if you want:

- `fix: ` prefix in the title indicates that PR is a bug fix and PATCH release must be triggered.
- `feat: ` prefix in the title indicates that PR is a feature and MINOR release must be triggered.
- `docs: ` prefix in the title indicates that PR is only related to the documentation and there is no need to trigger release.
- `chore: ` prefix in the title indicates that PR is only related to cleanup in the project and there is no need to trigger release.
- `test: ` prefix in the title indicates that PR is only related to tests and there is no need to trigger release.
- `refactor: ` prefix in the title indicates that PR is only related to refactoring and there is no need to trigger release.

What about MAJOR release? just add `!` to the prefix, like `fix!: ` or `refactor!: `

Prefix that follows specification is not enough though. Remember that the title must be clear and descriptive with usage of [imperative mood](https://chris.beams.io/posts/git-commit/#imperative).

## Maintainer Roles

To help scale maintenance of the monorepo, we define three key roles: **Triager**, **Committer**, and **Champion**.

### Triager

Triagers help manage issues and pull requests (PRs) across the entire project.

**Types:**
- `Code`: A code triager is responsible for triaging code-related topics.
- `Docs`: A docs triager is responsible for triaging documentation-related topics.

One person can be both a code and docs triager. However, this is not required, as `generator` is a large project with extensive documentation that benefits from having people focused solely on docs.

**Responsibilities:**
- Label issues and PRs
- Close or reopen issues
- Provide feedback and reviews
- Ensure contributor guidelines are followed
- Ensure PRs are of high quality and fullfil all the requirements

**Scope:**
- Applies to the entire monorepo (not scoped to specific templates).

**Notes:**
- Triagers **cannot** merge pull requests.
- Being active and consistent as a triager is the first step toward becoming a committer.
- Even though triagers cannot merge PRs and their approvals do not enable a PR to be merged, it is encouraged that triagers review and approve PRs using GitHub's functionality to indicate that the PR is accepted at the triage level.

### Committer

Committers are maintainers who can approve and merge PRs.

**Responsibilities:**
- Review and merge PRs
- Guide contributors
- Maintain high code/documentation standards

**Scope:**
- Some committers have access to the full monorepo (`core maintainers`)
- Others may have scoped access to specific area, like for example templates (`template champions`)

**Notes:**
- Committers play a vital role in onboarding and mentoring other contributors and triagers.

### Champion

Champions are committers who **own a specific area** of the codebase (e.g., a template, documentation, website). In other words, champions have write access to the repository, but through proper configuration in the `CODEOWNERS` file, their approval counts only for specific areas of the repository.

**Types of Champions:**
- **Template Champion** – Responsible for specific template(s) (e.g., Go, Markdown, Java, etc.).
- **Docs Champion** – Focuses on improving and maintaining generator's documentation.

**Becoming a Champion:**
- Regular, meaningful contributions in a focused area
- Active reviews, examples, tests, and documentation
- No limit to how many champions per area

**Notes:**
- Champions can merge PRs in their area of ownership.
- All champions are considered committers for their respective areas.

---

### Maintainer Role Matrix

| Responsibility        | Triager | Committer (Champion) | Committer (Core Maintainer) |
|-----------------------|:-------:|:----------------:|:-----------------------------:|
| Label issues/PRs      | ✅ | ✅ | ✅ | 
| Close/reopen issues   | ✅ | ✅ | ✅ | 
| Review PRs            | ✅ | ✅ | ✅ |
| Approve PRs           | ❌ | ✅ (within scope) | ✅ |
| Merge PRs             | ❌ | ✅ (within scope) | ✅ | 
| Modify repository settings | ❌ | ❌ | ✅ |
---

## License

By contributing, you agree that your submissions are under the [Apache 2.0 License](https://github.com/asyncapi/asyncapi/blob/master/LICENSE). Contact maintainers if this is a concern.

## References

This document was adapted from:

- [Facebook’s Draft Contributor Guide](https://github.com/facebook/draft-js/blob/master/CONTRIBUTING.md)
- [Modelina Champion Guidelines](https://github.com/asyncapi/modelina)
- [Website Triager/Committer Guidelines](https://github.com/asyncapi/website/blob/master/CONTRIBUTING.md#maintainers-setup)

---

# Community - Development setup
Source: https://www.asyncapi.com/docs/tools/generator/development-setup.md

# Community - Development setup

This guide helps you set up the `generator` locally and run it. For testing, see [Testing](/docs/tools/generator/development-testing.md). For releasing, see [Release process](/docs/tools/generator/release-process.md). For the AI tools that review your PRs, see [AI tooling](/docs/tools/generator/ai-tooling.md).

## Before you begin - new contributor onboarding

New to AsyncAPI Generator? We strongly recommend watching our comprehensive onboarding webinar first:

**Watch: [One Tool, One Flow: AsyncAPI's New Take on Code/Docs/Config Generation](https://www.youtube.com/watch?v=Mkd7FgKOMNE)**

### What you'll learn:

- What AsyncAPI is and the challenges it solves
- The origins and evolution of the Generator (legacy vs. future architecture)
- Understanding event-driven architectures and protocol complexity
- How the Generator works: templates, render engines, and the generation process
- Component-based template development for better reusability
- Baked-in templates and the monorepo structure
- Live demonstrations of code generation from AsyncAPI documents

This webinar provides essential context about the Generator's architecture, design decisions, and development workflow. Watching it will make the rest of this development guide much clearer and help you contribute more effectively.

## Getting started

1. Fork & Clone the repository:

First fork the repository from GitHub and then clone it using the following command:

```bash
git clone https://github.com/{your_username}/generator.git
cd generator
```

After cloning the repository, you should set up the fork properly and configure the `remote` repository as described in the [AsyncAPI git workflow guidelines](https://github.com/asyncapi/community/blob/master/docs/010-contribution-guidelines/git-workflow.md).

2. Install dependencies:

```bash
npm install --workspaces
```

**`CLAUDE.md` vs `AGENTS.md`:** The repo may ship `CLAUDE.md` as a symlink to [`AGENTS.md`](https://github.com/asyncapi/generator/blob/master/AGENTS.md) (the canonical guidelines file). After cloning, Linux and macOS usually need no extra step. On **Windows**, turn on **Developer Mode** (or enable symlink permissions), run `git config core.symlinks true`, then `git checkout -- CLAUDE.md` so Git creates a real symlink and not a one-line text stub. Edit **`AGENTS.md`** only for content updates and the symlink follows automatically.

## Additional commands

- Lint the code: `npm run lint`
- Generate documentation: `npm run docs`
- Build Docker image: `npm run docker:build`

## Troubleshooting

If you encounter any issues during development or testing, please check the following:

1. Ensure you're using the correct Node.js version (24.11 or higher) and npm version (11.5.1 or higher).
2. Clear the `node_modules` directory and reinstall dependencies if you encounter unexpected behavior.
3. For Docker-related issues, make sure Docker is running and you have sufficient permissions.

If problems persist, please open an issue on the GitHub repository.

---

# Community - Testing
Source: https://www.asyncapi.com/docs/tools/generator/development-testing.md

# Community - Testing

How to run and add tests for the generator. For local setup see [Development setup](/docs/tools/generator/development-setup.md).

### Running Tests Locally

To run all tests locally:

- Unit tests: `npm run generator:test:unit`
- Integration tests: `npm run generator:test:integration`

### Adding tests

1. Create new test files in the appropriate directory under `apps/generator/test/`.

2. Follow the existing test patterns.

3. Run your new tests using the commands listed above.

## Running Tests in Docker

To run tests in an isolated Docker environment:

1. Ensure Docker is installed and running on your machine, with **Docker Compose v2** (the `docker compose` command, not the legacy `docker-compose` v1). The Compose configuration files use the `pull_policy` key, which is only supported by Compose v2.

2. Run the following command from the project root:

```bash
docker compose up
```

You can also choose to run the lint checks after the tests complete by setting an environment variable `LINT` with any value before the command:
   - Windows: `set LINT=true && docker compose up`
   - Linux/macOS: `LINT=true docker compose up`

> This approach ensures a clean environment for each test run by cleanly installing dependencies and running tests in a Docker container.

### Manually testing with test templates

To test template features manually, use the `react-template` located in `apps/generator/test/test-templates`. You can run your changes against this template as follows:

1. Navigate to the generator directory:

```bash
cd apps/generator
```
2. Modify the react-template in `./test/test-templates/react-template` to test different features.

3. Run the generator against the the test template:

```bash
node ./test/cli ./test/docs/dummy.yml ./test/test-templates/react-template -o ./test/output --force-write
```

4. Check the `./test/output` directory to confirm it matches the output you expected.

---

# Community - Release process
Source: https://www.asyncapi.com/docs/tools/generator/release-process.md

# Community - Release process

This guide details how releases are handled for the generator packages. For local setup see the [Development setup](/docs/tools/generator/development-setup.md) guide.

To release a major/minor/patch:

## Conventional Commits

For a detailed explanation of conventional commits, refer to [this guide](/docs/tools/generator/contributing.md#conventional-commits).
To maintain a clear git history of commits and easily identify what each commit changed and whether it triggered a release, we use conventional commits. The feat and fix prefixes are particularly important as they are needed to trigger changesets. Using these prefixes ensures that the changes are correctly categorized and the versioning system functions as expected.

For Example:
```
feat: add new feature
```

## Pull Request Title Guidelines

To ensure successful workflow execution, all PR titles must follow the conventional commits format and PR titles should start with a lowercase character. Incorrect PR titles can cause workflow failures, preventing PRs from being merged.
For the PR titles you can refer to [this guide](/docs/tools/generator/contributing.md#conventional-commits).

### Manual

1.  Create a new release markdown file in the `.changeset` directory. The filename should indicate what the change is about.

2.  Add the following content to the file in this particular format:

    ```markdown
    ---
    "@package-name-1": [type] (major/minor/patch)
    "@package-name-2": [type]
    ---

    [Provide a brief description of the changes. For example: Added a new Release GitHub Flow to the Turborepo. No new features or bugfixes were introduced.]
    ```

    For Example:

    ```markdown
    ---
    "@asyncapi/generator": minor
    ---

    Adding new Release Github Flow to the Turborepo. No new features or bugfixes were introduced.

    ```

3. Include the file in your pull request.

### Using CLI

1. Create a new release markdown file using changeset CLI. The command below triggers an interactive prompt that you can use to specify the release type and affected packages.
    ```bash
    npx -p @changesets/cli@2.27.7 changeset
    ```

2. Include the file in your pull request.

> **Tip:**
> For more detailed instructions, refer to the official documentation for [adding a changeset](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

## Release Flow

1. **Add a Changeset**:
   - When you make changes that need to be released, create a markdown file in the `.changeset` directory stating the package name and level of change (major/minor/patch).

2. **Open a Pull Request**:
   - Push your changes and open a Pull Request (PR). After the PR is merged the changeset file helps communicate the type of changes (major, minor, patch).

3. **CI Processes Changeset**:
   - After the PR is merged, a dedicated GitHub Actions release workflow runs using the changeset action.

   - This action reads the markdown files in the `.changeset` folder and creates a PR with the updated version of the package and removes the markdown file. For example:

     Before:
     ```json
     "name": "@asyncapi/generator",
     "version": "2.0.1",
     ```

     After:
     ```json
     "name": "@asyncapi/generator",
     "version": "3.0.1",
     ```

   - The new PR will also contain the description from the markdown files.

   - The AsyncAPI bot automatically merges such a release PR.

4. **Release the Package**:

   - After the PR is merged, the CI/CD pipeline triggers again. The `changesets/action` step identifies that the PR was created by itself. It then verifies if the current version of the package is greater than the previously released version. If a difference is detected, it executes the publish command to release the updated package.

---

# Community - AI usage policy
Source: https://www.asyncapi.com/docs/tools/generator/ai-policy.md

# Community - AI usage policy

This policy governs the use of generative AI and AI-assisted tooling (LLMs, coding agents, autocomplete assistants, and similar) when contributing to this repository.

> **AI tools are instruments — humans are the only authors.**

You may use AI tools to help you contribute. But the moment you open a pull request or an issue, **you** are the author of every line in it. The tool is not a co-maintainer, it is not accountable, and it cannot be cited as an excuse. This policy exists so that AI accelerates good contributions without lowering the bar for quality, security, or trust.

This is a contributor-facing policy. It is **not** the same as [`AGENTS.md`](https://github.com/asyncapi/generator/blob/master/AGENTS.md): that file instructs coding agents on *how to write code that fits this repository*, whereas this policy defines *the rules and expectations for humans who use AI to contribute here*.

## When this applies

This policy applies to **any** contribution where a generative AI tool materially assisted in producing the content, including:

- source code, tests, and configuration,
- documentation and template content,
- issue descriptions, and
- review comments.

If you only used AI for spell-checking, search, or to understand existing code, disclosure is not required. If AI generated or substantially shaped the content you are submitting, it is.

## Your responsibilities as a contributor

Before you submit AI-assisted work, you must:

1. **Review it thoroughly.** Read and understand every part of the contribution. If you do not understand it, do not submit it.
2. **Verify quality.** Ensure it meets this project's standards — it builds, tests pass, and it follows the conventions in the [contributing guide](/docs/tools/generator/contributing.md) and [`AGENTS.md`](https://github.com/asyncapi/generator/blob/master/AGENTS.md).
3. **Remove extraneous changes.** Strip out unrelated edits, dead code, speculative abstractions, and noise the tool introduced. Keep the diff focused.
4. **Be prepared to explain it.** You must be able to justify any part of the contribution if a maintainer asks. "The AI wrote it" is not an answer.
5. **Accept responsibility.** You bear full accountability for the contribution, exactly as if you had written every line by hand.
6. **Check licensing.** Confirm that generated material does not reproduce code under incompatible licenses and does not violate this project's [license](https://github.com/asyncapi/generator/blob/master/LICENSE).

> Blindly copy-pasting AI output introduces security and stability risks. Maintainers may close such pull requests without review.

## Required disclosure

If a contribution was materially AI-assisted, you **must** disclose it:

- **Pull requests:** include a `Generated-by:` line in the PR description naming the tool and its version, for example:

  ```text
  Generated-by: Claude Code 1.x
  Generated-by: GitHub Copilot
  ```

  The pull request template carries a dedicated AI-assistance section — fill in the `Generated-by:` line, or check the "no AI assistance" box if it does not apply. A CI check verifies that one of the two is present. It confirms a declaration exists, but does not and cannot verify its truthfulness.

- **Issues:** note in the issue body that AI assisted in drafting it.

Disclosure is a sign of good faith, not an admission of wrongdoing. We welcome AI-assisted contributions that follow this policy.

## Consequences

- Maintainers may **close non-compliant pull requests without review**, including undisclosed AI-generated PRs and PRs the contributor cannot explain.
- **Repeated violations** are treated as a breach of our [Code of Conduct](https://github.com/asyncapi/generator/blob/master/CODE_OF_CONDUCT.md) and may result in the contributor being blocked.

If you are unsure whether something falls under this policy, ask a maintainer in the `#generator` channel on [AsyncAPI Slack](https://www.asyncapi.com/slack-invite) before submitting.

---

# Community - AI tooling
Source: https://www.asyncapi.com/docs/tools/generator/ai-tooling.md

# Community - AI tooling

This project uses automated AI tools to assist with code review and to answer questions on pull requests and issues. This page describes those tools, CodeRabbit and Dosu, explaining how they work, how to interact with them, and how much to rely on their output.

> **Note:**
> This page covers the AI tools that the project runs on your contributions. It is distinct from two related documents: the [AI Usage Policy](/docs/tools/generator/ai-policy.md) defines the rules for using AI to write your own contributions, including the required disclosure, while [`AGENTS.md`](https://github.com/asyncapi/generator/blob/master/AGENTS.md) provides guidelines for coding agents that generate code for this repository.

## CodeRabbit

[CodeRabbit](https://www.coderabbit.ai/) automatically reviews pull requests in this repository. Its behavior is configured in [`.coderabbit.yaml`](https://github.com/asyncapi/generator/blob/master/.coderabbit.yaml) at the repo root, so the review is consistent and reproducible.

**What it does on a pull request:**

- Posts an automatic review when a PR is opened and re-reviews incrementally as you push new commits. Draft PRs are not reviewed, and bot accounts (`dependabot`, `asyncapi-bot`) are ignored.
- Adds a high-level summary of the change and a per-file changed-files summary.
- Links the PR to related issues and PRs and assesses whether it addresses its linked issue.
- Runs linters as part of the review: ESLint, markdownlint, yamllint, and actionlint (for GitHub Actions workflows).
- Flags suspected low-effort or AI-generated "slop" with an `AI-Spam` label.
- Enforces a **pre-merge title check**: your PR title must follow our [Conventional Commits guidelines](/docs/tools/generator/contributing.md#conventional-commits). A non-conforming title fails the check and blocks merge until you fix it.

**How to interact with it:**

CodeRabbit only acts on explicit mentions (it does not auto-reply to every comment). In a PR comment you can use:

- `@coderabbitai review` — trigger a fresh review.
- `@coderabbitai summary` — regenerate the high-level summary.
- `@coderabbitai pause` / `@coderabbitai resume` — stop or restart automatic reviews on the PR.
- `@coderabbitai resolve` — resolve CodeRabbit's open review comments.

**How to treat its feedback:**

CodeRabbit is **advisory**. It is not a maintainer, and its review is **not an approval** — a human maintainer still reviews and approves every PR. Use its suggestions as a helpful first pass and act on the ones that make the change better. You are not obligated to apply a suggestion, but when you choose not to, reply with a comment explaining why.

## Dosu

[Dosu](https://dosu.dev/) answers questions about the project. You can reach it in three ways:

- **On GitHub** — mention `@dosu` in an issue or pull request comment with your question (for example, asking where a feature lives or how a workflow behaves). It does not comment on its own and replies only when mentioned.
- **On Slack** — Dosu is connected to the public `#generator` channel in the [AsyncAPI community Slack](https://www.asyncapi.com/slack-invite), so you can ask it there as well.
- **In its web chat** — ask a question directly in [Dosu's chat for the generator](https://app.dosu.dev/e0d32413-3b37-4b53-85d6-bd7caab075e8/ask).

**How to treat its answers:**

Dosu is useful for **orientation and context**, but its answers are **not authoritative maintainer decisions** and can be wrong or out of date. Verify anything important against the code, the docs, or a maintainer before relying on it. For a binding decision, ask a maintainer in the `#generator` channel on the AsyncAPI community Slack.

## Quick reference

| You want to... | Do this |
|---|---|
| Re-run the CodeRabbit review | Comment `@coderabbitai review` |
| Pause/resume CodeRabbit on a PR | Comment `@coderabbitai pause` / `@coderabbitai resume` |
| Fix a failing title check | Edit the PR title to follow [Conventional Commits](/docs/tools/generator/contributing.md#conventional-commits) |
| Ask a question about the project | Mention `@dosu` on an issue or PR, ask in the `#generator` Slack channel, or use [Dosu's web chat](https://app.dosu.dev/e0d32413-3b37-4b53-85d6-bd7caab075e8/ask) |

Both tools are assistants, not decision-makers. A human maintainer always has the final say.

---

# Introduction
Source: https://www.asyncapi.com/docs/tools/cli.md

# Introduction

The AsyncAPI CLI is a command-line tool that provides a set of commands for working with AsyncAPI documents. AsyncAPI is a specification for describing asynchronous APIs, which allows developers to define the structure of messages exchanged between different parts of their applications. The AsyncAPI CLI simplifies creating, validating, bundling, and manipulating AsyncAPI documents, making it easier to work with asynchronous APIs.

## Features

The AsyncAPI CLI offers the following key features:

* Creation: New AsyncAPI documents can be created from scratch using the CLI, which is useful when starting a new project or creating a new version of an existing API.

* Validation: AsyncAPI documents can be quickly and easily validated using the [AsyncAPI Parser](https://github.com/asyncapi/parser-js), which ensures that the documents conform to the AsyncAPI specification and catches errors early in the development process.

* Conversion: The AsyncAPI CLI can convert AsyncAPI documents from one version to another, which is helpful for migrating APIs to a newer version of the AsyncAPI specification.

* Difference: Using [Diff](https://github.com/asyncapi/cli/tree/master/packages/diff) (the `@asyncapi/diff` library, which lives in this monorepo under `packages/diff`), the AsyncAPI CLI can find the differences between two AsyncAPI documents, which helps compare different versions of an API or identify changes made to an API.
  
* Generation: The AsyncAPI CLI leverages AsyncAPI libraries like [Generator](https://github.com/asyncapi/generator) and [Modelina](https://github.com/asyncapi/modelina), which allow you to generate various types of documentation, applications, and models in different programming languages. This feature can save significant time and effort when creating new APIs.

* Optimize: Using [Optimizer](https://github.com/asyncapi/cli/tree/master/packages/optimizer) (the `@asyncapi/optimizer` library, which now lives in this monorepo under `packages/optimizer`), the AsyncAPI CLI can be used to optimize an AsyncAPI specification file which can optimize the structure of the AsyncAPI document to make it smaller and without repetition.

* Start: The AsyncAPI CLI can be used to start [AsyncAPI Studio](https://studio.asyncapi.com/) locally, which the user can use to view, edit, and test AsyncAPI documents. Studio is not bundled with the CLI; the first time you use it, the CLI installs it on-demand (~450MB).
  
To summarize, the AsyncAPI CLI offers the following features and process flow, as shown in the diagram below:

```mermaid
graph TD;
A[AsyncAPI Document]
B[Creation]
J[Studio - Editor]
I[Optimization]
D[Validation]
C[Generation]
F[Apps/Docs]
G[Models]
H[Diff]
K[Bundling]
E[Conversion]
A-->B;
A-->D;
A-->C;
C-->F
C-->G
A-->H;
A-->I;
A-->J;
A-->E;
A-->K;
```

## CLI flow

The following flowchart illustrates the process flow of the AsyncAPI CLI:

```mermaid
graph TD;
A[Start] --> B[User runs the AsyncAPI CLI]
B --> C[User issues a command]
C --> D[CLI processes the command and runs the corresponding operation]
D --> |Is the operation successful?| E{Yes}
D --> |Is the operation recoverable?| F{Yes}
E --> G[CLI returns the results of the operation to the user]
F --> |Operation Error| H[CLI displays an error message and suggests possible next steps]
G --> J[User receives the results]
H --> I[User follows suggested steps to recover]
I --> C[User reissues the corrected command]
J[User terminates the AsyncAPI CLI] --> K[End]
```

This flowchart shows the high-level process that occurs when using the AsyncAPI CLI. The user starts by running a command (such as `validate`, `generate`, or `start`), which the CLI processes. The CLI then performs the corresponding operation (such as validating or generating an AsyncAPI document) and returns the results to the user. If an error occurs, the CLI displays an error message and suggests possible next steps for the user.

---

# Installation guide
Source: https://www.asyncapi.com/docs/tools/cli/installation.md

# Installation guide

## Node and npm

To use the AsyncAPI CLI tool, you must install NPM and Node.js version 16 or higher. To check if you already have both installed, run the following commands in your terminal:

```sh
# check if node is installed
node -v
# or
node --version

# check if NPM is installed
npm -v
# or
npm --version
```

If you don’t have Node.js or NPM installed, you can install both with this [Node.js package manager](https://nodejs.org/en/download/package-manager/).

After installing Node.js and NPM, run the following command to install the AsyncAPI ClI globally:
```sh
npm install -g @asyncapi/cli
```

> [!NOTE]
> AsyncAPI Studio is not bundled with the CLI to keep the install small. The first time you run `asyncapi start studio`, `asyncapi start preview`, or `asyncapi new --studio`, the CLI will ask to download Studio (~450MB) into its data directory. To download it ahead of time, run `asyncapi studio install` (or `asyncapi studio install --yes` without a prompt). In non-interactive environments (like CI), pass `--yes` or set `ASYNCAPI_STUDIO_AUTO_INSTALL=1`.

> [!IMPORTANT]
> Standalone `.exe`, `.pkg`, `.deb`, and archive installations do not bundle npm. All non-Studio CLI commands work without npm, but installing Studio on-demand requires npm on `PATH`. If the CLI reports that npm is unavailable, install Node.js and npm from [nodejs.org](https://nodejs.org/) and rerun `asyncapi studio install --yes`.
To enable the autocomplete feature in the CLI for the shells **bash and zshrc**, there is a script that will run automatically and autocomplete is only support for **bash and zshrc** for the **powershell** refer to manually enabling  [autocomplete](https://www.asyncapi.com/docs/tools/cli/autocompleteEnabled) guide in ClI:

After the ClI installation :

if the configuration is not present logs will be:
```sh
✅ Autocomplete configuration added to .zshrc.
```
If the configuration is present for autocomplete logs:
```sh
✅ Autocomplete is already configured. Skipping addition.
```

To refresh the variables:

```sh
 source ~/.bashrc   # For bash
 source ~/.zshrc    # For zsh
```

## Docker

Install [Docker](https://docs.docker.com/get-docker/) first, then use docker to build the image using the following command :
``` 
docker build -t asyncapi/cli:latest . 
``` 
and run the image using the following command :

```bash
docker run --rm -it \
--user=root \
-v [ASYNCAPI SPEC FILE LOCATION]:/app/asyncapi.yml \
-v [GENERATED FILES LOCATION]:/app/output \
asyncapi/cli [COMMAND HERE]

# Example that you can run inside the cli directory after cloning this repository. First, you specify the mount in the location of your AsyncAPI specification file and then you mount it in the directory where the generation result should be saved.
docker run --rm -it \
   --user=root \
   -v ${PWD}/test/integration/fixtures/asyncapi_v1.yml:/app/asyncapi.yml \
   -v ${PWD}/output:/app/output \
   asyncapi/cli generate fromTemplate -o /app/output /app/asyncapi.yml @asyncapi/html-template --force-write
```
Note: Use ``` ` ``` instead of `\` for Windows.

> [!NOTE]
> The Docker image keeps chromium (so PDF generation with `@asyncapi/html-template` works out of the box) but does not bundle AsyncAPI Studio. Running `asyncapi start studio`/`start preview` inside the container will offer to install Studio on-demand; pass `--yes` (or set `ASYNCAPI_STUDIO_AUTO_INSTALL=1`) to install it without a prompt. Note that Studio starts a local web server, so you also need to publish the port (e.g. `-p 3210:3210`) to reach it from your host.

## Mac
There are two ways to install the AsyncAPI CLI on your macOS: using the `brew` package manager or `pkg` files.

### brew

To install the AsyncAPI CLI using the `brew` package manager, run the following commands in your terminal:
```sh
# Install brew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install AsyncAPI CLI
brew install asyncapi
```

### pkg

Every release of the AsyncAPI CLI has two macOS dedicated `pkg` file that enables you to install the CLI tool as a macOS application for x64 as well as arm64 architecture.
To download the latest CLI release, run this command in your terminal:
```sh
# For x64
curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x64.pkg

# For arm64
curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.arm64.pkg
```

To download a specific CLI release, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/download/<replace this with the specific CLI version e.g v0.13.0>/asyncapi.pkg
```

> **Remember**
>
> Follow this link for all <a href="https://github.com/asyncapi/cli/releases">AsyncAPI CLI releases</a>.

After downloading the AsyncAPI CLI, install it via the following command:

```sh
sudo installer -pkg asyncapi.pkg -target /
```

## Windows 

There are two ways to install the AsyncAPI CLI on your Windows operating system: using the `chocolatey` package manager or executable files.

### Chocolatey

Prerequisites:
[Chocolatey](https://chocolatey.org/install) must be installed on your Windows operating system. The installation instructions can be found [here](https://docs.chocolatey.org/en-us/choco/setup#installing-chocolatey-cli).

To install the AsyncAPI CLI using the `chocolatey` package manager, run the following command in your terminal with administrator privileges:

```sh
# Install AsyncAPI CLI
choco install asyncapi
```

To upgrade run this command:- 
```sh
# Upgrade AsyncAPI CLI
choco upgrade asyncapi
```
To install a specific version run this command:
```sh
# Install AsyncAPI CLI version xx.xx.xx
choco install asyncapi --version xx.xx.xx
```
All the AsyncAPI CLI versions can be found [here](https://chocolatey.org/packages/asyncapi).

### Executable files

Just install the appropriate installer and simply follow the default installation steps to complete the installation process.

Download [asyncapi.x64.exe](https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x64.exe) for 64-bit Windows and download [asyncapi.x86.exe](https://github.com/asyncapi/cli/releases/latest/download/asyncapi.x86.exe) for 32-bit Windows.

## Linux
Selecting the appropriate AsyncAPI CLI installation method on a Linux operating system depends on your Linux distro.

### Debian based distros

For Debian based distros, you can install the AsycAPI CLI using the `dpkg` package manager for Debian.
```sh
curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.deb
```

To download a specific release of the CLI, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/download/<replace this with the specific CLI version e.g v0.13.0>/asyncapi.deb
```

### Other distros
You can install the AsyncAPI CLI for other Linux distros using the archive `tar.gz` file. 

#### For Alpine Linux / musl-based systems:
To download the latest Alpine-compatible release, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi-alpine.tar.gz
```

To download a specific Alpine-compatible release, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/download/<replace this with the specific CLI version e.g v0.13.0>/asyncapi-alpine.tar.gz
```

Once downloaded, untar the file:
```sh
tar -xzf asyncapi-alpine.tar.gz
```

#### For other Linux distributions (glibc-based):

To download the latest release of the CLI, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/latest/download/asyncapi.tar.gz
```

To download a specific release of the CLI, run this command in your terminal:
```sh
curl -OL https://github.com/asyncapi/cli/releases/download/<replace this with the specific CLI version e.g v0.13.0>/asyncapi.tar.gz
```

Once you have downloaded the archived file, untar it by running this command in your terminal:
```sh
tar -xzf asyncapi.tar.gz
```

### Setting up the symlink (for both Alpine and glibc versions):

The step above will create an `AsyncAPI` directory in the current path. To run the CLI from anywhere, you must create a `symlink`. If the current path you are on is `/user/local/bin`, for example, you must create the `symlink` in the `/user/local/bin` directory by following these steps:
```sh
# cd into the unarchived directory
cd asyncapi

# get the absolute path
pwd

# Create a symlink
ln -s <absolute-path>/bin/asyncapi /user/local/bin/asyncapi

# The "asyncapi" command should be available to be used
asyncapi
```
> [!NOTE]
> If youare using Alpine Linux or any musl-based distribution, make sure to download the `-alpine.tar.gz` version to avoid glibc compatibility issues. The regular `asyncapi.tar.gz` file is compiled for glibc-based systems and will not work on Alpine.

---

# Auto-complete setup
Source: https://www.asyncapi.com/docs/tools/cli/autocompleteEnabled.md

# Auto-complete setup

# AsyncAPI CLI Autocomplete Setup

This guide provides steps to enable autocomplete for the AsyncAPI CLI. The setup supports `zsh`, `bash`, and `PowerShell` (manual setup only).

## Automatic Setup (Post-Install Script)
The AsyncAPI CLI includes a post-install script that automatically configures autocomplete for supported shells (`zsh` and `bash`). No additional steps are required.

### Steps:
1. Ensure that AsyncAPI CLI is installed. You can verify by running:
   ```sh
   asyncapi --version
   ```
   If the command fails, install it using:
   ```sh
   npm install -g @asyncapi/cli
   ```

2. Apply the changes by running:
   ```sh
   source ~/.bashrc   # For bash
   source ~/.zshrc    # For zsh
   ```

3. Verify autocomplete by typing:
   ```sh
   asyncapi <TAB>
   ```
   You should see command suggestions.

## Manual Setup (For PowerShell and Troubleshooting)
If the automatic setup does not work or if you need to enable autocomplete manually (especially for PowerShell), follow these steps.

### Steps:
1. **Build the AsyncAPI CLI manually:**
   If you are working with the CLI project locally, you need to build it first:
   ```sh
   npm install
   npm run build
   ```

2. **Run the autocomplete command manually:**
   ```sh
   ./bin/run autocomplete  # Run this from the project root folder
   ```

3. **Locate the AsyncAPI CLI executable:**
   Run the following command to find the executable path:
   ```sh
   which asyncapi   # For bash/zsh
   Get-Command asyncapi | Select-Object -ExpandProperty Definition   # For PowerShell
   ```
   If the command does not return a path, ensure AsyncAPI CLI is installed.

4. **Generate and apply the autocomplete script:**
   Run the following command based on your shell:
   ```sh
   printf "$(./bin/run autocomplete script bash)" >> ~/.bashrc; source ~/.bashrc   # For bash
   printf "$(./bin/run autocomplete script zsh)" >> ~/.zshrc; source ~/.zshrc       # For zsh
   printf "$(./bin/run autocomplete script powershell)" >> $PROFILE; . $PROFILE    # For PowerShell
   ```

5. **Test autocomplete:**
   ```sh
   asyncapi <TAB>
   ```
   If it works, autocomplete is successfully enabled!

---

If you encounter any issues, ensure that your shell configuration file is correctly updated and sourced. Restart your terminal if necessary.

---

# CLI Architecture
Source: https://www.asyncapi.com/docs/tools/cli/architecture.md

# CLI Architecture

## Overview

The AsyncAPI CLI is built with [oclif](https://oclif.io/) and provides both command-line operations and a REST API server for working with AsyncAPI specifications.

---

## Architecture Diagram

```
┌─────────────────────────────────────────────────┐
│  Entry Points                                   │
│  ┌──────────┐              ┌──────────┐         │
│  │   CLI    │              │   API    │         │
│  │  (oclif) │              │ (Express)│         │
│  └────┬─────┘              └────┬─────┘         │
└───────┼─────────────────────────┼───────────────┘
        └───────────┬─────────────┘
                    ▼
        ┌───────────────────────┐
        │   Domain Services     │
        │  Validation, Generator│
        │  Convert, Config      │
        └───────────┬───────────┘
                    ▼
        ┌───────────────────────┐
        │   Domain Models       │
        │  Specification,Context│
        └───────────┬───────────┘
                    ▼
        ┌───────────────────────┐
        │   Utilities           │
        │  Logger, Helpers      │
        └───────────────────────┘
```

---

## Directory Structure

```
src/
├── apps/
│   ├── cli/              # CLI commands & internals
│   └── api/              # REST API (Express)
├── domains/
│   ├── models/           # Specification, Context
│   └── services/         # Business logic
├── errors/               # Custom errors
├── interfaces/           # TypeScript types
└── utils/                # Utilities
```

---

## Core Components

### CLI Application

| Component | Description |
|-----------|-------------|
| **Entry Points** | `bin/run` (dev), `bin/run_bin` (prod) |
| **Base Command** | Metrics, parser integration, error handling |

**Commands:**
- **Core:** `validate`, `convert`, `format`, `optimize`, `diff`, `bundle`
- **Generation:** `generate client`, `generate models`, `generate fromTemplate`
- **Config:** `config context`, `config analytics`, `config versions`
- **Utility:** `new file`, `new template`, `start api|studio|preview`, `pretty` (Studio for `start studio`/`preview` is installed on-demand, not bundled)

### API Server

**Endpoints:** `/v1/validate`, `/v1/parse`, `/v1/generate`, `/v1/convert`, `/v1/bundle`, `/v1/diff`, `/v1/docs`, `/v1/help`, `/v1/version`

**Features:** Express with Helmet security, CORS, compression, RFC 7807 error responses

### Domain Services

All services extend `BaseService` and return `ServiceResult<T>`:

| Service | Purpose |
|---------|---------|
| `ValidationService` | Validates specs with Spectral, calculates scores |
| `GeneratorService` | Generates code/models |
| `ConvertService` | Converts between AsyncAPI/OpenAPI formats |
| `ConfigService` | Manages CLI config and contexts |
| `ArchiverService` | Creates ZIP archives |

### Domain Models

| Model | Purpose |
|-------|---------|
| **Specification** | Loads from file, URL, or context; auto-detects `asyncapi.json\|yml\|yaml` |
| **Context** | Manages multiple AsyncAPI contexts; stored in `~/.asyncapi/` |

### Error Classes

`ContextError`, `SpecificationFileError`, `ValidationError`, `GeneratorError`, `DiffError`

---

## Execution Flow

**CLI Command:**
```
User Command → oclif → Base Command → Domain Service → ServiceResult
```

**API Request:**
```
HTTP Request → Express → Controller → Domain Service → HTTP Response
```

---

## Extension Points

| Add | Steps |
|-----|-------|
| **New Command** | Create in `src/apps/cli/commands/`, extend `Command`, implement `run()` |
| **New API Endpoint** | Create controller in `src/apps/api/controllers/`, register in `index.ts` |
| **New Service** | Create in `src/domains/services/`, extend `BaseService`, return `ServiceResult<T>` |

---

## Configuration

| Config | Location |
|--------|----------|
| CLI Context | `~/.asyncapi/contexts.json`, `~/.asyncapi/.current` |
| Analytics | `~/.asyncapi-analytics` |

**Environment Variables:**
- `NODE_ENV` — `development` | `production` | `test`
- `PORT` — API server port (default: 3000)
- `ASYNCAPI_METRICS_*` — Metrics configuration

---

## Technology Stack

| Category | Technologies |
|----------|--------------|
| **Core** | oclif, TypeScript, Express |
| **AsyncAPI** | @asyncapi/parser, generator, converter, bundler, diff, optimizer |
| **Supporting** | winston, ajv, chalk, @clack/prompts |

## Workspace packages (monorepo)

This repository is an npm-workspaces + [Turborepo](https://turbo.build/) monorepo. The root package is
`@asyncapi/cli` (still published from the repo root). `workspaces` includes both `"."` and `packages/*`
so Changesets versions the CLI the same way it does today (`npx changeset` → select `@asyncapi/cli`)
and also versions workspace packages such as `@asyncapi/optimizer` and `@asyncapi/diff`. Additional publishable packages live under `packages/*`:

| Package | Path | Notes |
|---------|------|-------|
| `@asyncapi/optimizer` | `packages/optimizer/` | The optimization library used by the `asyncapi optimize` command. Published independently to npm; the CLI depends on it via the workspace (`"@asyncapi/optimizer": "*"`). `@asyncapi/parser` is a `peerDependency` of this package. |
| `@asyncapi/diff` | `packages/diff/` | The diff library used by `asyncapi diff` and `POST /v1/diff`. Published independently to npm; the CLI depends on it via the workspace (`"@asyncapi/diff": "*"`). Callers pass already-parsed documents. `@asyncapi/parser` is a devDependency of this package. |

Turbo orders builds so `@asyncapi/optimizer` and `@asyncapi/diff` are built before the root CLI (whose build compiles the
commands that import them). Use `npm run optimizer:build` / `npm run optimizer:test` and `npm run diff:build` / `npm run diff:test` to work on them
in isolation. Specs: [`docs/optimizer/spec.md`](https://github.com/asyncapi/cli/blob/master/docs/optimizer/spec.md), [`docs/diff/spec.md`](https://github.com/asyncapi/cli/blob/master/docs/diff/spec.md).

---

# Usage
Source: https://www.asyncapi.com/docs/tools/cli/usage.md

# Usage

<!-- 

This file is automatically generated from updateUsageDocs.js script. In package.json in line 158-161 lines the following steps has been executed in order to run this script successfully - 

* generate:readme:create: It creates the initial content for the README file by printing the usage and commands tags using printf and redirects the output to scripts/README.md file.
* generate:readme:commands: It changes the directory to the scripts folder and executes the oclif readme command. This command generates the usage and commands sections based on the CLI commands and updates the content in the scripts/README.md file.
* generate:assets: This script combines the two previously mentioned scripts (generate:readme:toc and generate:commands) to generate the necessary assets, such as the README file and usage documentation.
* generate:commands: This script executes the following steps:
 - Runs the generate:readme:create script to create the initial content for the README file.
 - Executes the generate:readme:commands script to generate the usage and commands sections based on the CLI commands.
 - Runs the updateUsageDocs.js script using Node.js to update the usage documentation file with the contents of the generated README file.
 - Deletes the scripts/README.md file using the rimraf command.

-->

The AsyncAPI CLI makes it easier to work with AsyncAPI documents.
# Usage

<!-- usage -->
```sh-session
$ npm install -g @asyncapi/cli
$ asyncapi COMMAND
running command...
$ asyncapi (--version|--v)
@asyncapi/cli/5.0.7 darwin-arm64 node-v24.7.0
$ asyncapi --help [COMMAND]
USAGE
  $ asyncapi COMMAND
...
```
<!-- usagestop -->

# Commands

<!-- commands -->
* [`asyncapi autocomplete [SHELL]`](#asyncapi-autocomplete-shell)
* [`asyncapi bundle`](#asyncapi-bundle)
* [`asyncapi config`](#asyncapi-config)
* [`asyncapi config analytics`](#asyncapi-config-analytics)
* [`asyncapi config auth add PATTERN TOKEN`](#asyncapi-config-auth-add-pattern-token)
* [`asyncapi config context`](#asyncapi-config-context)
* [`asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH`](#asyncapi-config-context-add-context-name-spec-file-path)
* [`asyncapi config context current`](#asyncapi-config-context-current)
* [`asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH`](#asyncapi-config-context-edit-context-name-new-spec-file-path)
* [`asyncapi config context init [CONTEXT-FILE-PATH]`](#asyncapi-config-context-init-context-file-path)
* [`asyncapi config context list`](#asyncapi-config-context-list)
* [`asyncapi config context remove CONTEXT-NAME`](#asyncapi-config-context-remove-context-name)
* [`asyncapi config context use CONTEXT-NAME`](#asyncapi-config-context-use-context-name)
* [`asyncapi config versions`](#asyncapi-config-versions)
* [`asyncapi convert [SPEC-FILE]`](#asyncapi-convert-spec-file)
* [`asyncapi diff OLD NEW`](#asyncapi-diff-old-new)
* [`asyncapi format [SPEC-FILE]`](#asyncapi-format-spec-file)
* [`asyncapi generate`](#asyncapi-generate)
* [`asyncapi generate client LANGUAGE [ASYNCAPI]`](#asyncapi-generate-client-language-asyncapi)
* [`asyncapi generate fromTemplate [ASYNCAPI] [TEMPLATE]`](#asyncapi-generate-fromtemplate-asyncapi-template)
* [`asyncapi generate models LANGUAGE FILE`](#asyncapi-generate-models-language-file)
* [`asyncapi new`](#asyncapi-new)
* [`asyncapi new file`](#asyncapi-new-file)
* [`asyncapi new template`](#asyncapi-new-template)
* [`asyncapi optimize [SPEC-FILE]`](#asyncapi-optimize-spec-file)
* [`asyncapi pretty SPEC-FILE`](#asyncapi-pretty-spec-file)
* [`asyncapi start`](#asyncapi-start)
* [`asyncapi start api`](#asyncapi-start-api)
* [`asyncapi start preview SPEC-FILE`](#asyncapi-start-preview-spec-file)
* [`asyncapi start studio [SPEC-FILE]`](#asyncapi-start-studio-spec-file)
* [`asyncapi validate [SPEC-FILE]`](#asyncapi-validate-spec-file)

## `asyncapi autocomplete [SHELL]`

Display autocomplete installation instructions.

```
USAGE
  $ asyncapi autocomplete [SHELL] [-r]

ARGUMENTS
  [SHELL]  (zsh|bash|powershell) Shell type

FLAGS
  -r, --refresh-cache  Refresh cache (ignores displaying instructions)

DESCRIPTION
  Display autocomplete installation instructions.

EXAMPLES
  $ asyncapi autocomplete

  $ asyncapi autocomplete bash

  $ asyncapi autocomplete zsh

  $ asyncapi autocomplete powershell

  $ asyncapi autocomplete --refresh-cache
```

_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.2.40/src/commands/autocomplete/index.ts)_

## `asyncapi bundle`

Bundle one or multiple AsyncAPI Documents and their references together.

```
USAGE
  $ asyncapi bundle [-h] [-o <value>] [-b <value>] [-d <value>] [-x]

FLAGS
  -b, --base=<value>     Path to the file which will act as a base. This is required when some properties need to be
                         overwritten.
  -d, --baseDir=<value>  One relative/absolute path to directory relative to which paths to AsyncAPI Documents that
                         should be bundled will be resolved.
  -h, --help             Show CLI help.
  -o, --output=<value>   The output file name. Omitting this flag the result will be printed in the console.
  -x, --xOrigin          Pass this switch to generate properties "x-origin" that will contain historical values of
                         dereferenced "$ref"s.

DESCRIPTION
  Bundle one or multiple AsyncAPI Documents and their references together.

EXAMPLES
  $ asyncapi bundle ./asyncapi.yaml > final-asyncapi.yaml

  $ asyncapi bundle ./asyncapi.yaml --output final-asyncapi.yaml

  $ asyncapi bundle ./asyncapi.yaml ./features.yaml

  $ asyncapi bundle ./asyncapi.yaml ./features.yaml --base ./main.yaml

  $ asyncapi bundle ./asyncapi.yaml ./features.yaml --base ./main.yaml --xOrigin

  $ asyncapi bundle ./asyncapi.yaml -o final-asyncapi.yaml --base ../public-api/main.yaml --baseDir ./social-media/comments-service
```

_See code: [src/commands/bundle.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/bundle.ts)_

## `asyncapi config`

CLI config settings

```
USAGE
  $ asyncapi config

DESCRIPTION
  CLI config settings
```

_See code: [src/commands/config/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/index.ts)_

## `asyncapi config analytics`

Enable or disable analytics for metrics collection

```
USAGE
  $ asyncapi config analytics [-h] [-d] [-e] [-s]

FLAGS
  -d, --disable  disable analytics
  -e, --enable   enable analytics
  -h, --help     Show CLI help.
  -s, --status   show current status of analytics

DESCRIPTION
  Enable or disable analytics for metrics collection
```

_See code: [src/commands/config/analytics.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/analytics.ts)_

## `asyncapi config auth add PATTERN TOKEN`

Add an authentication config for resolving $ref files requiring HTTP Authorization.

```
USAGE
  $ asyncapi config auth add PATTERN TOKEN [-a <value>] [-h <value>...]

ARGUMENTS
  PATTERN  Glob pattern for matching protected URLs (e.g. github.com/org/repo/**/*.*)
  TOKEN    Authentication token or environment variable reference (prefix with $, e.g. $GITHUB_TOKEN)

FLAGS
  -a, --auth-type=<value>  Authentication type (default is "Bearer")
  -h, --header=<value>...  Additional header in key=value format; can be used multiple times

DESCRIPTION
  Add an authentication config for resolving $ref files requiring HTTP Authorization.
```

_See code: [src/commands/config/auth/add.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/auth/add.ts)_

## `asyncapi config context`

Manage short aliases for full paths to AsyncAPI documents

```
USAGE
  $ asyncapi config context

DESCRIPTION
  Manage short aliases for full paths to AsyncAPI documents
```

_See code: [src/commands/config/context/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/index.ts)_

## `asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH`

Add a context to the store

```
USAGE
  $ asyncapi config context add CONTEXT-NAME SPEC-FILE-PATH [-h] [-s]

ARGUMENTS
  CONTEXT-NAME    context name
  SPEC-FILE-PATH  file path of the spec file

FLAGS
  -h, --help         Show CLI help.
  -s, --set-current  Set context being added as the current context

DESCRIPTION
  Add a context to the store
```

_See code: [src/commands/config/context/add.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/add.ts)_

## `asyncapi config context current`

Shows the current context that is being used

```
USAGE
  $ asyncapi config context current [-h]

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Shows the current context that is being used
```

_See code: [src/commands/config/context/current.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/current.ts)_

## `asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH`

Edit a context in the store

```
USAGE
  $ asyncapi config context edit CONTEXT-NAME NEW-SPEC-FILE-PATH [-h]

ARGUMENTS
  CONTEXT-NAME        context name
  NEW-SPEC-FILE-PATH  file path of the spec file

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Edit a context in the store
```

_See code: [src/commands/config/context/edit.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/edit.ts)_

## `asyncapi config context init [CONTEXT-FILE-PATH]`

Initialize context

```
USAGE
  $ asyncapi config context init [CONTEXT-FILE-PATH] [-h]

ARGUMENTS
  [CONTEXT-FILE-PATH]  Specify directory in which context file should be created:
                       - current directory          : asyncapi config context init .(default)
                       - root of current repository : asyncapi config context init ./
                       - user's home directory      : asyncapi config context init ~`

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Initialize context
```

_See code: [src/commands/config/context/init.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/init.ts)_

## `asyncapi config context list`

List all the stored contexts in the store

```
USAGE
  $ asyncapi config context list [-h]

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  List all the stored contexts in the store
```

_See code: [src/commands/config/context/list.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/list.ts)_

## `asyncapi config context remove CONTEXT-NAME`

Delete a context from the store

```
USAGE
  $ asyncapi config context remove CONTEXT-NAME [-h]

ARGUMENTS
  CONTEXT-NAME  Name of the context to delete

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Delete a context from the store
```

_See code: [src/commands/config/context/remove.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/remove.ts)_

## `asyncapi config context use CONTEXT-NAME`

Set a context as current

```
USAGE
  $ asyncapi config context use CONTEXT-NAME [-h]

ARGUMENTS
  CONTEXT-NAME  name of the saved context

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Set a context as current
```

_See code: [src/commands/config/context/use.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/context/use.ts)_

## `asyncapi config versions`

Show versions of AsyncAPI tools used

```
USAGE
  $ asyncapi config versions [-h]

FLAGS
  -h, --help  Show CLI help.

DESCRIPTION
  Show versions of AsyncAPI tools used
```

_See code: [src/commands/config/versions.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/config/versions.ts)_

## `asyncapi convert [SPEC-FILE]`

Convert asyncapi documents older to newer versions or OpenAPI documents to AsyncAPI

```
USAGE
  $ asyncapi convert [SPEC-FILE] -f openapi|asyncapi [-h] [-o <value>] [-t <value>] [-p client|server]
    [--proxyHost <value>] [--proxyPort <value>]

ARGUMENTS
  [SPEC-FILE]  spec path, url, or context-name

FLAGS
  -f, --format=<option>         (required) [default: asyncapi] Specify the format to convert from (openapi or asyncapi)
                                <options: openapi|asyncapi>
  -h, --help                    Show CLI help.
  -o, --output=<value>          path to the file where the result is saved
  -p, --perspective=<option>    [default: server] Perspective to use when converting OpenAPI to AsyncAPI (client or
                                server). Note: This option is only applicable for OpenAPI to AsyncAPI conversions.
                                <options: client|server>
  -t, --target-version=<value>  [default: 3.1.0] asyncapi version to convert to
      --proxyHost=<value>       Name of the ProxyHost
      --proxyPort=<value>       Port number number for the proxyHost.

DESCRIPTION
  Convert asyncapi documents older to newer versions or OpenAPI documents to AsyncAPI
```

_See code: [src/commands/convert.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/convert.ts)_

## `asyncapi diff OLD NEW`

Find diff between two asyncapi files

```
USAGE
  $ asyncapi diff OLD NEW [-h] [-f json|yaml|yml|md] [-t breaking|non-breaking|unclassified|all]
    [--markdownSubtype json|yaml|yml] [-o <value>] [--no-error] [-w] [--log-diagnostics] [--diagnostics-format
    json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-climate|gitlab|markdown] [--fail-severity
    error|warn|info|hint] [-s <value>]

ARGUMENTS
  OLD  old spec path, URL or context-name
  NEW  new spec path, URL or context-name

FLAGS
  -f, --format=<option>              [default: yaml] format of the output
                                     <options: json|yaml|yml|md>
  -h, --help                         Show CLI help.
  -o, --overrides=<value>            path to JSON file containing the override properties
  -s, --save-output=<value>          The output file name. Omitting this flag the result will be printed in the console.
  -t, --type=<option>                [default: all] type of the output
                                     <options: breaking|non-breaking|unclassified|all>
  -w, --watch                        Enable watch mode
      --diagnostics-format=<option>  [default: stylish] format to use for validation diagnostics
                                     <options: json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-cl
                                     imate|gitlab|markdown>
      --fail-severity=<option>       [default: error] diagnostics of this level or above will trigger a failure exit
                                     code
                                     <options: error|warn|info|hint>
      --[no-]log-diagnostics         log validation diagnostics or not
      --markdownSubtype=<option>     the format of changes made to AsyncAPI document. It works only when diff is
                                     generated using md type. For example, when you specify subtype as json, then diff
                                     information in markdown is dumped as json structure.
                                     <options: json|yaml|yml>
      --no-error                     don't show error on breaking changes

DESCRIPTION
  Find diff between two asyncapi files
```

_See code: [src/commands/diff.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/diff.ts)_

## `asyncapi format [SPEC-FILE]`

Convert asyncapi documents from any format to yaml, yml or JSON

```
USAGE
  $ asyncapi format [SPEC-FILE] -f yaml|yml|json [-h] [-o <value>]

ARGUMENTS
  [SPEC-FILE]  spec path, url, or context-name

FLAGS
  -f, --format=<option>  (required) [default: json] Specify the format to convert to
                         <options: yaml|yml|json>
  -h, --help             Show CLI help.
  -o, --output=<value>   path to the file where the result is saved

DESCRIPTION
  Convert asyncapi documents from any format to yaml, yml or JSON
```

_See code: [src/commands/format.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/format.ts)_

## `asyncapi generate`

Generate typed models or other things like clients, applications or docs using AsyncAPI Generator templates.

```
USAGE
  $ asyncapi generate

DESCRIPTION
  Generate typed models or other things like clients, applications or docs using AsyncAPI Generator templates.
```

_See code: [src/commands/generate/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/generate/index.ts)_

## `asyncapi generate client LANGUAGE [ASYNCAPI]`

Generates clients baked-in AsyncAPI Generator. Available for: dart, java, javascript, python. If some language is not supported or you want to improve existing client, join us at https://github.com/asyncapi/generator

```
USAGE
  $ asyncapi generate client LANGUAGE [ASYNCAPI] [-h] [-d <value>...] [--no-interactive] [-i] [--debug] [-n
    <value>...] [-o <value>] [--force-write] [-w] [-p <value>...] [--map-base-url <value>] [--registry-url <value>]
    [--registry-auth <value>] [--registry-token <value>] [--proxyHost <value>] [--proxyPort <value>]

ARGUMENTS
  LANGUAGE    The language you want the client generated for. Available target languages: dart, java, javascript, python
  [ASYNCAPI]  - Local path, url or context-name pointing to AsyncAPI file

FLAGS
  -d, --disable-hook=<value>...  Disable a specific hook type or hooks from a given hook type
  -h, --help                     Show CLI help.
  -i, --install                  Installs the template and its dependencies (defaults to false)
  -n, --no-overwrite=<value>...  Glob or path of the file(s) to skip when regenerating
  -o, --output=<value>           Directory where to put the generated files (defaults to current directory)
  -p, --param=<value>...         Additional param to pass to templates
  -w, --watch                    Watches the template directory and the AsyncAPI document, and re-generate the files
                                 when changes occur. Ignores the output directory.
      --debug                    Enable more specific errors in the console
      --force-write              Force writing of the generated files to given directory even if it is a git repo with
                                 unstaged files or not empty dir (defaults to false)
      --map-base-url=<value>     Maps all schema references from base url to local folder
      --no-interactive           Disable interactive mode and run with the provided flags.
      --proxyHost=<value>        Name of the ProxyHost
      --proxyPort=<value>        Port number number for the proxyHost.
      --registry-auth=<value>    The registry username and password encoded with base64, formatted as username:password
      --registry-token=<value>   The npm registry authentication token, that can be passed instead of base64 encoded
                                 username and password
      --registry-url=<value>     [default: https://registry.npmjs.org] Specifies the URL of the private registry for
                                 fetching templates and dependencies

DESCRIPTION
  Generates clients baked-in AsyncAPI Generator. Available for: dart, java, javascript, python. If some language is not
  supported or you want to improve existing client, join us at https://github.com/asyncapi/generator

EXAMPLES
  $ asyncapi generate client javascript asyncapi.yaml --param version=1.0.0 singleFile=true --output ./docs --force-write
```

_See code: [src/commands/generate/client.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/generate/client.ts)_

## `asyncapi generate fromTemplate [ASYNCAPI] [TEMPLATE]`

Generates whatever you want using templates compatible with AsyncAPI Generator.

```
USAGE
  $ asyncapi generate fromTemplate [ASYNCAPI] [TEMPLATE] [-h] [-d <value>...] [--no-interactive] [-i] [--debug] [-n
    <value>...] [-o <value>] [--force-write] [-w] [-p <value>...] [--map-base-url <value>] [--registry-url <value>]
    [--registry-auth <value>] [--registry-token <value>] [--proxyHost <value>] [--proxyPort <value>]

ARGUMENTS
  [ASYNCAPI]  - Local path, url or context-name pointing to AsyncAPI file
  [TEMPLATE]  - Name of the generator template like for example @asyncapi/html-template or
              https://github.com/asyncapi/html-template

FLAGS
  -d, --disable-hook=<value>...  Disable a specific hook type or hooks from a given hook type
  -h, --help                     Show CLI help.
  -i, --install                  Installs the template and its dependencies (defaults to false)
  -n, --no-overwrite=<value>...  Glob or path of the file(s) to skip when regenerating
  -o, --output=<value>           Directory where to put the generated files (defaults to current directory)
  -p, --param=<value>...         Additional param to pass to templates
  -w, --watch                    Watches the template directory and the AsyncAPI document, and re-generate the files
                                 when changes occur. Ignores the output directory.
      --debug                    Enable more specific errors in the console
      --force-write              Force writing of the generated files to given directory even if it is a git repo with
                                 unstaged files or not empty dir (defaults to false)
      --map-base-url=<value>     Maps all schema references from base url to local folder
      --no-interactive           Disable interactive mode and run with the provided flags.
      --proxyHost=<value>        Name of the ProxyHost
      --proxyPort=<value>        Port number number for the proxyHost.
      --registry-auth=<value>    The registry username and password encoded with base64, formatted as username:password
      --registry-token=<value>   The npm registry authentication token, that can be passed instead of base64 encoded
                                 username and password
      --registry-url=<value>     [default: https://registry.npmjs.org] Specifies the URL of the private registry for
                                 fetching templates and dependencies

DESCRIPTION
  Generates whatever you want using templates compatible with AsyncAPI Generator.

EXAMPLES
  $ asyncapi generate fromTemplate asyncapi.yaml @asyncapi/html-template --param version=1.0.0 singleFile=true --output ./docs --force-write
```

_See code: [src/commands/generate/fromTemplate.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/generate/fromTemplate.ts)_

## `asyncapi generate models LANGUAGE FILE`

Generates typed models

```
USAGE
  $ asyncapi generate models LANGUAGE FILE [-h] [-o <value>] [--packageName <value>] [--namespace <value>]
    [--tsModelType class|interface] [--tsEnumType enum|union] [--tsModuleSystem ESM|CJS] [--tsIncludeComments]
    [--tsExportType default|named] [--tsJsonBinPack] [--tsMarshalling] [--tsExampleInstance] [--tsRawPropertyNames]
    [--csharpAutoImplement] [--csharpNewtonsoft] [--csharpArrayType Array|List] [--csharpHashcode] [--csharpEqual]
    [--csharpSystemJson] [--goIncludeComments] [--goIncludeTags] [--javaIncludeComments] [--javaJackson]
    [--javaConstraints] [--javaArrayType Array|List] [--pyDantic] [--no-interactive] [--log-diagnostics]
    [--diagnostics-format
    json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-climate|gitlab|markdown] [--fail-severity
    error|warn|info|hint] [-s <value>] [--proxyHost <value>] [--proxyPort <value>]

ARGUMENTS
  LANGUAGE  (typescript|csharp|golang|java|javascript|dart|python|rust|kotlin|php|cplusplus|scala) The language you want
            the typed models generated for.
  FILE      Path or URL to the AsyncAPI document, or context-name

FLAGS
  -h, --help                         Show CLI help.
  -o, --output=<value>               The output directory where the models should be written to. Omitting this flag will
                                     write the models to `stdout`.
  -s, --save-output=<value>          The output file name. Omitting this flag the result will be printed in the console.
      --csharpArrayType=<option>     [default: Array] C# specific, define which type of array needs to be generated.
                                     <options: Array|List>
      --csharpAutoImplement          C# specific, define whether to generate auto-implemented properties or not.
      --csharpEqual                  C# specific, generate the models with the Equal method overwritten
      --csharpHashcode               C# specific, generate the models with the GetHashCode method overwritten
      --csharpNewtonsoft             C# specific, generate the models with newtonsoft serialization support
      --csharpSystemJson             C# specific, generate the models with System.Text.Json serialization support
      --diagnostics-format=<option>  [default: stylish] format to use for validation diagnostics
                                     <options: json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-cl
                                     imate|gitlab|markdown>
      --fail-severity=<option>       [default: error] diagnostics of this level or above will trigger a failure exit
                                     code
                                     <options: error|warn|info|hint>
      --goIncludeComments            Golang specific, if enabled add comments while generating models.
      --goIncludeTags                Golang specific, if enabled add tags while generating models.
      --javaArrayType=<option>       [default: Array] Java specific, define which type of array needs to be generated.
                                     <options: Array|List>
      --javaConstraints              Java specific, generate the models with constraints
      --javaIncludeComments          Java specific, if enabled add comments while generating models.
      --javaJackson                  Java specific, generate the models with Jackson serialization support
      --[no-]log-diagnostics         log validation diagnostics or not
      --namespace=<value>            C#, C++ and PHP specific, define the namespace to use for the generated models.
                                     This is required when language is `csharp`,`c++` or `php`.
      --no-interactive               Disable interactive mode and run with the provided flags.
      --packageName=<value>          Go, Java and Kotlin specific, define the package to use for the generated models.
                                     This is required when language is `go`, `java` or `kotlin`.
      --proxyHost=<value>            Name of the ProxyHost
      --proxyPort=<value>            Port number number for the proxyHost.
      --pyDantic                     Python specific, generate the Pydantic models.
      --tsEnumType=<option>          [default: enum] TypeScript specific, define which type of enums needs to be
                                     generated.
                                     <options: enum|union>
      --tsExampleInstance            Typescript specific, generate example of the model.
      --tsExportType=<option>        [default: default] TypeScript specific, define which type of export needs to be
                                     generated.
                                     <options: default|named>
      --tsIncludeComments            TypeScript specific, if enabled add comments while generating models.
      --tsJsonBinPack                TypeScript specific, define basic support for serializing to and from binary with
                                     jsonbinpack.
      --tsMarshalling                TypeScript specific, generate the models with marshalling functions.
      --tsModelType=<option>         [default: class] TypeScript specific, define which type of model needs to be
                                     generated.
                                     <options: class|interface>
      --tsModuleSystem=<option>      [default: ESM] TypeScript specific, define the module system to be used.
                                     <options: ESM|CJS>
      --tsRawPropertyNames           Typescript specific, generate the models using raw property names.

DESCRIPTION
  Generates typed models
```

_See code: [src/commands/generate/models.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/generate/models.ts)_

## `asyncapi new`

Create a new AsyncAPI project, specification files, or templates for clients and applications.

```
USAGE
  $ asyncapi new

DESCRIPTION
  Create a new AsyncAPI project, specification files, or templates for clients and applications.
```

_See code: [src/commands/new/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/new/index.ts)_

## `asyncapi new file`

Creates a new asyncapi file

```
USAGE
  $ asyncapi new file [-h] [-n <value>] [-e <value>] [-s] [-p <value>] [--no-tty]

FLAGS
  -e, --example=<value>
      name of the example to use. Available examples are:
      - simple-asyncapi.yml
      - adeo-kafka-request-reply-asyncapi.yml
      - anyof-asyncapi.yml
      - application-headers-asyncapi.yml
      - correlation-id-asyncapi.yml
      - websocket-gemini-asyncapi.yml
      - gitter-streaming-asyncapi.yml
      - kraken-websocket-request-reply-message-filter-in-reply-asyncapi.yml
      - kraken-websocket-request-reply-multiple-channels-asyncapi.yml
      - mercure-asyncapi.yml
      - not-asyncapi.yml
      - operation-security-asyncapi.yml
      - oneof-asyncapi.yml
      - rpc-client-asyncapi.yml
      - rpc-server-asyncapi.yml
      - slack-rtm-asyncapi.yml
      - tutorial.yml
      - streetlights-kafka-asyncapi.yml
      - streetlights-operation-security-asyncapi.yml
      - streetlights-mqtt-asyncapi.yml

  -h, --help
      Show CLI help.

  -n, --file-name=<value>
      name of the file

  -p, --port=<value>
      port in which to start Studio

  -s, --studio
      open in Studio

  --no-tty
      do not use an interactive terminal

DESCRIPTION
  Creates a new asyncapi file

EXAMPLES
  $ asyncapi new	 - start creation of a file in interactive mode

  $ asyncapi new --file-name=my-asyncapi.yaml --example=default-example.yaml --no-tty	 - create a new file with a specific name, using one of the examples and without interactive mode
```

_See code: [src/commands/new/file.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/new/file.ts)_

## `asyncapi new template`

Creates a new template

```
USAGE
  $ asyncapi new template [-h] [-n <value>] [-t <value>] [-f <value>] [--force-write]

FLAGS
  -f, --file=<value>      The path to the AsyncAPI file for generating a template.
  -h, --help              Show CLI help.
  -n, --name=<value>      [default: project] Name of the Project
  -t, --template=<value>  [default: default] Name of the Template
      --force-write       Force writing of the generated files to given directory even if it is a git repo with unstaged
                          files or not empty dir (defaults to false)

DESCRIPTION
  Creates a new template
```

_See code: [src/commands/new/template.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/new/template.ts)_

## `asyncapi optimize [SPEC-FILE]`

optimize asyncapi specification file

```
USAGE
  $ asyncapi optimize [SPEC-FILE] [-h] [-p
    remove-components|reuse-components|move-duplicates-to-components|move-all-to-components...] [-i schema...] [-o
    terminal|new-file|overwrite] [--no-tty] [--proxyHost <value>] [--proxyPort <value>]

ARGUMENTS
  [SPEC-FILE]  spec path, url, or context-name

FLAGS
  -h, --help                      Show CLI help.
  -i, --ignore=<option>...        [default: ] list of components to be ignored from the optimization process
                                  <options: schema>
  -o, --output=<option>           [default: terminal] select where you want the output.
                                  <options: terminal|new-file|overwrite>
  -p, --optimization=<option>...  [default: remove-components,reuse-components,move-duplicates-to-components,move-all-to
                                  -components] select the type of optimizations that you want to apply.
                                  <options: remove-components|reuse-components|move-duplicates-to-components|move-all-to
                                  -components>
      --no-tty                    do not use an interactive terminal
      --proxyHost=<value>         Name of the ProxyHost
      --proxyPort=<value>         Port number number for the proxyHost.

DESCRIPTION
  optimize asyncapi specification file

EXAMPLES
  $ asyncapi optimize ./asyncapi.yaml

  $ asyncapi optimize ./asyncapi.yaml --no-tty

  $ asyncapi optimize ./asyncapi.yaml --optimization=remove-components --optimization=reuse-components --optimization=move-all-to-components --no-tty

  $ asyncapi optimize ./asyncapi.yaml --optimization=remove-components --output=terminal --no-tty

  $ asyncapi optimize ./asyncapi.yaml --ignore=schema
```

_See code: [src/commands/optimize.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/optimize.ts)_

## `asyncapi pretty SPEC-FILE`

Beautify the AsyncAPI spec file (indentation, styling) in place or output the formatted spec to a new file.

```
USAGE
  $ asyncapi pretty SPEC-FILE [-o <value>]

ARGUMENTS
  SPEC-FILE  spec path, url, or context-name

FLAGS
  -o, --output=<value>  Output file path

DESCRIPTION
  Beautify the AsyncAPI spec file (indentation, styling) in place or output the formatted spec to a new file.

EXAMPLES
  $ asyncapi pretty ./asyncapi.yaml

  $ asyncapi pretty ./asyncapi.yaml --output formatted-asyncapi.yaml
```

_See code: [src/commands/pretty.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/pretty.ts)_

## `asyncapi start`

Starts AsyncAPI-related services. Currently, it supports launching the AsyncAPI Studio

```
USAGE
  $ asyncapi start

DESCRIPTION
  Starts AsyncAPI-related services. Currently, it supports launching the AsyncAPI Studio
```

_See code: [src/commands/start/index.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/start/index.ts)_

## `asyncapi start api`

starts the AsyncAPI server API.

```
USAGE
  $ asyncapi start api [-h] [-m development|production|test] [-p <value>]

FLAGS
  -h, --help           Show CLI help.
  -m, --mode=<option>  [default: production] mode in which to start the API
                       <options: development|production|test>
  -p, --port=<value>   port in which to start the API

DESCRIPTION
  starts the AsyncAPI server API.
```

_See code: [src/commands/start/api.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/start/api.ts)_

## `asyncapi start preview SPEC-FILE`

starts a new local instance of Studio in minimal state bundling all the refs of the schema file and with no editing allowed.

```
USAGE
  $ asyncapi start preview SPEC-FILE [-h] [-p <value>] [-b <value>] [-d <value>] [-x] [-l] [-B]

ARGUMENTS
  SPEC-FILE  the path to the file to be opened with studio or context name

FLAGS
  -B, --noBrowser        Pass this to not open browser automatically upon running the command
  -b, --base=<value>     Path to the file which will act as a base. This is required when some properties need to be
                         overwritten while bundling with the file.
  -d, --baseDir=<value>  One relative/absolute path to directory relative to which paths to AsyncAPI Documents that
                         should be bundled will be resolved.
  -h, --help             Show CLI help.
  -l, --suppressLogs     Pass this to suppress the detiled error logs.
  -p, --port=<value>     port in which to start Studio in the preview mode
  -x, --xOrigin          Pass this switch to generate properties "x-origin" that will contain historical values of
                         dereferenced "$ref"s.

DESCRIPTION
  starts a new local instance of Studio in minimal state bundling all the refs of the schema file and with no editing
  allowed.
```

_See code: [src/commands/start/preview.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/start/preview.ts)_

## `asyncapi start studio [SPEC-FILE]`

starts a new local instance of Studio

```
USAGE
  $ asyncapi start studio [SPEC-FILE] [-h] [-f <value>] [-p <value>] [--no-interactive] [-B]

ARGUMENTS
  [SPEC-FILE]  spec path, url, or context-name

FLAGS
  -B, --noBrowser       Pass this to not open browser automatically upon running the command
  -f, --file=<value>    path to the AsyncAPI file to link with Studio
  -h, --help            Show CLI help.
  -p, --port=<value>    port in which to start Studio
      --no-interactive  disable prompts for this command which asks for file path if not passed via the arguments.

DESCRIPTION
  starts a new local instance of Studio
```

_See code: [src/commands/start/studio.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/start/studio.ts)_

## `asyncapi validate [SPEC-FILE]`

validate asyncapi file

```
USAGE
  $ asyncapi validate [SPEC-FILE] [-h] [-w] [--log-diagnostics] [--diagnostics-format
    json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-climate|gitlab|markdown] [--fail-severity
    error|warn|info|hint] [-s <value>] [--score] [--suppressWarnings <value>...] [--suppressAllWarnings] [--proxyHost
    <value>] [--proxyPort <value>]

ARGUMENTS
  [SPEC-FILE]  spec path, url, or context-name

FLAGS
  -h, --help                         Show CLI help.
  -s, --save-output=<value>          The output file name. Omitting this flag the result will be printed in the console.
  -w, --watch                        Enable watch mode
      --diagnostics-format=<option>  [default: stylish] format to use for validation diagnostics
                                     <options: json|stylish|junit|html|text|teamcity|pretty|github-actions|sarif|code-cl
                                     imate|gitlab|markdown>
      --fail-severity=<option>       [default: error] diagnostics of this level or above will trigger a failure exit
                                     code
                                     <options: error|warn|info|hint>
      --[no-]log-diagnostics         log validation diagnostics or not
      --proxyHost=<value>            Name of the ProxyHost
      --proxyPort=<value>            Port number number for the proxyHost.
      --score                        Compute the score of the AsyncAPI document. Scoring is based on whether the
                                     document has description, license, server and/or channels.
      --suppressAllWarnings          Suppress all warnings from the validation output.
      --suppressWarnings=<value>...  List of warning codes to suppress from the validation output.

DESCRIPTION
  validate asyncapi file
```

_See code: [src/commands/validate.ts](https://github.com/asyncapi/cli/blob/v5.0.7/src/commands/validate.ts)_
<!-- commandsstop -->

---

# Contributing via Pull Requests
Source: https://www.asyncapi.com/docs/tools/cli/contributing-prs.md

# Contributing via Pull Requests

## Getting Started

1. **Open an issue first** (unless it's a trivial fix)
2. **Set up environment** — Follow [DEVELOPMENT.md](../DEVELOPMENT.md)
3. **Create a branch** — Use prefixes: `feat/`, `fix/`, `docs/`, `refactor/`, `test/`, `chore/`

---

## PR Title Format

Follow [Conventional Commits](https://www.conventionalcommits.org/):

| Type | Description | Release |
|------|-------------|---------|
| `feat:` | New feature | MINOR |
| `fix:` | Bug fix | PATCH |
| `docs:` | Documentation | None |
| `chore:` | Maintenance | None |
| `test:` | Tests only | None |
| `refactor:` | Code refactoring | None |

**Breaking changes:** Add `!` → `feat!:`, `fix!:`

**Examples:**
- ✅ `feat: add AsyncAPI 3.0 validation support`
- ✅ `fix: resolve context loading with special characters`
- ❌ `Added new feature`
- ❌ `fix bug`

---

## PR Checklist

**Before submitting:**
- [ ] Branch synced with `main`
- [ ] `npm run build` passes
- [ ] `npm run cli:test` passes
- [ ] `npm run lint` passes (max 5 warnings)
- [ ] Documentation updated (if needed)

**Code quality:**
- [ ] Follows existing code patterns
- [ ] TypeScript types used (avoid `any`)
- [ ] Error handling implemented
- [ ] Tests added for new functionality
- [ ] No `console.log` or commented code

---

## Code Standards

| Area | Guideline |
|------|-----------|
| **TypeScript** | Explicit types, interfaces for objects, prefer `const` |
| **Organization** | Follow existing structure, use path aliases (`@/`, `@cli/`, `@domains/`) |
| **Errors** | Use custom errors from `src/errors/`, return `ServiceResult<T>` from services |
| **Commands** | Extend base `Command`, use domain services for business logic |

---

## Testing

**Add tests for:**
- New commands or API endpoints
- Bug fixes (regression tests)
- New domain services
- Complex business logic

```bash
npm run cli:test      # All tests
npm run unit:test     # Unit tests only
```

---

## Best Practices

| ❌ Avoid | ✅ Do |
|----------|-------|
| Large PRs (>500 lines) | Small, focused PRs |
| Multiple concerns in one PR | One issue per PR |
| Skipping tests | Comprehensive tests |
| Hardcoded values | Externalize configuration |
| Force push to main | Rebase instead of merge |

---

## Review Process

1. CI runs automated checks
2. Maintainers review code
3. Address feedback promptly
4. PR merged when approved

---

## Quick Reference

```bash
# Setup
npm install && npx lefthook install

# Before PR
npm run build && npm run lint && npm run cli:test
```

**Quality over speed** — Write good code, tests, and documentation.

---

# GitHub Action for CLI
Source: https://www.asyncapi.com/docs/tools/cli/github-action.md

# GitHub Action for CLI

This action exposes the [AsyncAPI CLI](https://github.com/asyncapi/cli). It allows you to generate documentation, validate AsyncAPI documents, convert between different AsyncAPI versions and much more. The source code of the action can be found [here](https://github.com/asyncapi/cli/tree/master/github-action)

## Inputs

### `cli_version`

Version of the AsyncAPI CLI you wish to use. You can find all available versions [here](https://github.com/asyncapi/cli/releases). Recommended leave it out of the inputs and use the default value.

**Default** points to the`latest` version.

> [!TIP]
> We recommend to default to `latest` version. This way there is no overhead with the script updating the CLI version. As it takes a lot of time to update the CLI version, we recommend to update it only when you need to use another one for compatibility reasons.

### `command`

Command that you wish to run. You can find all available commands Available commands are:
- `generate` - generates documentation from AsyncAPI document
- `validate` - validates AsyncAPI document
- `optimize` - optimizes AsyncAPI document
- `convert` - converts AsyncAPI document to another version
- `custom` - allows you to run any command that is available in the AsyncAPI CLI. You can find all available commands [here](https://www.asyncapi.com/docs/tools/cli/usage).

**Default** points to `generate` command.

> [!IMPORTANT]
> In case you want to use `custom` command, you need to pass an array of commands to the [`custom_command`](#custom_command) input. Although passing command is not required, it is recommended to pass it to avoid any issues later on.
> For example, if you want to run `asyncapi bundle ./asyncapi.yaml --output final-asyncapi.yaml` you need to pass `"bundle ./asyncapi.yaml --output final-asyncapi.yaml" to the `custom_command` input.

### `custom_command`

In case you want to use `custom` command you need to pass the command that you want to run in this input. You can find all available commands [here](https://www.asyncapi.com/docs/tools/cli/usage). 

**Default** points to '' (empty string).

Sample usage:

```yaml
- name: Generating HTML from my AsyncAPI document
  uses: asyncapi/cli@v2.16.0# You can use any version you want
  with:
    custom_command: bundle ./asyncapi.yaml --output final-asyncapi.yaml
```

> [!CAUTION]
> You have to pass the whole command as a string including the parameters and the command itself.
> It will run like this: `asyncapi <custom_command>`

### `filepath`

Path to the AsyncAPI document that you want to process.   

**Default** expects the AsyncAPI document to be in the root of the repository and named `asyncapi.yaml`.

### `template`

Template for the generator. Official templates are listed here https://github.com/asyncapi/generator#list-of-official-generator-templates. You can pass template as npm package, url to git repository, link to tar file or local template.

**Default** points to `@asyncapi/markdown-template@2.0.0` template.

> [!TIP]
> We recommend to always specify the version of the template to not encounter any issues with the action in case of release of the template that is not compatible with given version of the generator.

### `language`

Specifies the language to be used for the generated models. The value must be a valid language name supported by [modelina](https://github.com/asyncapi/modelina). 

**Default** is not set.

> [!WARNING]
> Either `language` or `template` must be set else an error will be thrown. 
> The action will return an error if the language is not supported by [modelina](https://github.com/asyncapi/modelina).

### `output`

Path to the output directory. Can be used for `generate` and `convert` commands.

**Default** points to `output` directory in the root of the repository.

### `parameters`

The command that you use might support and even require specific parameters to be passed to the CLI for the generation. You can find all available parameters [here](https://www.asyncapi.com/docs/tools/cli/usage).

**Default** points to '' (empty string).

> [!NOTE]
> For template parameters, you need to pass them as `-p <template_parameters>` as can be seen in CLI documentation.

## Example usage

> [!WARNING]
> Using `docker://asyncapi/github-action-for-cli` will not work as expected. This is because the GitHub Actions runner does not pass params to the docker image correctly. This is why we recommend to use `asyncapi/cli` instead.
> However, you don't need to worry as it won't build the image every time. It will pull it from Docker Hub as it is already built there.

### Basic

In case all defaults are fine for you, just add such step:

```yaml
- name: Generating Markdown from my AsyncAPI document
  uses: asyncapi/cli@v2.16.0 # You can use any version you want
```

### Using all possible inputs

In case you do not want to use defaults, you for example want to use different template:

```yaml
- name: Generating HTML from my AsyncAPI document
  uses: asyncapi/cli@v2.16.0 # You can use any version you want
  with:
    command: generate
    filepath: ./docs/api/asyncapi.yaml
    template: "@asyncapi/html-template@0.9.0" #In case of template from npm. Or can use a link.
    output: ./generated-html
    parameters: "-p baseHref=/test-experiment/ sidebarOrganization=byTags"
```
> [!IMPORTANT]
> Note the usage of `-p` in `parameters` input. This is required for template parameters, unlike previous versions of this action as the action includes other commands than just `generate`.

### Example workflow with publishing generated HTML to GitHub Pages

In case you want to validate your asyncapi file first, and also send generated HTML to GitHub Pages this is how full workflow could look like:

```yaml
name: AsyncAPI documents processing

on:
  push:
    branches: [ master ]

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
    #"standard step" where repo needs to be checked-out first
    - name: Checkout repo
      uses: actions/checkout@v2
      
    #In case you do not want to use defaults, you for example want to use different template
    - name: Generating HTML from my AsyncAPI document
      uses: asyncapi/cli@v2.16.0 # You can use any version you want
      with:
        template: '@asyncapi/html-template@0.9.0'  #In case of template from npm, because of @ it must be in quotes
        filepath: docs/api/my-asyncapi.yml
        parameters: -p baseHref=/test-experiment/ sidebarOrganization=byTags #space separated list of key/values
        output: generated-html
      
    #Using another action that takes generated HTML and pushes it to GH Pages
    - name: Deploy GH page
      uses: JamesIves/github-pages-deploy-action@3.4.2
      with:
        ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        BRANCH: gh-pages
        FOLDER: generated-html
```

### Example workflow for generating models

In case you want to use models generated from your AsyncAPI document, you can use this action to generate them and then use them in your workflow. This is how full workflow could look like:

```yaml

name: AsyncAPI documents processing

on:
  push:
    branches: [ master ]

jobs:
  generate-models:
    runs-on: ubuntu-latest
    steps:
    #"standard step" where repo needs to be checked-out first
    - name: Checkout repo
      uses: actions/checkout@v2
      
    - name: Generating models from my AsyncAPI document
      uses: asyncapi/cli@v2.16.0 # You can use any version you want
      with:
        command: generate
        filepath: docs/api/my-asyncapi.yml
        language: typescript
        output: generated-models
```

### Example workflow for validating AsyncAPI document changes

In case you want to validate your AsyncAPI document changes, you can use this action to validate them and then use them in your workflow. This is how full workflow could look like:

```yaml
name: Validate AsyncAPI document

on:
  pull_request:
    branches: [ master ]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
    #"standard step" where repo needs to be checked-out first
    - name: Checkout repo
      uses: actions/checkout@v2
      
    - name: Validating AsyncAPI document
      uses: asyncapi/cli@v2.16.0 # You can use any version you want
      with:
        command: validate
        filepath: docs/api/my-asyncapi.yml
```

## Local dry run

Use following commands to run and test github action locally:

1. Build docker image of github action for cli

  ```bash
    npm run action:docker:build
  ```

2. Execute docker image with proper arguments

  ```bash
    docker run -e GITHUB_WORKSPACE="" --workdir /action  -v "/home/{user}/path/to/repo":"/action" asyncapi/github-action-for-cli  "" "generate" "github-action/test/asyncapi.yml" "@asyncapi/markdown-template@2.0.0" "" "output" "" ""
  ```

Make sure to change the path of the repo and user in the command.

## Troubleshooting

You can enable more log information in GitHub Action by adding `ACTIONS_STEP_DEBUG` secret to repository where you want to use this action. Set the value of this secret to `true` and you''ll notice more debug logs from this action.

---

# Context concept
Source: https://www.asyncapi.com/docs/tools/cli/context.md

# Context concept

## Overview

AsyncAPI CLI provides functionality called `context`. It's purpose is to help to work with AsyncAPI CLI in large projects where you do not have just one service exposing AsyncAPI document, but multiple.

Event driven architecture involves multiple actors, subscribers and publishers. One time you want to validate document **A** and the other time you want to generate models from document **B**. Every time you do it, you need to provide to AsyncAPI CLI the location of the AsyncAPI document, which might be time consuming. You can workaround it with aliases in bash profiles or with other solutions but it is better to use `context` feature, as you can then store it in your repository and share with other team members.

In short it means that for example instead of writing `asyncapi validate /some/folder/my-asyncapi.yml` you can create a context called `myasync` that will be an alias for and point to `/some/folder/my-asyncapi.yml`. This way next time you use the CLI you can do `asyncapi validate myasync`.

## Context File location

You can have a global context for your workstation, and a project specific context.

If your use case is that you work with multiple repositories, you might want to use a global context. The `.asyncapi-cli` context file is then located in your home directory. You can also store your custom `.asyncapi-cli` file in your project with custom configuration. This way when you run `asyncapi config context add` inside your project, the new context is added to the context file under your project.

## How to add context to a project

### Manually
  - Create file `.asyncapi-cli` containing [minimal empty context file](#minimalEmptyContextFile) in:
    - current directory
    - root of current repository
    - user's home directory

### Using CLI's `init` command

`asyncapi config context init [CONTEXT-FILE-PATH]`

Where `[CONTEXT-FILE-PATH]` instructs CLI what directory should the file `.asyncapi-cli` containing [minimal empty context file](#minimalEmptyContextFile) be created in:
  - current directory: `asyncapi config context init .` (default)
  - root of current repository: `asyncapi config context init ./`
  - user's home directory: `asyncapi config context init ~`
  
(if `[CONTEXT-FILE-PATH]` is omitted, empty context file is created in current directory)

Make use of newly created `.asyncapi-cli` by executing command:

`asyncapi config context add [CONTEXT-NAME] [SPEC-FILE-PATH]`

### Setup example in a real project

Below you can see an example of context setup for [Event Driven Flight status notification service](https://github.com/amadeus4dev-examples/amadeus-async-flight-status/tree/ff433b6d320a3a6a2499976cbf0782353bc57c16) of the [Amadeus Airline Platform](https://amadeus.com/en/industries/airlines/airline-platform), with multiple microservices and their AsyncAPI documents.

```bash
# One-time initialization of '.asyncapi-cli' file
(main)$ asyncapi config context init
Initialized context /amadeus-async-flight-status/.asyncapi-cli

# Adding first context
(main)$ asyncapi config context add subscriber subscriber/asyncapi.yaml
Added context "subscriber".
You can set it as your current context: asyncapi config context use subscriber
You can use this context when needed by passing subscriber as a parameter: asyncapi validate subscriber

# Adding more contexts
(main)$ asyncapi config context add notifier notifier/asyncapi.yaml
Added context "notifier".
You can set it as your current context: asyncapi config context use notifier
You can use this context when needed by passing notifier as a parameter: asyncapi validate notifier

(main)$ asyncapi config context add monitor monitor/asyncapi.yaml
Added context "monitor".
You can set it as your current context: asyncapi config context use monitor
You can use this context when needed by passing monitor as a parameter: asyncapi validate monitor

# Setting monitor as default context
(main)$ asyncapi config context use monitor
monitor is set as current

# Now you do not even have to remember the context name, and default 'monitor/asyncapi.yaml' will be validated
(main)$ asyncapi validate
File monitor/asyncapi.yaml is valid but has (itself and/or referenced documents) governance issues.
monitor/asyncapi.yaml
  1:1       warning  asyncapi-defaultContentType      AsyncAPI document should have "defaultContentType" field.
  1:1       warning  asyncapi-id                      AsyncAPI document should have "id" field.
  1:1       warning  asyncapi2-tags                   AsyncAPI object should have non-empty "tags" array.
  1:11  information  asyncapi-latest-version          The latest version of AsyncAPi is not used. It is recommended update to the "2.6.0" version.  asyncapi
  2:6       warning  asyncapi-info-contact            Info object should have "contact" object.                                                     info
 19:15      warning  asyncapi2-operation-operationId  Operation should have an "operationId" field defined.                                         channels.flight/update.subscribe
 26:13      warning  asyncapi2-operation-operationId  Operation should have an "operationId" field defined.                                         channels.flight/queue.publish
✖ 7 problems (0 errors, 6 warnings, 1 info, 0 hints)

# You can now use context name when running AsyncAPI commands, no need to remember file location like 'notifier/asyncapi.yaml'
(main)$ asyncapi validate notifier
File notifier/asyncapi.yaml is valid but has (itself and/or referenced documents) governance issues.
notifier/asyncapi.yaml
  1:1       warning  asyncapi-defaultContentType      AsyncAPI document should have "defaultContentType" field.
  1:1       warning  asyncapi-id                      AsyncAPI document should have "id" field.
  1:1       warning  asyncapi2-tags                   AsyncAPI object should have non-empty "tags" array.
  1:11  information  asyncapi-latest-version          The latest version of AsyncAPi is not used. It is recommended update to the "2.6.0" version.  asyncapi
  2:6       warning  asyncapi-info-contact            Info object should have "contact" object.                                                     info
 18:13      warning  asyncapi2-operation-operationId  Operation should have an "operationId" field defined.                                         channels.flight/update.publish
✖ 6 problems (0 errors, 5 warnings, 1 info, 0 hints)

# Switch default context 
(main)$ asyncapi config context use notifier
notifier is set as current

# List all contexts
(main)$ asyncapi config context list
monitor: monitor/asyncapi.yaml
notifier: notifier/asyncapi.yaml
subscriber: subscriber/asyncapi.yaml
```

## Context File structure

### Fixed Fields

Field Name | Type | Description
---|:---:|---
current | `string` | An optional string value representing one of context names, which is used as default in CLI. Default means you can run CLI commands without providing context name, like `asyncapi validate`, and it will run against the default - `current` - context.
store | [Store Object](#storeObject) | **REQUIRED**. Map of filesystem paths to target AsyncAPI documents.

### <a name="storeObject"></a>Store Object

Map of filesystem paths to target AsyncAPI documents.

**Patterned Fields**

Field Pattern | Type | Description
---|:---:|---
\{contextName\} | `string` | An optional string value representing filesystem path to the target AsyncAPI document.

### <a name="minimalEmptyContextFile"></a>Minimal Empty Context File
Raw JSON:
```
{
  "store": {}
}
```
Stringified JSON:
```
{"store":{}}
```

### Context File Example

Example of a context file for [Event Driven Flight status notification service](https://github.com/amadeus4dev-examples/amadeus-async-flight-status/tree/ff433b6d320a3a6a2499976cbf0782353bc57c16) of the [Amadeus Airline Platform](https://amadeus.com/en/industries/airlines/airline-platform), with multiple microservices and their AsyncAPI documents:
```
{
  "current": "monitor",
  "store": {
    "monitor": "monitor/asyncapi.yaml",
    "notifier": "notifier/asyncapi.yaml",
    "subscriber": "subscriber/asyncapi.yaml"
  }
}
```

## More context related CLI options

All commands for managing contexts are available under `asyncapi config context` [CLI commands group](usage#asyncapi-config-context).

---

# Debugging & Testing Guide
Source: https://www.asyncapi.com/docs/tools/cli/debugging-testing.md

# Debugging & Testing Guide

This guide provides step-by-step instructions for debugging and testing the AsyncAPI CLI. Whether you're fixing a bug, adding a new feature, or understanding existing code, this document will help you navigate the debugging process effectively.

## Table of Contents

- [Project Structure Overview](#project-structure-overview)
- [Setting Up Your Environment](#setting-up-your-environment)
- [Debugging CLI Commands](#debugging-cli-commands)
- [Debugging the API Server](#debugging-the-api-server)
- [Debugging Services](#debugging-services)
- [Writing Tests](#writing-tests)
- [Running Tests](#running-tests)
- [Common Issues & Solutions](#common-issues--solutions)
- [Debugging Tools & Tips](#debugging-tools--tips)

---

## Project Structure Overview

Understanding the codebase structure is essential for effective debugging:

```
src/
├── apps/
│   ├── api/           # REST API server (Express.js)
│   │   ├── controllers/   # API endpoint handlers
│   │   ├── middlewares/   # Request/response middleware
│   │   └── exceptions/    # API error types
│   └── cli/           # CLI application (oclif)
│       ├── commands/      # CLI command implementations
│       └── internal/      # Shared CLI utilities, flags, base classes
├── domains/
│   ├── models/        # Domain models (SpecificationFile, Context, etc.)
│   └── services/      # Business logic services
├── errors/            # Custom error classes
├── utils/             # Utility functions
└── interfaces/        # TypeScript interfaces

test/
├── fixtures/          # Test data files (AsyncAPI specs, etc.)
├── helpers/           # Test utilities
├── integration/       # Integration tests for CLI commands
└── unit/              # Unit tests for services and controllers
    ├── controllers/   # API controller tests
    ├── services/      # Service layer tests
    └── utils/         # Utility function tests
```

---

## Setting Up Your Environment

### 1. Install Dependencies

```bash
npm install
```

### 2. Build the Project

```bash
npm run build
```

### 3. Set Up Environment Variables for Debugging

Create a `.env` file or export variables:

```bash
# Enable development mode (verbose logging)
export NODE_ENV=development

# Disable analytics during testing
export TEST=1

# Set custom context file for testing
export CUSTOM_CONTEXT_FILENAME="test.asyncapi-cli"
export CUSTOM_CONTEXT_FILE_LOCATION=""
```

---

## Debugging CLI Commands

### Method 1: Using `bin/run` (Development Mode)

The `bin/run` script runs the CLI in development mode with TypeScript directly:

```bash
# Run any command with debugging
./bin/run validate ./path/to/asyncapi.yml

# With verbose output
DEBUG=* ./bin/run validate ./path/to/asyncapi.yml
```

### Method 2: Using Node.js Inspector

```bash
# Start with Node inspector
node --inspect-brk ./bin/run validate ./path/to/asyncapi.yml

# Then open Chrome DevTools at: chrome://inspect
```

### Method 3: VS Code Debugging

Create `.vscode/launch.json`:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug CLI Command",
      "program": "${workspaceFolder}/bin/run",
      "args": ["validate", "./test/fixtures/specification.yml"],
      "env": {
        "NODE_ENV": "development",
        "TEST": "1"
      },
      "sourceMaps": true,
      "outFiles": ["${workspaceFolder}/lib/**/*.js"]
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current Test File",
      "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
      "args": [
        "--require", "ts-node/register",
        "--require", "tsconfig-paths/register",
        "--timeout", "100000",
        "${file}"
      ],
      "env": {
        "NODE_ENV": "development",
        "TEST": "1",
        "CUSTOM_CONTEXT_FILENAME": "test.asyncapi-cli"
      },
      "sourceMaps": true
    }
  ]
}
```

### Method 4: Adding Console Logs

For quick debugging, add logs in command files:

```typescript
// In src/apps/cli/commands/validate.ts
async run() {
  const { args, flags } = await this.parse(Validate);
  
  // Debug: Log parsed arguments
  console.log('DEBUG - Args:', JSON.stringify(args, null, 2));
  console.log('DEBUG - Flags:', JSON.stringify(flags, null, 2));
  
  // ... rest of the command
}
```

---

## Debugging the API Server

### Starting the API in Development Mode

```bash
# Start with hot-reload
npm run api:dev

# Or manually with debugging
NODE_ENV=development DEBUG=* node ./lib/apps/api/server.js
```

### Testing API Endpoints

```bash
# Validate endpoint
curl -X POST http://localhost:3000/v1/validate \
  -H "Content-Type: application/json" \
  -d '{"asyncapi": "asyncapi: 3.1.0\ninfo:\n  title: Test\n  version: 1.0.0\nchannels: {}"}'

# Parse endpoint
curl -X POST http://localhost:3000/v1/parse \
  -H "Content-Type: application/json" \
  -d '{"asyncapi": "..."}'
```

### Debugging API Controllers

Add middleware logging:

```typescript
// In src/apps/api/middlewares/logger.middleware.ts
// Logs are automatically enabled in development mode
```

---

## Debugging Services

### ValidationService

The `ValidationService` handles document validation. To debug:

```typescript
// Test the service directly
import { ValidationService } from '@services/validation.service';
import { load } from '@models/SpecificationFile';

async function debugValidation() {
  const service = new ValidationService();
  const specFile = await load('./path/to/spec.yml');
  
  const result = await service.validateDocument(specFile, {
    'fail-severity': 'error',
    'log-diagnostics': true,
  });
  
  console.log('Validation Result:', JSON.stringify(result, null, 2));
}
```

### ConversionService

```typescript
import { ConversionService } from '@services/convert.service';
import { load } from '@models/SpecificationFile';

async function debugConversion() {
  const service = new ConversionService();
  const specFile = await load('./path/to/spec.yml');
  
  const result = await service.convertDocument(specFile, {
    format: 'asyncapi',
    'target-version': '3.0.0',
    perspective: 'server',
  });
  
  console.log('Conversion Result:', JSON.stringify(result, null, 2));
}
```

### GeneratorService

```typescript
import { GeneratorService } from '@services/generator.service';

async function debugGenerator() {
  const service = new GeneratorService();
  // Add your debugging logic
}
```

---

## Writing Tests

### Test File Naming Convention

- Unit tests: `test/unit/<category>/<name>.test.ts`
- Integration tests: `test/integration/<command>.test.ts`

### Unit Test Structure

```typescript
// test/unit/services/my-service.test.ts
import { expect } from 'chai';
import { MyService } from '../../../src/domains/services/my.service';

describe('MyService', () => {
  let service: MyService;

  beforeEach(() => {
    service = new MyService();
  });

  describe('methodName', () => {
    it('should do something when given valid input', async () => {
      // Arrange
      const input = { /* test data */ };
      
      // Act
      const result = await service.methodName(input);
      
      // Assert
      expect(result.success).to.be.true;
      expect(result.data).to.exist;
    });

    it('should handle errors gracefully', async () => {
      // Arrange
      const invalidInput = null;
      
      // Act
      const result = await service.methodName(invalidInput);
      
      // Assert
      expect(result.success).to.be.false;
      expect(result.error).to.include('error message');
    });
  });
});
```

### Integration Test Structure (CLI Commands)

```typescript
// test/integration/mycommand.test.ts
import { expect, test } from '@oclif/test';
import path from 'path';

const validSpec = path.resolve(__dirname, '../fixtures/specification.yml');
const invalidSpec = path.resolve(__dirname, '../fixtures/specification-invalid.yml');

describe('mycommand', () => {
  describe('with valid input', () => {
    test
      .stdout()
      .command(['mycommand', validSpec])
      .it('should succeed with valid specification', (ctx) => {
        expect(ctx.stdout).to.contain('Success');
      });
  });

  describe('with invalid input', () => {
    test
      .stderr()
      .command(['mycommand', invalidSpec])
      .exit(1)
      .it('should fail with invalid specification', (ctx) => {
        expect(ctx.stderr).to.contain('Error');
      });
  });

  describe('with flags', () => {
    test
      .stdout()
      .command(['mycommand', validSpec, '--output', 'result.json'])
      .it('should handle output flag', (ctx) => {
        expect(ctx.stdout).to.contain('saved');
      });
  });
});
```

### API Controller Test Structure

```typescript
// test/unit/controllers/my.controller.test.ts
import request from 'supertest';
import { App } from '../../../src/apps/api/app';
import { MyController } from '../../../src/apps/api/controllers/my.controller';

describe('MyController', () => {
  let app: App;

  beforeEach(async () => {
    app = new App([new MyController()]);
    await app.init();
  });

  describe('[POST] /v1/myendpoint', () => {
    it('should return 200 with valid input', async () => {
      return request(app.getServer())
        .post('/v1/myendpoint')
        .send({ data: 'valid' })
        .expect(200)
        .then((response) => {
          expect(response.body).to.have.property('result');
        });
    });

    it('should return 422 with invalid input', async () => {
      return request(app.getServer())
        .post('/v1/myendpoint')
        .send({})
        .expect(422);
    });
  });
});
```

### Using Test Fixtures

```typescript
import path from 'path';
import { load } from '@models/SpecificationFile';

// Load test fixtures
const fixturesPath = path.resolve(__dirname, '../../fixtures');

async function loadTestSpec(filename: string) {
  return load(path.join(fixturesPath, filename));
}

// Usage in tests
describe('MyTest', () => {
  it('should handle v3 spec', async () => {
    const spec = await loadTestSpec('specification-v3.yml');
    // ... test logic
  });
});
```

---

## Running Tests

### Run All Tests

```bash
npm test
```

This runs optimizer Jest (`optimizer:test`), then CLI Mocha (`cli:test`), then the GitHub Action tests.
PR CI (`.github/workflows/if-nodejs-pr-testing.yml`) and the Changesets release workflow both call `npm test`.

### Run Only Optimizer Tests

```bash
npm run optimizer:test
```

### Run Only CLI Tests

```bash
npm run cli:test
```

### Run Only Unit Tests

```bash
npm run unit:test
```

### Run a Single Test File

```bash
npm run test:one -- test/integration/validate.test.ts
```

### Run Tests with Coverage

```bash
npm run cli:test
# Coverage report is generated in ./coverage/
```

### Run Tests in Watch Mode (Development)

```bash
# Using nodemon for file watching
npm run dev

# Then run tests manually when needed
npm run unit:test
```

---

## Common Issues & Solutions

### Issue 1: "Cannot find module '@utils/proxy'"

**Cause:** TypeScript path aliases not resolved.

**Solution:**
```bash
# Rebuild the project
npm run build
```

### Issue 2: Permission Denied Errors

**Cause:** Files created by root or different user.

**Solution:**
```bash
# Fix permissions
sudo chown -R $(whoami) ./lib ./node_modules ./.nyc_output
```

### Issue 3: Test Context File Conflicts

**Cause:** Tests using the same context file as development.

**Solution:**
```bash
# Set test-specific context file
export CUSTOM_CONTEXT_FILENAME="test.asyncapi-cli"
export CUSTOM_CONTEXT_FILE_LOCATION=""
```

### Issue 4: "ECONNREFUSED" in API Tests

**Cause:** API server not started or wrong port.

**Solution:**
```bash
# Ensure the app is initialized in tests
const app = new App([new MyController()]);
await app.init();  // Don't forget this!
```

### Issue 5: Async Test Timeouts

**Cause:** Default timeout too short for async operations.

**Solution:**
```typescript
// Increase timeout for specific tests
it('should handle slow operation', async function() {
  this.timeout(30000);  // 30 seconds
  // ... test logic
});
```

### Issue 6: ESLint Errors in Tests

**Cause:** Using testing patterns that trigger lint rules.

**Solution:**
```typescript
// Add eslint disable for specific patterns
/* eslint-disable @typescript-eslint/no-unused-expressions */
expect(result).to.be.true;  // Chai assertions
```

---

## Debugging Tools & Tips

### 1. Enable Verbose Logging

```bash
DEBUG=* ./bin/run validate spec.yml
```

### 2. Use Node.js Inspector

```bash
node --inspect-brk ./bin/run validate spec.yml
# Open chrome://inspect in Chrome
```

### 3. Print Stack Traces

```typescript
try {
  // risky operation
} catch (error) {
  console.error('Stack trace:', error.stack);
  throw error;
}
```

### 4. Use TypeScript Source Maps

Ensure `tsconfig.json` has:
```json
{
  "compilerOptions": {
    "sourceMap": true
  }
}
```

### 5. Debug Parser Output

```typescript
import { Parser } from '@asyncapi/parser';

const parser = new Parser();
const { document, diagnostics } = await parser.parse(specContent);

console.log('Parsed document:', JSON.stringify(document?.json(), null, 2));
console.log('Diagnostics:', JSON.stringify(diagnostics, null, 2));
```

### 6. Inspect Service Results

All services return a `ServiceResult` type:
```typescript
interface ServiceResult<T> {
  success: boolean;
  data?: T;
  error?: string;
}

// Always check both success and data
if (result.success && result.data) {
  console.log('Success:', result.data);
} else {
  console.log('Error:', result.error);
}
```

### 7. Test Commands Interactively

```bash
# Build and run immediately
npm run build && ./bin/run validate ./test/fixtures/specification.yml
```

---

## Quick Reference

| Task | Command |
|------|---------|
| Build project | `npm run build` |
| Run all tests | `npm test` |
| Run optimizer tests | `npm run optimizer:test` |
| Run CLI tests | `npm run cli:test` |
| Run unit tests | `npm run unit:test` |
| Run single test | `npm run test:one -- <path>` |
| Lint code | `npm run lint` |
| Fix lint issues | `npm run lint:fix` |
| Start API dev server | `npm run api:dev` |
| Debug CLI command | `./bin/run <command> <args>` |
| Debug with inspector | `node --inspect-brk ./bin/run <command>` |

---

## Getting Help

If you're still stuck:

1. Check existing tests for similar functionality
2. Look at the error messages and stack traces
3. Search for similar issues in the [GitHub Issues](https://github.com/asyncapi/cli/issues)
4. Ask in the [AsyncAPI Slack](https://asyncapi.com/slack-invite) `#tooling` channel

---

# Metrics Collection
Source: https://www.asyncapi.com/docs/tools/cli/metrics_collection.md

# Metrics Collection

# Metrics collection guideline

AsyncAPI **anonymously** tracks command executions to improve the specification and tools, ensuring no sensitive data reaches our servers. It aids in comprehending how AsyncAPI tools are used and adopted, facilitating ongoing improvements to our specifications and tools.

Even though metrics collection is enabled by default, you can always [disable tracking](#how-to-disable-tracking) if you want to.

## What we collect
We are collecting the following metrics:

- `asyncapi_adoption.action.invoked`:
With this metric we are tracking the command executed on the CLI as soon as the command is invoked, so it has already been executed but not finished yet. We just want to know which commands are used, regardless they have failed or succeeded.

Example of the data collected by this metric when the `validate` command has been executed:
```
asyncapi_adoption.action.invoked        COUNTER { action: 'validate' }  1
```

- `asyncapi_adoption.action.finished`:
This metric tracks the command executed once it has already finished, carrying the result of the execution and some metadata based on the AsyncAPI document in place.

Example for `validate` command successfully executed and finished:
```
asyncapi_adoption.action.finished       COUNTER {
  validation_result: 'valid',
  success: true,
  asyncapi_version: '2.6.0',
  asyncapi_servers: 2,
  asyncapi_channels: 4,
  asyncapi_messages: 3,
  asyncapi_operations_send: 3,
  asyncapi_operations_receive: 1,
  asyncapi_schemas: 52,
  action: 'validate'
  }       1
```

## Where the data is stored
We are making use of [New Relic API](https://docs.newrelic.com/docs/apis/intro-apis/introduction-new-relic-apis/#rest-api) to send the metrics collected to _New Relic_ servers, where they are stored, and finally visualized on the AsyncAPI website.

Metrics won't be collected in CI environments, or when the "CI" env variable is set up to "true".

The analytics config file will be store by default at your home directory. In case you prefer to change the file path then you should set the `ASYNCAPI_METRICS_CONFIG_PATH` env var to any specific path value when running any command. For instance:
````
ASYNCAPI_METRICS_CONFIG_PATH=/tmp/.asyncapi-analytics asyncapi config analytics --status
````

## How to disable tracking
To disable tracking, please run the following command:  
`asyncapi config analytics --disable`

Once disabled, if you want to enable tracking back again then run:  
`asyncapi config analytics --enable`

In case you do not know the current status of analytics, then you can append the "--status" flag to be aware of it:
`asyncapi config analytics --status`

Remember that keeping this tracking enabled will help AsyncAPI community to provide better specifications and tools in the future.

---

# Overview
Source: https://www.asyncapi.com/docs/guides.md

# Overview

## Guides: Teaches AsyncAPI's capabilities at a high level

Welcome to AsyncAPI **Guides**! Our Guides section teaches AsyncAPI's capabilities and features at a high level.

> **Remember**
>
> ## Contribute to AsyncAPI Guides
> Code isn't the only way to contribute to OSS; Dev Docs are a **huge** help that benefit the entire OSS ecosystem. At AsyncAPI, we value Doc contributions as much as every other type of contribution. ❤️
> 
> To get started as a Docs contributor:
> 
> 1. Familiarize yourself with our [project's Contribution Guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md).
> 2. Head over to our [AsyncAPI Docs Board](https://github.com/orgs/asyncapi/projects/12).
> 3. Pick an issue you would like to contribute to and leave a comment introducing yourself. This is also the perfect place to leave any questions you may have on how to get started.
> 4. If there is no work done in that Docs issue yet, feel free to open a PR and get started!
> 
> ### Docs contributor questions
> 
> Do you have a question about contributing to the docs or an issue with your pull request? [Join our Slack community](https://www.asyncapi.com/slack-invite) and ask in the `#docs` channel; the maintainers will get back to you.

---

# Validate AsyncAPI documents
Source: https://www.asyncapi.com/docs/guides/validate.md

# Validate AsyncAPI documents

> In this guide, you'll learn multiple ways to validate AsyncAPI documents.

## Introduction
In this guide, you'll learn multiple ways to validate AsyncAPI documents.

## Validate AsyncAPI documents
Validating an AsyncAPI document can mean one of two things: 
- Validation against the specification.
- Validation against the best practices or company governance rules also known as linting.

### Validate against specification
Validating against the specification ensures that every content of the document is written in accordance with the AsyncAPI specification. Several tool options exist for validating against the specification: _AsyncAPI Studio_, _AsyncAPI CLI_, and _Parsers_.

#### AsyncAPI Studio validation 
[AsyncAPI Studio](https://studio.asyncapi.com/) provides a visual and easy way to validate your AsyncAPI documents against the specification. (It uses the [AsyncAPI JavaScript parser](https://github.com/asyncapi/parser-js) behind the scenes to perform syntax checks and validate documents.)

Errors in your document are highlighted with a red underline, showing which lines are invalid. The `Diagnostics` section also provides feedback, allowing you to further troubleshoot with detailed error messages. When a document is invalid, it provides the following error: `Empty or invalid document please fix errors / define AsyncAPI document`.

#### AsyncAPI CLI validation 
The following [AsyncAPI CLI](https://github.com/asyncapi/cli#installation) command validates AsyncAPI documents in your local computer or in CI/CD automation:

 ```
 asyncapi validate asyncapi.yaml
 ```

> **Remember**
>
> You can also open AsyncAPI Studio from the CLI by running the command `asyncapi start studio`.

#### Parsers (code) validation 
AsyncAPI provides official [JavaScript](https://github.com/asyncapi/parser-js) and [Go](https://github.com/asyncapi/parser-go) parsers for validating AsyncAPI documents. 

> **Remember**
>
> Official parsers use <a href='https://github.com/asyncapi/spec-json-schemas/'>JSON Schema</a> created for AsyncAPI specification. JSON Schema is not enough to fully validate AsyncAPI documents. Learn more about <a href='https://github.com/asyncapi/spec-json-schemas#custom-validation-needs'>custom JSON Schemas validation needs</a>. Official JavaScript parser supports and validates these special needs.
> 
> Take it into account if you're thinking about writing your own parser using official JSON Schema.

### Validation against best practices or company governance rules
Now let's discuss options for validating against best practices or company governance rules, also known as **linting**. When various teams use AsyncAPI, you want to ensure they follow the same rules and are consistent across the organization. It is not enough to validate AsyncAPI documents against official specification rules. 

> **Remember**
>
> Let's discuss an example. While the `summary` property is optional in an AsyncAPI document, you could choose to require it for your organization. You would then implement a solution that enables you to enforce internal rules on AsyncAPI documents' providers.

One way to do this is to use the **Spectral** open-source tool. It enables you to define company-specific rules that you can use internally.  

To get started:
1. Install [Spectral](https://meta.stoplight.io/docs/spectral/b8391e051b7d8-installation). 
2. Create a file named `.spectral.yaml` to begin writing your API description and document rules. 
    Example:
    ```yaml
    rules:
      # add your own rules here
    ```

3. Create and add your own custom ruleset:

   ```yaml
   rules:
     valid-document-version:
       message: Application title must start with upper case
       severity: error
       given: "$.info"
       then:
         - field: title
           function: pattern
           functionOptions:
             match: "^[A-Z]"
   ```

4. After setting up Spectral and creating custom rules following steps 1 - 3, validate your AsyncAPI document using this Spectral CLI command:

  ```
    spectral lint asyncapi.yaml
  ```

---

## Additional resources
- [AsyncAPI **Studio READme**](https://github.com/asyncapi/studio#readme)
- [AsyncAPI **CLI READme**](https://github.com/asyncapi/cli#readme)
- [AsyncAPI **JavaScript Parsers READme**](https://github.com/asyncapi/parser-js#readme) 
- [AsyncAPI **Go Parsers READme**](https://github.com/asyncapi/parser-go#readme)

---

# Message validation
Source: https://www.asyncapi.com/docs/guides/message-validation.md

# Message validation

> This guide explains different use cases for AsyncAPI message validation.

## Introduction
This guide explains different concepts of validating messages in event-driven communication. You will also learn what role AsyncAPI documents play in validation.

## Message validation
To understand message validation in event-driven communication, we must first understand the basic components involved.
- Producer: responsible for producing messages.
- Consumer: responsible for getting the producer's messages.
- Broker: acts as a bridge between the consumer and the producer because messages travel through the broker.

Message validation can occur in different places in your system. This guide highlights three of those:
- Both producers and consumers can do validation internally during runtime.
- API Gateway can handle message validation.
- Validation of messages can be a native solution implemented by the Schema Registry.
Because consumers and producers cannot communicate directly, the AsyncAPI file dictates what should be included in the payload when a service produces a message. The AsyncAPI document also tells the consumer about the message's properties.
Let's further break down how validation works for all.

### Runtime validation
Messages produced and consumed are both required for runtime message validation. The AsyncAPI document should include descriptions of payload schemas so that you can read them in your application and validate messages that are consumed and produced by the application.

Before messages reach the consumer, runtime validation ensures that any errors are resolved and valid messages are sent to your application.

An example implementation of message validation in runtime is the [asyncapi-validator](https://github.com/WaleedAshraf/asyncapi-validator) library that enables you to validate messages produced/consumed in your application against schemas provided in your AsyncAPI document.
Check out the [message validation in the runtime](https://www.asyncapi.com/docs/tutorials/message-validation) tutorial if you want to get your hands dirty with message validation. 

```mermaid
graph TD
    subgraph Producer
    G[Message produced] -->|Message| B{Is Message valid?}
    B -->|No| A[Logs]
    end
    B -->|Yes| C[Broker]
    C -->|Message| E{Is Message valid?}
    subgraph Consumer
    E -->|No| F[Logs]
    E -->|Yes| H[Message consumed]
    end
```

### Gateway validation
A gateway intercepts all incoming messages and routes them through the middleware and handler pipelines. The gateway sits between the producer and the broker. First, the messages are routed through the gateway, and then the gateway determines whether the message is valid. If the message is invalid, it displays an error and is not forwarded to the broker.

An example implementation of message validation in a gateway is the [AsyncAPI gateway](https://github.com/asyncapi/event-gateway). It intercepts all incoming messages moving them into a pipeline of middlewares and handlers such as message validation. You can use a Kafka consumer/producer[(kcat)](https://github.com/edenhill/kcat), a broker, and a simple WebSocket to run the AsyncAPI gateway in your machine.
Check out an [AsyncAPI file demo with Studio](https://studio.asyncapi.com/?url=https://raw.githubusercontent.com/asyncapi/event-gateway/master/deployments/k8s/event-gateway-demo/event-gateway-demo.asyncapi.yaml) to learn more about how an AsyncAPI file can be used in gateway validation.

> **Remember**
>
> Currently, only the Kafka protocol is supported.

```mermaid
graph TD
    PR[Producer]-- Message --- EG[AsyncAPI Event-Gateway]
    EG -- Message --- EGV{Is Message valid?}
    EGV -->|Yes| BR[Broker]
    EGV --- |No| INV{Fail when invalid?}
    INV -->|Yes| ERR[/Fail/] -- Produce request errored --> PR
    INV -->|No| BR
```
The AsyncAPI document is important because payload schemas are taken from it, and messages are validated against it in your application.
You can spin up the AsyncAPI gateway using an AsyncAPI file. All the messages are forwarded to a WebSocket endpoint; if the message/payload is invalid, it includes a validation error message.

### Schema Registry validation
Producers and consumers do not communicate with each other directly; rather, information transfer happens via Kafka. At the same time, the consumer still needs to know the type of data the producer is sending. Imagine if the producer starts sending bad data to Kafka or if the data type of your data gets changed. We need a way to have a common data type that must be agreed upon.

This is where Schema Registry comes into play. It is an application that runs outside your Kafka protocol and handles schema distribution to producers and consumers by storing a copy of the schema in its local cache and validating them in Kafka.

```mermaid
sequenceDiagram
Producer ->> Schema Registry: Register/checks message schema
Schema Registry ->> Producer: Return registration result

Producer ->> Kafka: Publish message
Kafka ->> Consumer: Receives message
Consumer ->> Schema Registry: Validate message schema
Schema Registry ->> Consumer: Return validation result
```

With the Schema Registry in place, the producer first talks to the Schema Registry and checks if the schema of the message it wants to send is available before sending it to the broker. If it cannot locate the schema, it registers it in the Schema Registry. Then the producer sends a message to the broker prefixed with a unique schema ID. When the consumer processes this message, it will communicate with the Schema Registry using the schema ID obtained from the producer. If there is a schema mismatch, the Schema Registry will throw an error, informing the producer that it violates the schema agreement.

AsyncAPI is not directly involved in validation based on the Schema Registry. The good thing is that you do not have to duplicate schemas in your AsyncAPI document stored in Schema Registry. You can reference schemas from Schema Registry in your AsyncAPI documents.
Here's an example of an AsyncAPI document where you can see both `schemaFormat` and `payload` referenced from the Schema Registry:
```yml
asyncapi: 3.1.0
info:
  title: Example with Avro
  version: 0.1.0

channels:
  example:
    address: 'example'
    messages:
      avroMessage:
        payload:
          schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
          schema:
            $ref: 'https://raw.githubusercontent.com/asyncapi/website/20a31a0396b41dd24b1bac877ab7ce3f58037c28/public/resources/casestudies/adeo/CostingRequestPayload.avsc'

operations:
  onMessage:
    action: receive
    channel:
      $ref: '#/channels/example'
```

---

---

# Overview
Source: https://www.asyncapi.com/docs/reference.md

# Overview

## Reference: AsyncAPI Specification

Welcome to AsyncAPI **Reference**! Our Reference section documents the AsyncAPI specification.  

> **Remember**
>
> ## Contribute to the AsyncAPI Reference section
> Code isn't the only way to contribute to OSS; Dev Docs are a **huge** help that benefit the entire OSS ecosystem. At AsyncAPI, we value Doc contributions as much as every other type of contribution. ❤️
> 
> To get started as a Docs contributor:
> 
> 1. Familiarize yourself with our [project's Contribution Guide](https://github.com/asyncapi/community/blob/master/CONTRIBUTING.md) and our [Code of Conduct](https://github.com/asyncapi/.github/blob/master/CODE_OF_CONDUCT.md).
> 2. Head over to our [AsyncAPI Docs Board](https://github.com/orgs/asyncapi/projects/12).
> 3. Pick an issue you would like to contribute to and leave a comment introducing yourself. This is also the perfect place to leave any questions you may have on how to get started.
> 4. If there is no work done in that Docs issue yet, feel free to open a PR and get started!
> 
> ### Docs contributor questions
> 
> Do you have a question about contributing to the docs or an issue with your pull request? [Join our Slack community](https://www.asyncapi.com/slack-invite) and ask in the `#docs` channel; the maintainers will get back to you.

---

# 3.1.0
Source: https://www.asyncapi.com/docs/reference/specification/v3.1.0.md

# 3.1.0

# AsyncAPI Specification

## Attribution

Part of this content has been taken from the great work done by the folks at the [OpenAPI Initiative](https://openapis.org).

### Version 3.1.0

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

The AsyncAPI Specification is licensed under [The Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).

## Introduction

The AsyncAPI Specification is a project used to describe message-driven APIs in a machine-readable format. It’s protocol-agnostic, so you can use it for APIs that work over any protocol (e.g., AMQP, MQTT, WebSockets, Kafka, STOMP, HTTP, Mercure, etc).

The AsyncAPI Specification defines a set of fields that can be used in an AsyncAPI document to describe an [application](#definitionsApplication)'s API. The document may reference other files for additional details or shared fields, but it is typically a single, primary document that encapsulates the API description.

The AsyncAPI document SHOULD describe the operations an [application](#definitionsApplication) performs. For instance, consider the following AsyncAPI definition snippet:

```yaml
channels:
  userSignedUp:
    # ...(redacted for brevity)
operations:
  onUserSignedUp:
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
```

It means that the [application](#definitionsApplication) will receive messages from  the `userSignedUp` [channel](#definitionsChannel).

**The AsyncAPI specification does not assume any kind of software topology, architecture or pattern.** Therefore, a server MAY be a message broker, a web server or any other kind of computer program capable of sending and/or receiving data. However, AsyncAPI offers a mechanism called "bindings" that aims to help with more specific information about the protocol.

It's NOT RECOMMENDED to derive a [receiver](#definitionsReceiver) AsyncAPI document from a [sender](#definitionsSender) one or vice versa. There are no guarantees that the channel used by an application to receive messages will be the same channel where another application is sending them. Also, certain fields in the document like `summary`, `description`, and the id of the operation might stop making sense. For instance, given the following receiver snippet:

```yaml
operations:
  onUserSignedUp:
    summary: On user signed up.
    description: Event received when a user signed up on the product.
    action: receive
    channel:
      $ref: '#/channels/userSignedUp'
```

We can't automatically assume that an _opposite_ application exists by simply replacing `receive` with `send`:

```yaml
operations:
  onUserSignedUp: # <-- This doesn't make sense now. Should be something like sendUserSignedUp.
    summary: On user signed up. # <-- This doesn't make sense now. Should say something like "Sends a user signed up event".
    description: Event received when a user signed up on the product. # <-- This doesn't make sense now. Should speak about sending an event, not receiving it.
    action: send
    channel:
      $ref: '#/channels/userSignedUp'
```

Aside from the issues mentioned above, there may also be infrastructure configuration that is not represented here. For instance, a system may use a read-only channel for receiving messages, a different one for sending them, and an intermediary process that will forward messages from one channel to the other.

## <a name="definitions"></a>Definitions

### <a name="definitionsServer"></a>Server

A server MAY be a message broker that is capable of sending and/or receiving between a [sender](#definitionsSender) and [receiver](#definitionsReceiver). A server MAY be a service with WebSocket API that enables message-driven communication between browser-to-server or server-to-server.

### <a name="definitionsApplication"></a>Application

An application is any kind of computer program or a group of them. It MUST be a [sender](#definitionsSender), a [receiver](#definitionsReceiver), or both. An application MAY be a microservice, IoT device (sensor), mainframe process, message broker, etc. An application MAY be written in any number of different programming languages as long as they support the selected [protocol](#definitionsProtocol). An application MUST also use a protocol supported by the [server](#definitionsServer) in order to connect and exchange [messages](#definitionsMessage), or expose the protocol described in the AsyncAPI document.

### <a name="definitionsSender"></a>Sender

A sender is a type of application, that is sending [messages](#definitionsMessage) to [channels](#definitionsChannel). A sender MAY send to multiple channels depending on the [server](#definitionsServer), protocol, and use-case pattern.

### <a name="definitionsReceiver"></a>Receiver

A receiver is a type of application that is receiving [messages](#definitionsMessage) from [channels](#definitionsChannel). A receiver MAY receive from multiple channels depending on the [server](#definitionsServer), protocol, and the use-case pattern. A receiver MAY forward a received message further without changing it. A receiver MAY act as a consumer and react to the message. A receiver MAY act as a processor that, for example, aggregates multiple messages in one and forwards them.

### <a name="definitionsMessage"></a>Message

A message is the mechanism by which information is exchanged via a channel between [servers](#definitionsServer) and applications. A message MAY contain a payload and MAY also contain headers. The headers MAY be subdivided into [protocol](#definitionsProtocol)-defined headers and header properties defined by the application which can act as supporting metadata. The payload contains the data, defined by the application, which MUST be serialized into a format (JSON, XML, Avro, binary, etc.). Since a message is a generic mechanism, it can support multiple interaction patterns such as event, command, request, or response.

### <a name="definitionsChannel"></a>Channel

A channel is an addressable component, made available by the [server](#definitionsServer), for the organization of [messages](#definitionsMessage). [Sender](#definitionsSender) applications send messages to channels and [receiver](#definitionsReceiver) applications receive messages from channels. [Servers](#definitionsServer) MAY support many channel instances, allowing messages with different content to be addressed to different channels. Depending on the [server](#definitionsServer) implementation, the channel MAY be included in the message via protocol-defined headers.

### <a name="definitionsProtocol"></a>Protocol

A protocol is the mechanism (wireline protocol or API) by which [messages](#definitionsMessage) are exchanged between the application and the [channel](#definitionsChannel). Example protocols include, but are not limited to, AMQP, HTTP, JMS, Kafka, Anypoint MQ, MQTT, Solace, STOMP, Mercure, WebSocket, Google Pub/Sub, Pulsar, ROS 2.  

### <a name="definitionsBindings"></a>Bindings

A "binding" (or "protocol binding") is a mechanism to define protocol-specific information. Therefore, a protocol binding MUST define protocol-specific information only.

## <a name="specification"></a>Specification

### <a name="format"></a>Format

The files describing the message-driven API in accordance with the AsyncAPI Specification are represented as JSON objects and conform to the JSON standards.
YAML, being a superset of JSON, can be used as well to represent a A2S (AsyncAPI Specification) file.

For example, if a field is said to have an array value, the JSON array representation will be used:

```yaml
{
   "field" : [...]
}
```

While the API is described using JSON it does not impose a JSON input/output to the API itself.

All field names in the specification are **case sensitive**.

The schema exposes two types of fields.
Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name.
Patterned fields can have multiple occurrences as long as each has a unique name.

In order to preserve the ability to round-trip between YAML and JSON formats, YAML version [1.2](https://www.yaml.org/spec/1.2/spec.html) is recommended along with some additional constraints:

- Tags MUST be limited to those allowed by the [JSON Schema ruleset](https://www.yaml.org/spec/1.2/spec.html#id2803231)
- Keys used in YAML maps MUST be limited to a scalar string, as defined by the YAML Failsafe schema ruleset

### <a name="file-structure"></a>File Structure

An AsyncAPI document MAY be made up of a single document or be divided into multiple,
connected parts at the discretion of the author. In the latter case, [Reference Objects](#referenceObject) are used.

It is important to note that everything that is defined in an AsyncAPI document MUST be used by the implemented [Application](#definitionsApplication), with the exception of the [Components Object](#componentsObject). Everything that is defined inside the Components Object represents a resource that MAY or MAY NOT be used by the implemented [Application](#definitionsApplication).

By convention, the AsyncAPI Specification (A2S) file is named `asyncapi.json` or `asyncapi.yaml`.

### <a name="absolute-urls"></a>Absolute URLs

Unless specified otherwise, all properties that are absolute URLs are defined by [RFC3986, section 4.3](https://datatracker.ietf.org/doc/html/rfc3986#section-4.3).

### <a name="schema"></a>Schema

#### <a name="A2SObject"></a>AsyncAPI Object

This is the root document object for the API specification.
It combines resource listing and API declaration together into one document.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="A2SAsyncAPI"></a>asyncapi | [AsyncAPI Version String](#A2SVersionString) | **REQUIRED.** Specifies the AsyncAPI Specification version being used. It can be used by tooling Specifications and clients to interpret the version. The structure shall be `major`.`minor`.`patch`, where `patch` versions _must_ be compatible with the existing `major`.`minor` tooling. Typically patch versions will be introduced to address errors in the documentation, and tooling should typically be compatible with the corresponding `major`.`minor` (1.0.*). Patch versions will correspond to patches of this document.
<a name="A2SId"></a>id | [Identifier](#A2SIdString) | Identifier of the [application](#definitionsApplication) the AsyncAPI document is defining.
<a name="A2SInfo"></a>info | [Info Object](#infoObject) | **REQUIRED.** Provides metadata about the API. The metadata can be used by the clients if needed.
<a name="A2SServers"></a>servers | [Servers Object](#serversObject) | Provides connection details of servers.
<a name="A2SDefaultContentType"></a>defaultContentType | [Default Content Type](#defaultContentTypeString) | Default content type to use when encoding/decoding a message's payload.
<a name="A2SChannels"></a>channels | [Channels Object](#channelsObject) | The channels used by this [application](#definitionsApplication).
<a name="A2SOperations"></a>operations | [Operations Object](#operationsObject) | The operations this [application](#definitionsApplication) MUST implement.
<a name="A2SComponents"></a>components | [Components Object](#componentsObject) | An element to hold various reusable objects for the specification. Everything that is defined inside this object represents a resource that MAY or MAY NOT be used in the rest of the document and MAY or MAY NOT be used by the implemented [Application](#definitionsApplication).

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="A2SVersionString"></a>AsyncAPI Version String

The version string signifies the version of the AsyncAPI Specification that the document complies to.
The format for this string _must_ be `major`.`minor`.`patch`.  The `patch` _may_ be suffixed by a hyphen and extra alphanumeric characters.

A `major`.`minor` shall be used to designate the AsyncAPI Specification version, and will be considered compatible with the AsyncAPI Specification specified by that `major`.`minor` version.
The patch version will not be considered by tooling, making no distinction between `1.0.0` and `1.0.1`.

In subsequent versions of the AsyncAPI Specification, care will be given such that increments of the `minor` version should not interfere with operations of tooling developed to a lower minor version. Thus a hypothetical `1.1.0` specification should be usable with tooling designed for `1.0.0`.

#### <a name="A2SIdString"></a>Identifier

This field represents a unique universal identifier of the [application](#definitionsApplication) the AsyncAPI document is defining. It must conform to the URI format, according to [RFC3986](https://tools.ietf.org/html/rfc3986).

It is RECOMMENDED to use a [URN](https://tools.ietf.org/html/rfc8141) to globally and uniquely identify the application during long periods of time, even after it becomes unavailable or ceases to exist.

##### Examples

```json
{
  "id": "urn:example:com:smartylighting:streetlights:server"
}
```

```yaml
id: 'urn:example:com:smartylighting:streetlights:server'
```

```json
{
  "id": "https://github.com/smartylighting/streetlights-server"
}
```

```yaml
id: 'https://github.com/smartylighting/streetlights-server'
```

#### <a name="infoObject"></a>Info Object

The object provides metadata about the API.
The metadata can be used by the clients if needed.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="infoObjectTitle"></a>title | `string` | **REQUIRED.** The title of the application.
<a name="infoObjectVersion"></a>version | `string` | **REQUIRED** Provides the version of the application API (not to be confused with the specification version).
<a name="infoObjectDescription"></a>description | `string` | A short description of the application. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="infoObjectTermsOfService"></a>termsOfService | `string` | A URL to the Terms of Service for the API. This MUST be in the form of an absolute URL.
<a name="infoObjectContact"></a>contact | [Contact Object](#contactObject) | The contact information for the exposed API.
<a name="infoObjectLicense"></a>license | [License Object](#licenseObject) | The license information for the exposed API.
<a name="infoObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for application API documentation control. Tags can be used for logical grouping of applications.
<a name="infoObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation of the exposed API.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Info Object Example

<!-- asyncapi-example-tester:{"name":"Info Object","json_pointer":"/info"} -->
```json
{
  "title": "AsyncAPI Sample App",
  "version": "1.0.1",
  "description": "This is a sample app.",
  "termsOfService": "https://asyncapi.org/terms/",
  "contact": {
    "name": "API Support",
    "url": "https://www.asyncapi.org/support",
    "email": "support@asyncapi.org"
  },
  "license": {
    "name": "Apache 2.0",
    "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
  },
  "externalDocs": {
    "description": "Find more info here",
    "url": "https://www.asyncapi.org"
  },
  "tags": [
    {
      "name": "e-commerce"
    }
  ]
}
```

<!-- asyncapi-example-tester:{"name":"Info Object","json_pointer":"/info"} -->
```yaml
title: AsyncAPI Sample App
version: 1.0.1
description: This is a sample app.
termsOfService: https://asyncapi.org/terms/
contact:
  name: API Support
  url: https://www.asyncapi.org/support
  email: support@asyncapi.org
license:
  name: Apache 2.0
  url: https://www.apache.org/licenses/LICENSE-2.0.html
externalDocs:
  description: Find more info here
  url: https://www.asyncapi.org
tags:
  - name: e-commerce
```

#### <a name="contactObject"></a>Contact Object

Contact information for the exposed API.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="contactObjectName"></a>name | `string` | The identifying name of the contact person/organization.
<a name="contactObjectUrl"></a>url | `string` | The URL pointing to the contact information. This MUST be in the form of an absolute URL.
<a name="contactObjectEmail"></a>email | `string` | The email address of the contact person/organization. MUST be in the format of an email address.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Contact Object Example

<!-- asyncapi-example-tester:{"name":"Contact Object","json_pointer":"/info/contact"} -->
```json
{
  "name": "API Support",
  "url": "https://www.example.com/support",
  "email": "support@example.com"
}
```

<!-- asyncapi-example-tester:{"name":"Contact Object","json_pointer":"/info/contact"} -->
```yaml
name: API Support
url: https://www.example.com/support
email: support@example.com
```

#### <a name="licenseObject"></a>License Object

License information for the exposed API.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="licenseObjectName"></a>name | `string` | **REQUIRED.** The license name used for the API.
<a name="licenseObjectUrl"></a>url | `string` | A URL to the license used for the API. This MUST be in the form of an absolute URL.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### License Object Example

<!-- asyncapi-example-tester:{"name":"License Object","json_pointer":"/info/license"} -->
```json
{
  "name": "Apache 2.0",
  "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
}
```

<!-- asyncapi-example-tester:{"name":"License Object","json_pointer":"/info/license"} -->
```yaml
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
```

#### <a name="serversObject"></a>Servers Object

The Servers Object is a map of [Server Objects](#serverObject).

##### Patterned Fields

Field Pattern | Type | Description
---|:---:|---
<a name="serversObjectServer"></a>`^[A-Za-z0-9_\-]+$` | [Server Object](#serverObject) \| [Reference Object](#referenceObject) | The definition of a server this application MAY connect to.

##### Servers Object Example

<!-- asyncapi-example-tester:{"name":"Servers Object","json_pointer":"/servers"} -->
```json
{
  "development": {
    "host": "localhost:5672",
    "description": "Development AMQP broker.",
    "protocol": "amqp",
    "protocolVersion": "0-9-1",
    "tags": [
      { 
        "name": "env:development",
        "description": "This environment is meant for developers to run their own tests."
      }
    ]
  },
  "staging": {
    "host": "rabbitmq-staging.in.mycompany.com:5672",
    "description": "RabbitMQ broker for the staging environment.",
    "protocol": "amqp",
    "protocolVersion": "0-9-1",
    "tags": [
      { 
        "name": "env:staging",
        "description": "This environment is a replica of the production environment."
      }
    ]
  },
  "production": {
    "host": "rabbitmq.in.mycompany.com:5672",
    "description": "RabbitMQ broker for the production environment.",
    "protocol": "amqp",
    "protocolVersion": "0-9-1",
    "tags": [
      { 
        "name": "env:production",
        "description": "This environment is the live environment available for final users."
      }
    ]
  }
}
```

<!-- asyncapi-example-tester:{"name":"Servers Object","json_pointer":"/servers"} -->
```yaml
development:
  host: localhost:5672
  description: Development AMQP broker.
  protocol: amqp
  protocolVersion: 0-9-1
  tags:
    - name: 'env:development'
      description: 'This environment is meant for developers to run their own tests.'
staging:
  host: rabbitmq-staging.in.mycompany.com:5672
  description: RabbitMQ broker for the staging environment.
  protocol: amqp
  protocolVersion: 0-9-1
  tags:
    - name: 'env:staging'
      description: 'This environment is a replica of the production environment.'
production:
  host: rabbitmq.in.mycompany.com:5672
  description: RabbitMQ broker for the production environment.
  protocol: amqp
  protocolVersion: 0-9-1
  tags:
    - name: 'env:production'
      description: 'This environment is the live environment available for final users.'
```

#### <a name="serverObject"></a>Server Object

An object representing a message broker, a server or any other kind of computer program capable of sending and/or receiving data. This object is used to capture details such as URIs, protocols and security configuration. Variable substitution can be used so that some details, for example usernames and passwords, can be injected by code generation tools.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="serverObjectHost"></a>host | `string` | **REQUIRED**. The server host name. It MAY include the port. This field supports [Server Variables](#serverObjectVariables). Variable substitutions will be made when a variable is named in `{`braces`}`.
<a name="serverObjectProtocol"></a>protocol | `string` | **REQUIRED**. The protocol this server supports for connection.
<a name="serverObjectProtocolVersion"></a>protocolVersion | `string` | The version of the protocol used for connection. For instance: AMQP `0.9.1`, HTTP `2.0`, Kafka `1.0.0`, etc.
<a name="serverObjectPathname"></a>pathname | `string` | The path to a resource in the host. This field supports [Server Variables](#serverObjectVariables). Variable substitutions will be made when a variable is named in `{`braces`}`.
<a name="serverObjectDescription"></a>description | `string` | An optional string describing the server. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
<a name="serverObjectTitle"></a>title | `string` | A human-friendly title for the server.
<a name="serverObjectSummary"></a>summary | `string` | A short summary of the server.
<a name="serverObjectVariables"></a>variables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)]] | A map between a variable name and its value.  The value is used for substitution in the server's `host` and `pathname` template.
<a name="serverObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | A declaration of which security schemes can be used with this server. The list of values includes alternative [security scheme objects](#securitySchemeObject) that can be used. Only one of the security scheme objects need to be satisfied to authorize a connection or operation.
<a name="serverObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of servers.
<a name="serverObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this server.
<a name="serverObjectBindings"></a>bindings | [Server Bindings Object](#serverBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the server.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Server Object Example

A single server would be described as:

<!-- asyncapi-example-tester:{"name":"Server Object","json_pointer":"/servers/production"} -->
```json
{
  "host": "kafka.in.mycompany.com:9092",
  "description": "Production Kafka broker.",
  "protocol": "kafka",
  "protocolVersion": "3.2"
}
```

<!-- asyncapi-example-tester:{"name":"Server Object","json_pointer":"/servers/production"} -->
```yaml
host: kafka.in.mycompany.com:9092
description: Production Kafka broker.
protocol: kafka
protocolVersion: '3.2'
```

An example of a server that has a `pathname`:

<!-- asyncapi-example-tester:{"name":"Server Object with pathname","json_pointer":"/servers/production"} -->
```json
{
  "host": "rabbitmq.in.mycompany.com:5672",
  "pathname": "/production",
  "protocol": "amqp",
  "description": "Production RabbitMQ broker (uses the `production` vhost)."
}
```

<!-- asyncapi-example-tester:{"name":"Server Object with pathname","json_pointer":"/servers/production"} -->
```yaml
host: rabbitmq.in.mycompany.com:5672
pathname: /production
protocol: amqp
description: Production RabbitMQ broker (uses the `production` vhost).
```

#### <a name="serverVariableObject"></a>Server Variable Object

An object representing a Server Variable for server URL template substitution.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="serverVariableObjectEnum"></a>enum | [`string`] | An enumeration of string values to be used if the substitution options are from a limited set.
<a name="serverVariableObjectDefault"></a>default | `string` | The default value to use for substitution, and to send, if an alternate value is _not_ supplied.
<a name="serverVariableObjectDescription"></a>description | `string` | An optional description for the server variable. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
<a name="serverVariableObjectExamples"></a>examples | [`string`] | An array of examples of the server variable.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Server Variable Object Example

<!-- asyncapi-example-tester:{"name":"Server Object with Variable Object","json_pointer":"/servers/production"} -->
```json
{
  "host": "rabbitmq.in.mycompany.com:5672",
  "pathname": "/{env}",
  "protocol": "amqp",
  "description": "RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`.",
  "variables": {
    "env": {
      "description": "Environment to connect to. It can be either `production` or `staging`.",
      "enum": [
        "production",
        "staging"
      ]
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Server Object with Variable Object","json_pointer":"/servers/production"} -->
```yaml
host: 'rabbitmq.in.mycompany.com:5672'
pathname: '/{env}'
protocol: amqp
description: RabbitMQ broker. Use the `env` variable to point to either `production` or `staging`.
variables:
  env:
    description: Environment to connect to. It can be either `production` or `staging`.
    enum:
      - production
      - staging
```

#### <a name="defaultContentTypeString"></a>Default Content Type

A string representing the default content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). This value MUST be used by schema parsers when the [contentType](#messageObjectContentType) property is omitted.

In case a message can't be encoded/decoded using this value, schema parsers MUST use their default content type.

##### Default Content Type Example

<!-- asyncapi-example-tester:{"name":"Default Content Type at root doc","json_pointer":""} -->  
```json
{
  "defaultContentType": "application/json"
}
```

<!-- asyncapi-example-tester:{"name":"Default Content Type at root doc","json_pointer":""} -->  
```yaml
defaultContentType: application/json
```

#### <a name="channelsObject"></a>Channels Object

An object containing all the [Channel Object](#channelObject) definitions the [Application](#definitionsApplication) MUST use during runtime.

##### Patterned Fields

Field Pattern | Type | Description
---|:---:|---
<a name="channelsObjectChannel"></a>\{channelId} | [Channel Object](#channelObject) \| [Reference Object](#referenceObject) | An identifier for the described channel. The `channelId` value is **case-sensitive**. Tools and libraries MAY use the `channelId` to uniquely identify a channel, therefore, it is RECOMMENDED to follow common programming naming conventions.

##### Channels Object Example

<!-- asyncapi-example-tester:{"name":"Channels Object","json_pointer":"/channels"} -->
```json
{
  "userSignedUp": {
    "address": "user.signedup",
    "messages": {
      "userSignedUp": {
        "$ref": "#/components/messages/userSignedUp"
      }
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Channels Object","json_pointer":"/channels"} -->
```yaml
userSignedUp:
  address: 'user.signedup'
  messages:
    userSignedUp:
      $ref: '#/components/messages/userSignedUp'
```

#### <a name="channelObject"></a>Channel Object

Describes a shared communication channel.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="channelObjectAddress"></a>address | `string` \| `null` | An optional string representation of this channel's address. The address is typically the "topic name", "routing key", "event type", or "path". When `null` or absent, it MUST be interpreted as unknown. This is useful when the address is generated dynamically at runtime or can't be known upfront. It MAY contain [Channel Address Expressions](#channelAddressExpressions). Query parameters and fragments SHALL NOT be used, instead use [bindings](#channelBindingsObject) to define them.
<a name="channelObjectMessages"></a>messages | [Messages Object](#messagesObject) | A map of the messages that will be sent to this channel by any application at any time. **Every message sent to this channel MUST be valid against one, and only one, of the [message objects](#messageObject) defined in this map.**
<a name="channelObjectTitle"></a>title | `string` | A human-friendly title for the channel.
<a name="channelObjectSummary"></a>summary | `string` | A short summary of the channel.
<a name="channelObjectDescription"></a>description | `string` | An optional description of this channel. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="channelObjectServers"></a>servers | [[Reference Object](#referenceObject)] | An array of `$ref` pointers to the definition of the servers in which this channel is available. If the channel is located in the [root Channels Object](#channelsObject), it MUST point to a subset of server definitions located in the [root Servers Object](#serversObject), and MUST NOT point to a subset of server definitions located in the [Components Object](#componentsObject) or anywhere else. If the channel is located in the [Components Object](#componentsObject), it MAY point to a [Server Objects](#serverObject) in any location. If `servers` is absent or empty, this channel MUST be available on all the servers defined in the [Servers Object](#serversObject). Please note the `servers` property value MUST be an array of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain an array of [Server Objects](#serverObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.
<a name="channelObjectParameters"></a>parameters | [Parameters Object](#parametersObject) | A map of the parameters included in the channel address. It MUST be present only when the address contains [Channel Address Expressions](#channelAddressExpressions).
<a name="channelObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping of channels.
<a name="channelObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this channel.
<a name="channelObjectBindings"></a>bindings | [Channel Bindings Object](#channelBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the channel.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Channel Object Example

<!-- asyncapi-example-tester:{"name":"Channel Object","json_pointer":"/channels/user"} -->
```json
{
  "address": "users.{userId}",
  "title": "Users channel",
  "description": "This channel is used to exchange messages about user events.",
  "messages": {
    "userSignedUp": {
      "$ref": "#/components/messages/userSignedUp"
    },
    "userCompletedOrder": {
      "$ref": "#/components/messages/userCompletedOrder"
    }
  },
  "parameters": {
    "userId": {
      "$ref": "#/components/parameters/userId"
    }
  },
  "servers": [
    { "$ref": "#/servers/rabbitmqInProd" },
    { "$ref": "#/servers/rabbitmqInStaging" }
  ],
  "bindings": {
    "amqp": {
      "is": "queue",
      "queue": {
        "exclusive": true
      }
    }
  },
  "tags": [{
    "name": "user",
    "description": "User-related messages"
  }],
  "externalDocs": {
    "description": "Find more info here",
    "url": "https://example.com"
  }
}
```

<!-- asyncapi-example-tester:{"name":"Channel Object","json_pointer":"/channels/user"} -->
```yaml
address: 'users.{userId}'
title: Users channel
description: This channel is used to exchange messages about user events.
messages:
  userSignedUp:
    $ref: '#/components/messages/userSignedUp'
  userCompletedOrder:
    $ref: '#/components/messages/userCompletedOrder'
parameters:
  userId:
    $ref: '#/components/parameters/userId'
servers:
  - $ref: '#/servers/rabbitmqInProd'
  - $ref: '#/servers/rabbitmqInStaging'
bindings:
  amqp:
    is: queue
    queue:
      exclusive: true
tags:
  - name: user
    description: User-related messages
externalDocs:
  description: 'Find more info here'
  url: 'https://example.com'
```

#### <a name="channelAddressExpressions"></a>Channel Address Expressions

Channel addresses MAY contain expressions that can be used to define dynamic values.

Expressions MUST be composed by a name enclosed in curly braces (`{` and `}`). E.g., `{userId}`.

#### <a name="messagesObject"></a>Messages Object

Describes a map of messages included in a channel.

##### Patterned Fields

Field Pattern | Type | Description
---|:---:|---
<a name="messagesObjectId"></a>`{messageId}` | [Message Object](#messageObject) \| [Reference Object](#referenceObject) | The key represents the message identifier. The `messageId` value is **case-sensitive**. Tools and libraries MAY use the `messageId` value to uniquely identify a message, therefore, it is RECOMMENDED to follow common programming naming conventions.

##### Messages Object Example

<!-- asyncapi-example-tester:{"name":"Messages Object","json_pointer":"/channels/user/messages"} -->
```json
{
  "userSignedUp": {
    "$ref": "#/components/messages/userSignedUp"
  },
  "userCompletedOrder": {
    "$ref": "#/components/messages/userCompletedOrder"
  }
}
```

<!-- asyncapi-example-tester:{"name":"Messages Object","json_pointer":"/channels/user/messages"} -->
```yaml
userSignedUp:
  $ref: '#/components/messages/userSignedUp'
userCompletedOrder:
  $ref: '#/components/messages/userCompletedOrder'
```

#### <a name="operationsObject"></a>Operations Object

Holds a dictionary with all the [operations](#operationObject) this application MUST implement.

> If you're looking for a place to define operations that MAY or MAY NOT be implemented by the application, consider defining them in [`components/operations`](#componentsOperations).

##### Patterned Fields

Field Pattern | Type | Description
---|:---:|---
<a name="operationsObjectOperation"></a>\{operationId} | [Operation Object](#operationObject) \| [Reference Object](#referenceObject) | The operation this application MUST implement. The field name (`operationId`) MUST be a string used to identify the operation in the document where it is defined, and its value is **case-sensitive**. Tools and libraries MAY use the `operationId` to uniquely identify an operation, therefore, it is RECOMMENDED to follow common programming naming conventions.

##### Operations Object Example

<!-- asyncapi-example-tester:{"name":"Operations Object","json_pointer":"/operations"} -->
```json
{
  "onUserSignUp": {
    "title": "User sign up",
    "summary": "Action to sign a user up.",
    "description": "A longer description",
    "channel": {
      "$ref": "#/channels/userSignup"
    },
    "action": "send",
    "tags": [
      { "name": "user" },
      { "name": "signup" },
      { "name": "register" }
    ],
    "bindings": {
      "amqp": {
        "ack": false
      }
    },
    "traits": [
      { "$ref": "#/components/operationTraits/kafka" }
    ]
  }
}
```

<!-- asyncapi-example-tester:{"name":"Operations Object","json_pointer":"/operations"} -->
```yaml
onUserSignUp:
  title: User sign up
  summary: Action to sign a user up.
  description: A longer description
  channel:
    $ref: '#/channels/userSignup'
  action: send
  tags:
    - name: user
    - name: signup
    - name: register
  bindings:
    amqp:
      ack: false
  traits:
    - $ref: '#/components/operationTraits/kafka'
```

#### <a name="operationObject"></a>Operation Object

Describes a specific operation.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationObjectAction"></a>action | `"send"` &#124; `"receive"` | **Required**. Use `send` when it's expected that the application will send a message to the given [`channel`](#operationObjectChannel), and `receive` when the application should expect receiving messages from the given [`channel`](#operationObjectChannel).
<a name="operationObjectChannel"></a>channel | [Reference Object](#referenceObject) | **Required**. A `$ref` pointer to the definition of the channel in which this operation is performed. If the operation is located in the [root Operations Object](#operationsObject), it MUST point to a channel definition located in the [root Channels Object](#channelsObject), and MUST NOT point to a channel definition located in the [Components Object](#componentsObject) or anywhere else. If the operation is located in the [Components Object](#componentsObject), it MAY point to a [Channel Object](#channelObject) in any location. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.
<a name="operationObjectTitle"></a>title | `string` | A human-friendly title for the operation.
<a name="operationObjectSummary"></a>summary | `string` | A short summary of what the operation is about.
<a name="operationObjectDescription"></a>description | `string` | A verbose explanation of the operation. [CommonMark syntax](http://spec.commonmark.org/) can be used for rich text representation.
<a name="operationObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations.
<a name="operationObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation.
<a name="operationObjectBindings"></a>bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.
<a name="operationObjectTraits"></a>traits | [[Operation Trait Object](#operationTraitObject) &#124; [Reference Object](#referenceObject) ] | A list of traits to apply to the operation object. Traits MUST be merged using [traits merge mechanism](#traits-merge-mechanism). The resulting object MUST be a valid [Operation Object](#operationObject).
<a name="operationObjectMessages"></a>messages | [[Reference Object](#referenceObject)] | A list of `$ref` pointers pointing to the supported [Message Objects](#messageObject) that can be processed by this operation. It MUST contain a subset of the messages defined in the [channel referenced in this operation](#operationObjectChannel), and MUST NOT point to a subset of message definitions located in the [Messages Object](#componentsMessages) in the [Components Object](#componentsObject) or anywhere else. **Every message processed by this operation MUST be valid against one, and only one, of the [message objects](#messageObject) referenced in this list.** Please note the `messages` property value MUST be a list of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain [Message Objects](#messageObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. <p>**Note**: excluding this property from the Operation implies that all messages from the channel will be included. Explicitly set the `messages` property to `[]` if this operation should contain no messages.</p>
<a name="operationObjectReply"></a>reply | [Operation Reply Object](#operationReplyObject) &#124; [Reference Object](#referenceObject)  | The definition of the reply in a request-reply operation.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Operation Object Example

<!-- asyncapi-example-tester:{"name":"Operation Object","json_pointer":"/operations/sendUserSignUp"} -->
```json
{
  "title": "User sign up",
  "summary": "Action to sign a user up.",
  "description": "A longer description",
  "channel": {
    "$ref": "#/channels/userSignup"
  },
  "action": "send",
  "security": [
    {
      "type": "oauth2",
      "description": "The oauth security descriptions",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://example.com/api/oauth/dialog",
          "availableScopes": {
            "subscribe:auth_revocations": "Scope required for authorization revocation topic"
          }
        }
      },
      "scopes": [
        "subscribe:auth_revocations"
      ],
     "petstore_auth": [
       "write:pets",
       "read:pets"
     ]
    }
  ],
  "tags": [
    { "name": "user" },
    { "name": "signup" },
    { "name": "register" }
  ],
  "bindings": {
    "amqp": {
      "ack": false
    }
  },
  "traits": [
    { "$ref": "#/components/operationTraits/kafka" }
  ],
  "messages": [
    { "$ref": "#/channels/userSignup/messages/userSignedUp" }
  ],
  "reply": {
    "address": {
      "location": "$message.header#/replyTo"
    },
    "channel": {
      "$ref": "#/channels/userSignupReply"
    },
    "messages": [
      { "$ref": "#/channels/userSignupReply/messages/userSignedUpReply" }
    ]
  }
}
```

<!-- asyncapi-example-tester:{"name":"Operation Object","json_pointer":"/operations/sendUserSignUp"} -->
```yaml
title: User sign up
summary: Action to sign a user up.
description: A longer description
channel:
  $ref: '#/channels/userSignup'
action: send
security:
  - type: oauth2
    description: The oauth security descriptions
    flows:
      clientCredentials:
        tokenUrl: 'https://example.com/api/oauth/dialog'
        availableScopes:
          'subscribe:auth_revocations': Scope required for authorization revocation topic
    scopes:
      - 'subscribe:auth_revocations'
    petstore_auth:
      - 'write:pets'
      - 'read:pets'
tags:
  - name: user
  - name: signup
  - name: register
bindings:
  amqp:
    ack: false
traits:
  - $ref: '#/components/operationTraits/kafka'
messages:
  - $ref: '#/channels/userSignup/messages/userSignedUp'
reply:
  address:
    location: '$message.header#/replyTo'
  channel:
    $ref: '#/channels/userSignupReply'
  messages:
    - $ref: '#/channels/userSignupReply/messages/userSignedUpReply'
```

#### <a name="operationTraitObject"></a>Operation Trait Object

Describes a trait that MAY be applied to an [Operation Object](#operationObject). This object MAY contain any property from the [Operation Object](#operationObject), except the `action`, `channel`, `messages` and `traits` ones.

If you're looking to apply traits to a message, see the [Message Trait Object](#messageTraitObject).

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationTraitObjectTitle"></a>title | `string` | A human-friendly title for the operation.
<a name="operationTraitObjectSummary"></a>summary | `string` | A short summary of what the operation is about.
<a name="operationTraitObjectDescription"></a>description | `string` | A verbose explanation of the operation. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="operationTraitObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationTraitObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations.
<a name="operationTraitObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation.
<a name="operationTraitObjectBindings"></a>bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Operation Trait Object Example

<!-- asyncapi-example-tester:{"name":"Operation Traits Object","json_pointer":"/operations/sendUserSignUp/traits/0"} -->
```json
{
  "bindings": {
    "amqp": {
      "ack": false
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Operation Traits Object","json_pointer":"/operations/sendUserSignUp/traits/0"} -->
```yaml
bindings:
  amqp:
    ack: false
```

#### <a name="operationReplyObject"></a>Operation Reply Object

Describes the reply part that MAY be applied to an Operation Object. If an operation implements the request/reply pattern, the reply object represents the response message.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationReplyObjectAddress"></a>address | [Operation Reply Address Object](#operationReplyAddressObject) &#124; [Reference Object](#referenceObject) | Definition of the address that implementations MUST use for the reply.
<a name="operationReplyObjectChannel"></a>channel | [Reference Object](#referenceObject) | A `$ref` pointer to the definition of the channel in which this operation is performed. When [address](#operationReplyAddressObject) is specified, the [`address` property](#channelObjectAddress) of the channel referenced by this property MUST be either `null` or not defined. If the operation reply is located inside a [root Operation Object](#operationObject), it MUST point to a channel definition located in the [root Channels Object](#channelsObject), and MUST NOT point to a channel definition located in the [Components Object](#componentsObject) or anywhere else. If the operation reply is located inside an [Operation Object] in the [Components Object](#componentsObject) or in the [Replies Object](#componentsReplies) in the [Components Object](#componentsObject), it MAY point to a [Channel Object](#channelObject) in any location. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.
<a name="operationReplyObjectMessages"></a>messages | [[Reference Object](#referenceObject)] | A list of `$ref` pointers pointing to the supported [Message Objects](#messageObject) that can be processed by this operation as reply. It MUST contain a subset of the messages defined in the [channel referenced in this operation reply](#operationObjectChannel), and MUST NOT point to a subset of message definitions located in the [Components Object](#componentsObject) or anywhere else. **Every message processed by this operation MUST be valid against one, and only one, of the [message objects](#messageObject) referenced in this list.** Please note the `messages` property value MUST be a list of [Reference Objects](#referenceObject) and, therefore, MUST NOT contain [Message Objects](#messageObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="operationReplyAddressObject"></a>Operation Reply Address Object

An object that specifies where an operation has to send the reply.

For specifying and computing the location of a reply address, a [runtime expression](#runtimeExpression) is used.

##### Fixed Fields

Field Name | Type | Description
---|:---|---
description | `string` | An optional description of the address. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
location | `string` | **REQUIRED.** A [runtime expression](#runtimeExpression) that specifies the location of the reply address.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Examples

<!-- asyncapi-example-tester:{"name":"Operation Reply Address Object","json_pointer":"/operations/sendUserSignUp/reply/address"} -->
```json
{
  "description": "Consumer inbox",
  "location": "$message.header#/replyTo"
}
```

<!-- asyncapi-example-tester:{"name":"Operation Reply Address Object","json_pointer":"/operations/sendUserSignUp/reply/address"} -->
```yaml
description: Consumer Inbox
location: $message.header#/replyTo
```

#### <a name="parametersObject"></a>Parameters Object

Describes a map of parameters included in a channel address.

This map MUST contain all the parameters used in the parent channel address.

##### Patterned Fields

Field Pattern | Type | Description
---|:---:|---
<a name="parametersObjectName"></a>`^[A-Za-z0-9_\-]+$` | [Parameter Object](#parameterObject) &#124; [Reference Object](#referenceObject) | The key represents the name of the parameter. It MUST match the parameter name used in the parent channel address.

##### Parameters Object Example

<!-- asyncapi-example-tester:{"name":"Channel Parameters Object","json_pointer":"/channels/user"} -->
```json
{
  "address": "user/{userId}/signedup",
  "parameters": {
    "userId": {
      "description": "Id of the user."
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Channel Parameters Object","json_pointer":"/channels/user"} -->
```yaml
address: user/{userId}/signedup
parameters:
  userId:
    description: Id of the user.
```

#### <a name="parameterObject"></a>Parameter Object

Describes a parameter included in a channel address.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="parameterObjectEnum"></a>enum | [`string`] | An enumeration of string values to be used if the substitution options are from a limited set.
<a name="parameterObjectDefault"></a>default | `string` | The default value to use for substitution, and to send, if an alternate value is _not_ supplied.
<a name="parameterObjectDescription"></a>description | `string` | An optional description for the parameter. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
<a name="parameterObjectExamples"></a>examples | [`string`] | An array of examples of the parameter value.
<a name="parameterObjectLocation"></a>location | `string` | A [runtime expression](#runtimeExpression) that specifies the location of the parameter value.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Parameter Object Example

<!-- asyncapi-example-tester:{"name":"Channel Parameter Object","json_pointer":"/channels/user"} -->
```json
{
  "address": "user/{userId}/signedup",
  "parameters": {
    "userId": {
      "description": "Id of the user.",
      "location": "$message.payload#/user/id"
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Channel Parameter Object","json_pointer":"/channels/user"} -->
```yaml
address: user/{userId}/signedup
parameters:
  userId:
    description: Id of the user.
    location: $message.payload#/user/id
```

#### <a name="serverBindingsObject"></a>Server Bindings Object

Map describing protocol-specific definitions for a server.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="serverBindingsObjectHTTP"></a>`http` | [HTTP Server Binding](https://github.com/asyncapi/bindings/blob/master/http#server) | Protocol-specific information for an HTTP server.
<a name="serverBindingsObjectWebSockets"></a>`ws` | [WebSockets Server Binding](https://github.com/asyncapi/bindings/blob/master/websockets#server) | Protocol-specific information for a WebSockets server.
<a name="serverBindingsObjectKafka"></a>`kafka` | [Kafka Server Binding](https://github.com/asyncapi/bindings/blob/master/kafka#server) | Protocol-specific information for a Kafka server.
<a name="serverBindingsObjectAnypointMQ"></a>`anypointmq` | [Anypoint MQ Server Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq#server) | Protocol-specific information for an Anypoint MQ server.
<a name="serverBindingsObjectAMQP"></a>`amqp` | [AMQP Server Binding](https://github.com/asyncapi/bindings/blob/master/amqp#server) | Protocol-specific information for an AMQP 0-9-1 server.
<a name="serverBindingsObjectAMQP1"></a>`amqp1` | [AMQP 1.0 Server Binding](https://github.com/asyncapi/bindings/blob/master/amqp1#server) | Protocol-specific information for an AMQP 1.0 server.
<a name="serverBindingsObjectMQTT"></a>`mqtt` | [MQTT Server Binding](https://github.com/asyncapi/bindings/blob/master/mqtt#server) | Protocol-specific information for an MQTT server.
<a name="serverBindingsObjectMQTT5"></a>`mqtt5` | [MQTT 5 Server Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5#server) | Protocol-specific information for an MQTT 5 server.
<a name="serverBindingsObjectNATS"></a>`nats` | [NATS Server Binding](https://github.com/asyncapi/bindings/blob/master/nats#server) | Protocol-specific information for a NATS server.
<a name="serverBindingsObjectJMS"></a>`jms` | [JMS Server Binding](https://github.com/asyncapi/bindings/blob/master/jms#server) | Protocol-specific information for a JMS server.
<a name="serverBindingsObjectSNS"></a>`sns` | [SNS Server Binding](https://github.com/asyncapi/bindings/blob/master/sns#server) | Protocol-specific information for an SNS server.
<a name="serverBindingsObjectSolace"></a>`solace` | [Solace Server Binding](https://github.com/asyncapi/bindings/blob/master/solace#server) | Protocol-specific information for a Solace server.
<a name="serverBindingsObjectSQS"></a>`sqs` | [SQS Server Binding](https://github.com/asyncapi/bindings/blob/master/sqs#server) | Protocol-specific information for an SQS server.
<a name="serverBindingsObjectSTOMP"></a>`stomp` | [STOMP Server Binding](https://github.com/asyncapi/bindings/blob/master/stomp#server) | Protocol-specific information for a STOMP server.
<a name="serverBindingsObjectRedis"></a>`redis` | [Redis Server Binding](https://github.com/asyncapi/bindings/blob/master/redis#server) | Protocol-specific information for a Redis server.
<a name="serverBindingsObjectMercure"></a>`mercure` | [Mercure Server Binding](https://github.com/asyncapi/bindings/blob/master/mercure#server) | Protocol-specific information for a Mercure server.
<a name="serverBindingsObjectIBMMQ"></a>`ibmmq` | [IBM MQ Server Binding](https://github.com/asyncapi/bindings/blob/master/ibmmq#server-binding-object) | Protocol-specific information for an IBM MQ server.
<a name="serverBindingsObjectGooglePubSub"></a>`googlepubsub` | [Google Cloud Pub/Sub Server Binding](https://github.com/asyncapi/bindings/blob/master/googlepubsub#server) | Protocol-specific information for a Google Cloud Pub/Sub server.
<a name="serverBindingsObjectPulsar"></a>`pulsar` | [Pulsar Server Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#server-binding-object) | Protocol-specific information for a Pulsar server.
<a name="serverBindingsObjectROS2"></a>`ros2` | [ROS 2 Server Binding](https://github.com/asyncapi/bindings/tree/master/ros2#server-binding-object) | Protocol-specific information for a ROS 2 server.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="channelBindingsObject"></a>Channel Bindings Object

Map describing protocol-specific definitions for a channel.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="channelBindingsObjectHTTP"></a>`http` | [HTTP Channel Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#channel) | Protocol-specific information for an HTTP channel.
<a name="channelBindingsObjectWebSockets"></a>`ws` | [WebSockets Channel Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#channel) | Protocol-specific information for a WebSockets channel.
<a name="channelBindingsObjectKafka"></a>`kafka` | [Kafka Channel Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#channel) | Protocol-specific information for a Kafka channel.
<a name="channelBindingsObjectAnypointMQ"></a>`anypointmq` | [Anypoint MQ Channel Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#channel) | Protocol-specific information for an Anypoint MQ channel.
<a name="channelBindingsObjectAMQP"></a>`amqp` | [AMQP Channel Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#channel) | Protocol-specific information for an AMQP 0-9-1 channel.
<a name="channelBindingsObjectAMQP1"></a>`amqp1` | [AMQP 1.0 Channel Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#channel) | Protocol-specific information for an AMQP 1.0 channel.
<a name="channelBindingsObjectMQTT"></a>`mqtt` | [MQTT Channel Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#channel) | Protocol-specific information for an MQTT channel.
<a name="channelBindingsObjectMQTT5"></a>`mqtt5` | [MQTT 5 Channel Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5#channel) | Protocol-specific information for an MQTT 5 channel.
<a name="channelBindingsObjectNATS"></a>`nats` | [NATS Channel Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#channel) | Protocol-specific information for a NATS channel.
<a name="channelBindingsObjectJMS"></a>`jms` | [JMS Channel Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#channel) | Protocol-specific information for a JMS channel.
<a name="channelBindingsObjectSNS"></a>`sns` | [SNS Channel Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#channel) | Protocol-specific information for an SNS channel.
<a name="channelBindingsObjectSolace"></a>`solace` | [Solace Channel Binding](https://github.com/asyncapi/bindings/blob/master/solace#channel) | Protocol-specific information for a Solace channel.
<a name="channelBindingsObjectSQS"></a>`sqs` | [SQS Channel Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#channel) | Protocol-specific information for an SQS channel.
<a name="channelBindingsObjectSTOMP"></a>`stomp` | [STOMP Channel Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#channel) | Protocol-specific information for a STOMP channel.
<a name="channelBindingsObjectRedis"></a>`redis` | [Redis Channel Binding](https://github.com/asyncapi/bindings/blob/master/redis#channel) | Protocol-specific information for a Redis channel.
<a name="channelBindingsObjectMercure"></a>`mercure` | [Mercure Channel Binding](https://github.com/asyncapi/bindings/blob/master/mercure#channel) | Protocol-specific information for a Mercure channel.
<a name="channelBindingsObjectIBMMQ"></a>`ibmmq` | [IBM MQ Channel Binding](https://github.com/asyncapi/bindings/tree/master/ibmmq#channel-binding-object) | Protocol-specific information for an IBM MQ channel.
<a name="channelBindingsObjectGooglePubSub"></a>`googlepubsub` | [Google Cloud Pub/Sub Channel Binding](https://github.com/asyncapi/bindings/tree/master/googlepubsub#channel) | Protocol-specific information for a Google Cloud Pub/Sub channel.
<a name="channelBindingsObjectPulsar"></a>`pulsar` | [Pulsar Channel Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#channel-binding-object) | Protocol-specific information for a Pulsar channel.
<a name="channelBindingsObjectROS2"></a>`ros2` | [ROS 2 Channel Binding](https://github.com/asyncapi/bindings/tree/master/ros2#channel-binding-object) | Protocol-specific information for a ROS 2 channel.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="operationBindingsObject"></a>Operation Bindings Object

Map describing protocol-specific definitions for an operation.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationBindingsObjectHTTP"></a>`http` | [HTTP Operation Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#operation) | Protocol-specific information for an HTTP operation.
<a name="operationBindingsObjectWebSockets"></a>`ws` | [WebSockets Operation Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#operation) | Protocol-specific information for a WebSockets operation.
<a name="operationBindingsObjectKafka"></a>`kafka` | [Kafka Operation Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#operation) | Protocol-specific information for a Kafka operation.
<a name="operationBindingsObjectAnypointMQ"></a>`anypointmq` | [Anypoint MQ Operation Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#operation) | Protocol-specific information for an Anypoint MQ operation.
<a name="operationBindingsObjectAMQP"></a>`amqp` | [AMQP Operation Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#operation) | Protocol-specific information for an AMQP 0-9-1 operation.
<a name="operationBindingsObjectAMQP1"></a>`amqp1` | [AMQP 1.0 Operation Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#operation) | Protocol-specific information for an AMQP 1.0 operation.
<a name="operationBindingsObjectMQTT"></a>`mqtt` | [MQTT Operation Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#operation) | Protocol-specific information for an MQTT operation.
<a name="operationBindingsObjectMQTT5"></a>`mqtt5` | [MQTT 5 Operation Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5/README.md#operation) | Protocol-specific information for an MQTT 5 operation.
<a name="operationBindingsObjectNATS"></a>`nats` | [NATS Operation Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#operation) | Protocol-specific information for a NATS operation.
<a name="operationBindingsObjectJMS"></a>`jms` | [JMS Operation Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#operation) | Protocol-specific information for a JMS operation.
<a name="operationBindingsObjectSNS"></a>`sns` | [SNS Operation Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#operation) | Protocol-specific information for an SNS operation.
<a name="operationBindingsObjectSolace"></a>`solace` | [Solace Operation Binding](https://github.com/asyncapi/bindings/blob/master/solace#operation) | Protocol-specific information for a Solace operation.
<a name="operationBindingsObjectSQS"></a>`sqs` | [SQS Operation Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#operation) | Protocol-specific information for an SQS operation.
<a name="operationBindingsObjectSTOMP"></a>`stomp` | [STOMP Operation Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#operation) | Protocol-specific information for a STOMP operation.
<a name="operationBindingsObjectRedis"></a>`redis` | [Redis Operation Binding](https://github.com/asyncapi/bindings/blob/master/redis#operation) | Protocol-specific information for a Redis operation.
<a name="operationBindingsObjectMercure"></a>`mercure` | [Mercure Operation Binding](https://github.com/asyncapi/bindings/blob/master/mercure#operation) | Protocol-specific information for a Mercure operation.
<a name="operationBindingsObjectGooglePubSub"></a>`googlepubsub` | [Google Cloud Pub/Sub Operation Binding](https://github.com/asyncapi/bindings/blob/master/googlepubsub#operation) | Protocol-specific information for a Google Cloud Pub/Sub operation.
<a name="operationBindingsObjectIBMMQ"></a>`ibmmq` | [IBM MQ Operation Binding](https://github.com/asyncapi/bindings/blob/master/ibmmq#operation-binding-object) | Protocol-specific information for an IBM MQ operation.
<a name="operationBindingsObjectPulsar"></a>`pulsar` | [Pulsar Operation Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#operation-binding-fields) | Protocol-specific information for a Pulsar operation.
<a name="operationBindingsObjectROS2"></a>`ros2` | [ROS 2 Operation Binding](https://github.com/asyncapi/bindings/tree/master/ros2#operation-binding-fields) | Protocol-specific information for a ROS 2 operation.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="messageBindingsObject"></a>Message Bindings Object

Map describing protocol-specific definitions for a message.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageBindingsObjectHTTP"></a>`http` | [HTTP Message Binding](https://github.com/asyncapi/bindings/blob/master/http/README.md#message) | Protocol-specific information for an HTTP message, i.e., a request or a response.
<a name="messageBindingsObjectWebSockets"></a>`ws` | [WebSockets Message Binding](https://github.com/asyncapi/bindings/blob/master/websockets/README.md#message) | Protocol-specific information for a WebSockets message.
<a name="messageBindingsObjectKafka"></a>`kafka` | [Kafka Message Binding](https://github.com/asyncapi/bindings/blob/master/kafka/README.md#message) | Protocol-specific information for a Kafka message.
<a name="messageBindingsObjectAnypointMQ"></a>`anypointmq` | [Anypoint MQ Message Binding](https://github.com/asyncapi/bindings/blob/master/anypointmq/README.md#message) | Protocol-specific information for an Anypoint MQ message.
<a name="messageBindingsObjectAMQP"></a>`amqp` | [AMQP Message Binding](https://github.com/asyncapi/bindings/blob/master/amqp/README.md#message) | Protocol-specific information for an AMQP 0-9-1 message.
<a name="messageBindingsObjectAMQP1"></a>`amqp1` | [AMQP 1.0 Message Binding](https://github.com/asyncapi/bindings/blob/master/amqp1/README.md#message) | Protocol-specific information for an AMQP 1.0 message.
<a name="messageBindingsObjectMQTT"></a>`mqtt` | [MQTT Message Binding](https://github.com/asyncapi/bindings/blob/master/mqtt/README.md#message) | Protocol-specific information for an MQTT message.
<a name="messageBindingsObjectMQTT5"></a>`mqtt5` | [MQTT 5 Message Binding](https://github.com/asyncapi/bindings/blob/master/mqtt5/README.md#message) | Protocol-specific information for an MQTT 5 message.
<a name="messageBindingsObjectNATS"></a>`nats` | [NATS Message Binding](https://github.com/asyncapi/bindings/blob/master/nats/README.md#message) | Protocol-specific information for a NATS message.
<a name="messageBindingsObjectJMS"></a>`jms` | [JMS Message Binding](https://github.com/asyncapi/bindings/blob/master/jms/README.md#message) | Protocol-specific information for a JMS message.
<a name="messageBindingsObjectSNS"></a>`sns` | [SNS Message Binding](https://github.com/asyncapi/bindings/blob/master/sns/README.md#message) | Protocol-specific information for an SNS message.
<a name="messageBindingsObjectSolace"></a>`solace` | [Solace Server Binding](https://github.com/asyncapi/bindings/blob/master/solace#message) | Protocol-specific information for a Solace message.
<a name="messageBindingsObjectSQS"></a>`sqs` | [SQS Message Binding](https://github.com/asyncapi/bindings/blob/master/sqs/README.md#message) | Protocol-specific information for an SQS message.
<a name="messageBindingsObjectSTOMP"></a>`stomp` | [STOMP Message Binding](https://github.com/asyncapi/bindings/blob/master/stomp/README.md#message) | Protocol-specific information for a STOMP message.
<a name="messageBindingsObjectRedis"></a>`redis` | [Redis Message Binding](https://github.com/asyncapi/bindings/blob/master/redis#message) | Protocol-specific information for a Redis message.
<a name="messageBindingsObjectMercure"></a>`mercure` | [Mercure Message Binding](https://github.com/asyncapi/bindings/blob/master/mercure#message) | Protocol-specific information for a Mercure message.
<a name="messageBindingsObjectIBMMQ"></a>`ibmmq` | [IBM MQ Message Binding](https://github.com/asyncapi/bindings/tree/master/ibmmq#message-binding-object) | Protocol-specific information for an IBM MQ message.
<a name="messageBindingsObjectGooglePubSub"></a>`googlepubsub` | [Google Cloud Pub/Sub Message Binding](https://github.com/asyncapi/bindings/tree/master/googlepubsub#message) | Protocol-specific information for a Google Cloud Pub/Sub message.
<a name="messageBindingsObjectPulsar"></a>`pulsar` | [Pulsar Message Binding](https://github.com/asyncapi/bindings/tree/master/pulsar#message-binding-fields) | Protocol-specific information for a Pulsar message.
<a name="messageBindingsObjectROS2"></a>`ros2` | [ROS 2 Message Binding](https://github.com/asyncapi/bindings/tree/master/ros2#message-binding-fields) | Protocol-specific information for a ROS 2 message.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="messageObject"></a>Message Object

Describes a message received on a given channel and operation.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageObjectHeaders"></a>headers | [Multi Format Schema Object](#multiFormatSchemaObject) &#124; [Schema Object](#schemaObject) &#124; [Reference Object](#referenceObject) | Schema definition of the application headers. Schema MUST be a map of key-value pairs. It **MUST NOT** define the protocol headers. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString).
<a name="messageObjectPayload"></a>payload | [Multi Format Schema Object](#multiFormatSchemaObject) &#124; [Schema Object](#schemaObject) &#124; [Reference Object](#referenceObject) | Definition of the message payload. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString).
<a name="messageObjectCorrelationId"></a>correlationId | [Correlation ID Object](#correlationIdObject) &#124; [Reference Object](#referenceObject) | Definition of the correlation ID used for message tracing or matching.
<a name="messageObjectContentType"></a>contentType | `string` | The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). When omitted, the value MUST be the one specified on the [defaultContentType](#defaultContentTypeString) field.
<a name="messageObjectName"></a>name | `string` | A machine-friendly name for the message.
<a name="messageObjectTitle"></a>title | `string` | A human-friendly title for the message.
<a name="messageObjectSummary"></a>summary | `string` | A short summary of what the message is about.
<a name="messageObjectDescription"></a>description | `string` | A verbose explanation of the message. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="messageObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of messages.
<a name="messageObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this message.
<a name="messageObjectBindings"></a>bindings | [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message.
<a name="messageObjectExamples"></a>examples | [[Message Example Object](#messageExampleObject)] | List of examples.
<a name="messageObjectTraits"></a>traits | [[Message Trait Object](#messageTraitObject) &#124; [Reference Object](#referenceObject)] | A list of traits to apply to the message object. Traits MUST be merged using [traits merge mechanism](#traits-merge-mechanism). The resulting object MUST be a valid [Message Object](#messageObject).

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Message Object Example

<!-- asyncapi-example-tester:{"name":"Message Object","json_pointer":"/components/messages/userSignedUp"} -->
```json
{
  "name": "UserSignup",
  "title": "User signup",
  "summary": "Action to sign a user up.",
  "description": "A longer description",
  "contentType": "application/json",
  "tags": [
    { "name": "user" },
    { "name": "signup" },
    { "name": "register" }
  ],
  "headers": {
    "type": "object",
    "properties": {
      "correlationId": {
        "description": "Correlation ID set by application",
        "type": "string"
      },
      "applicationInstanceId": {
        "description": "Unique identifier for a given instance of the publishing application",
        "type": "string"
      }
    }
  },
  "payload": {
    "type": "object",
    "properties": {
      "user": {
        "$ref": "#/components/schemas/userCreate"
      },
      "signup": {
        "$ref": "#/components/schemas/signup"
      }
    }
  },
  "correlationId": {
    "description": "Default Correlation ID",
    "location": "$message.header#/correlationId"
  },
  "traits": [
    { "$ref": "#/components/messageTraits/commonHeaders" }
  ],
  "examples": [
    {
      "name": "SimpleSignup",
      "summary": "A simple UserSignup example message",
      "headers": {
        "correlationId": "my-correlation-id",
        "applicationInstanceId": "myInstanceId"
      },
      "payload": {
        "user": {
          "someUserKey": "someUserValue"
        },
        "signup": {
          "someSignupKey": "someSignupValue"
        }
      }
    }
  ]
}
```

<!-- asyncapi-example-tester:{"name":"Message Object","json_pointer":"/components/messages/userSignedUp"} -->
```yaml
name: UserSignup
title: User signup
summary: Action to sign a user up.
description: A longer description
contentType: application/json
tags:
  - name: user
  - name: signup
  - name: register
headers:
  type: object
  properties:
    correlationId:
      description: Correlation ID set by application
      type: string
    applicationInstanceId:
      description: Unique identifier for a given instance of the publishing application
      type: string
payload:
  type: object
  properties:
    user:
      $ref: '#/components/schemas/userCreate'
    signup:
      $ref: '#/components/schemas/signup'
correlationId:
  description: Default Correlation ID
  location: $message.header#/correlationId
traits:
  - $ref: '#/components/messageTraits/commonHeaders'
examples:
  - name: SimpleSignup
    summary: A simple UserSignup example message
    headers:
      correlationId: my-correlation-id
      applicationInstanceId: myInstanceId
    payload:
      user:
        someUserKey: someUserValue
      signup:
        someSignupKey: someSignupValue
```

Example using Avro to define the payload:

<!-- asyncapi-example-tester:{"name":"Message Object","json_pointer":"/components/messages/userSignedUp"} -->
```json
{
  "name": "UserSignup",
  "title": "User signup",
  "summary": "Action to sign a user up.",
  "description": "A longer description",
  "tags": [
    { "name": "user" },
    { "name": "signup" },
    { "name": "register" }
  ],
  "payload": {
    "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0",
    "schema": {
      "$ref": "./user-create.avsc"
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Message Object","json_pointer":"/components/messages/userSignedUp"} -->
```yaml
name: UserSignup
title: User signup
summary: Action to sign a user up.
description: A longer description
tags:
  - name: user
  - name: signup
  - name: register
payload:
  schemaFormat: 'application/vnd.apache.avro+yaml;version=1.9.0'
  schema:
    $ref: './user-create.avsc'
```

#### <a name="messageTraitObject"></a>Message Trait Object

Describes a trait that MAY be applied to a [Message Object](#messageObject). This object MAY contain any property from the [Message Object](#messageObject), except `payload` and `traits`.

If you're looking to apply traits to an operation, see the [Operation Trait Object](#operationTraitObject).

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageTraitObjectHeaders"></a>headers | [Multi Format Schema Object](#multiFormatSchemaObject) &#124; [Schema Object](#schemaObject) &#124; [Reference Object](#referenceObject) | Schema definition of the application headers. Schema MUST be a map of key-value pairs. It **MUST NOT** define the protocol headers. If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString).
<a name="messageTraitObjectCorrelationId"></a>correlationId | [Correlation ID Object](#correlationIdObject) &#124; [Reference Object](#referenceObject) | Definition of the correlation ID used for message tracing or matching.
<a name="messageTraitObjectContentType"></a>contentType | `string` | The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type (e.g. `application/json`). When omitted, the value MUST be the one specified on the [defaultContentType](#defaultContentTypeString) field.
<a name="messageTraitObjectName"></a>name | `string` | A machine-friendly name for the message.
<a name="messageTraitObjectTitle"></a>title | `string` | A human-friendly title for the message.
<a name="messageTraitObjectSummary"></a>summary | `string` | A short summary of what the message is about.
<a name="messageTraitObjectDescription"></a>description | `string` | A verbose explanation of the message. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="messageTraitObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of messages.
<a name="messageTraitObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this message.
<a name="messageTraitObjectBindings"></a>bindings | [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message.
<a name="messageTraitObjectExamples"></a>examples | [[Message Example Object](#messageExampleObject)] | List of examples.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Message Trait Object Example

<!-- asyncapi-example-tester:{"name":"Message Trait Object","json_pointer":"/components/messageTraits/commonHeaders"} -->
```json
{
  "contentType": "application/json"
}
```

<!-- asyncapi-example-tester:{"name":"Message Trait Object","json_pointer":"/components/messageTraits/commonHeaders"} -->
```yaml
contentType: application/json
```

#### <a name="messageExampleObject"></a> Message Example Object

Message Example Object represents an example of a [Message Object](#messageObject) and MUST contain either **headers** and/or **payload** fields.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageExampleObjectHeaders"></a>headers | `Map[string, any]` | The value of this field MUST validate against the [Message Object's headers](#messageObjectHeaders) field.
<a name="messageExampleObjectPayload"></a>payload | `any` | The value of this field MUST validate against the [Message Object's payload](#messageObjectPayload) field.
<a name="messageExampleObjectName"></a>name | `string` | A machine-friendly name.
<a name="messageExampleObjectSummary"></a>summary | `string` |  A short summary of what the example is about.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Message Example Object Example

<!-- asyncapi-example-tester:{"name":"Message Example Object","json_pointer":"/components/messages/userSignUp/examples/0"} -->
```json
{
  "name": "SimpleSignup",
  "summary": "A simple UserSignup example message",
  "headers": {
    "correlationId": "my-correlation-id",
    "applicationInstanceId": "myInstanceId"
  },
  "payload": {
    "user": {
      "someUserKey": "someUserValue"
    },
    "signup": {
      "someSignupKey": "someSignupValue"
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Message Example Object","json_pointer":"/components/messages/userSignUp/examples/0"} -->
```yaml
name: SimpleSignup
summary: A simple UserSignup example message
headers:
  correlationId: my-correlation-id
  applicationInstanceId: myInstanceId
payload:
  user:
    someUserKey: someUserValue
  signup:
    someSignupKey: someSignupValue
```

#### <a name="tagsObject"></a>Tags Object

A Tags object is a list of [Tag Objects](#tagObject). An [Tag Object](#tagObject) in a list can be referenced by [Reference Object](#referenceObject).

#### <a name="tagObject"></a>Tag Object

Allows adding meta data to a single tag.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="tagObjectName"></a>name | `string` | **REQUIRED.** The name of the tag.
<a name="tagObjectDescription"></a>description | `string` | A short description for the tag. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="tagObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this tag.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Tag Object Example

<!-- asyncapi-example-tester:{"name":"Tag Object","json_pointer":"/components/tags/user"} -->
```json
{
 "name": "user",
 "description": "User-related messages"
}
```

<!-- asyncapi-example-tester:{"name":"Tag Object","json_pointer":"/components/tags/user"} -->
```yaml
name: user
description: User-related messages
```

#### <a name="externalDocumentationObject"></a>External Documentation Object

Allows referencing an external resource for extended documentation.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="externalDocDescription"></a>description | `string` | A short description of the target documentation. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="externalDocUrl"></a>url | `string` | **REQUIRED.** The URL for the target documentation. This MUST be in the form of an absolute URL.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### External Documentation Object Example

<!-- asyncapi-example-tester:{"name":"External Docs Object","json_pointer":"/components/externalDocs/infoDocs"} -->
```json
{
  "description": "Find more info here",
  "url": "https://example.com"
}
```

<!-- asyncapi-example-tester:{"name":"External Docs Object","json_pointer":"/components/externalDocs/infoDocs"} -->
```yaml
description: Find more info here
url: https://example.com
```

#### <a name="referenceObject"></a>Reference Object

A simple object to allow referencing other components in the specification, internally and externally.

The Reference Object is defined by [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) and follows the same structure, behavior and rules. A JSON Reference SHALL only be used to refer to a schema that is formatted in either JSON or YAML. In the case of a YAML-formatted Schema, the JSON Reference SHALL be applied to the JSON representation of that schema. The JSON representation SHALL be made by applying the conversion described [here](#format).

For this specification, reference resolution is done as defined by the JSON Reference specification and not by the JSON Schema specification.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="referenceRef"></a>$ref | `string` | **REQUIRED.** The reference string.

This object cannot be extended with additional properties and any properties added SHALL be ignored.

##### Reference Object Example

<!-- asyncapi-example-tester:{"name":"Reference Object","json_pointer":"/components/messages/userSignUp/payload"} -->
```json
{
  "$ref": "#/components/schemas/Pet"
}
```

<!-- asyncapi-example-tester:{"name":"Reference Object","json_pointer":"/components/messages/userSignUp/payload"} -->
```yaml
  $ref: '#/components/schemas/Pet'
```

#### <a name="componentsObject"></a>Components Object

Holds a set of reusable objects for different aspects of the AsyncAPI specification.
All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object.

##### Fixed Fields

Field Name | Type | Description
---|:---|---
<a name="componentsSchemas"></a> schemas | Map[`string`, [Multi Format Schema Object](#multiFormatSchemaObject) \| [Schema Object](#schemaObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Schema Object](#schemaObject). If this is a [Schema Object](#schemaObject), then the `schemaFormat` will be assumed to be "application/vnd.aai.asyncapi+json;version=`asyncapi`" where the version is equal to the [AsyncAPI Version String](#A2SVersionString).
<a name="componentsServers"></a> servers | Map[`string`, [Server Object](#serverObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Objects](#serverObject).
<a name="componentsChannels"></a> channels | Map[`string`, [Channel Object](#channelObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Channel Objects](#channelObject).
<a name="componentsOperations"></a> operations | Map[`string`, [Operation Object](#operationObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Objects](#operationObject).
<a name="componentsMessages"></a> messages | Map[`string`, [Message Object](#messageObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Message Objects](#messageObject).
<a name="componentsSecuritySchemes"></a> securitySchemes| Map[`string`, [Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Security Scheme Objects](#securitySchemeObject).
<a name="componentsServerVariables"></a> serverVariables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Server Variable Objects](#serverVariableObject).
<a name="componentsParameters"></a> parameters | Map[`string`, [Parameter Object](#parameterObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Parameter Objects](#parameterObject).
<a name="componentsCorrelationIDs"></a> correlationIds | Map[`string`, [Correlation ID Object](#correlationIdObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Correlation ID Objects](#correlationIdObject).
<a name="componentsReplies"></a>replies | Map[`string`, [Operation Reply Object](#operationReplyObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Operation Reply Objects](#operationReplyObject).
<a name="componentsReplyAddresses"></a> replyAddresses | Map[`string`, [Operation Reply Address Object](#operationReplyAddressObject) &#124; [Reference Object](#referenceObject)] | An object to hold reusable [Operation Reply Address Objects](#operationReplyAddressObject).
<a name="componentsExternalDocs"></a> externalDocs | Map[`string`, [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [External Documentation Objects](#externalDocumentationObject).
<a name="componentsTags"></a> tags | Map[`string`, [Tag Object](#tagObject) \| [Reference Object](#referenceObject)] | An object to hold reusable [Tag Objects](#tagObject).
<a name="componentsOperationTraits"></a> operationTraits | Map[`string`, [Operation Trait Object](#operationTraitObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Operation Trait Objects](#operationTraitObject).
<a name="componentsMessageTraits"></a> messageTraits | Map[`string`, [Message Trait Object](#messageTraitObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Message Trait Objects](#messageTraitObject).
<a name="componentsServerBindings"></a> serverBindings | Map[`string`, [Server Bindings Object](#serverBindingsObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Server Bindings Objects](#serverBindingsObject).
<a name="componentsChannelBindings"></a> channelBindings | Map[`string`, [Channel Bindings Object](#channelBindingsObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Channel Bindings Objects](#channelBindingsObject).
<a name="componentsOperationBindings"></a> operationBindings | Map[`string`, [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Operation Bindings Objects](#operationBindingsObject).
<a name="componentsMessageBindings"></a> messageBindings | Map[`string`, [Message Bindings Object](#messageBindingsObject) \| [Reference Object](#referenceObject)]  | An object to hold reusable [Message Bindings Objects](#messageBindingsObject).

This object MAY be extended with [Specification Extensions](#specificationExtensions).

All the fixed fields declared above are objects that MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`.

Field Name Examples:

```text
User
User_1
User_Name
user-name
my.org.User
```

##### Components Object Example

<!-- asyncapi-example-tester:{"name":"Components Object","json_pointer":""} -->
```json
{
  "components": {
    "schemas": {
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Tag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "AvroExample": {
        "schemaFormat": "application/vnd.apache.avro+json;version=1.9.0",
        "schema": {
          "$ref": "./user-create.avsc"
        }
      }
    },
    "servers": {
      "development": {
        "host": "{stage}.in.mycompany.com:{port}",
        "description": "RabbitMQ broker",
        "protocol": "amqp",
        "protocolVersion": "0-9-1",
        "variables": {
          "stage": {
            "$ref": "#/components/serverVariables/stage"
          },
          "port": {
            "$ref": "#/components/serverVariables/port"
          }
        }
      }
    },
    "serverVariables": {
      "stage": {
        "default": "demo",
        "description": "This value is assigned by the service provider, in this example `mycompany.com`"
      },
      "port": {
        "enum": ["5671", "5672"],
        "default": "5672"
      }
    },
    "channels": {
      "user/signedup": {
        "subscribe": {
          "message": {
            "$ref": "#/components/messages/userSignUp"
          }
        }
      }
    },
    "messages": {
      "userSignUp": {
        "summary": "Action to sign a user up.",
        "description": "Multiline description of what this action does.\nHere you have another line.\n",
        "tags": [
          {
            "name": "user"
          },
          {
            "name": "signup"
          }
        ],
        "headers": {
          "type": "object",
          "properties": {
            "applicationInstanceId": {
              "description": "Unique identifier for a given instance of the publishing application",
              "type": "string"
            }
          }
        },
        "payload": {
          "type": "object",
          "properties": {
            "user": {
              "$ref": "#/components/schemas/userCreate"
            },
            "signup": {
              "$ref": "#/components/schemas/signup"
            }
          }
        }
      }
    },
    "parameters": {
      "userId": {
        "description": "Id of the user."
      }
    },
    "correlationIds": {
      "default": {
        "description": "Default Correlation ID",
        "location": "$message.header#/correlationId"
      }
    },
    "messageTraits": {
      "commonHeaders": {
        "headers": {
          "type": "object",
          "properties": {
            "my-app-header": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          }
        }
      }
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Components Object","json_pointer":""} -->
```yaml
components:
  schemas:
    Category:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    Tag:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    AvroExample:
      schemaFormat: 'application/vnd.apache.avro+json;version=1.9.0'
      schema:
        $ref: './user-create.avsc'
  servers:
    development:
      host: '{stage}.in.mycompany.com:{port}'
      description: RabbitMQ broker
      protocol: amqp
      protocolVersion: 0-9-1
      variables:
        stage:
          $ref: '#/components/serverVariables/stage'
        port:
          $ref: '#/components/serverVariables/port'
  serverVariables:
    stage:
      default: demo
      description: |
        This value is assigned by the service provider, in this example
        `mycompany.com`
    port:
      enum:
        - '5671'
        - '5672'
      default: '5672'
  channels:
    user/signedup:
      subscribe:
        message:
          $ref: '#/components/messages/userSignUp'
  messages:
    userSignUp:
      summary: Action to sign a user up.
      description: |
        Multiline description of what this action does.
        Here you have another line.
      tags:
        - name: user
        - name: signup
      headers:
        type: object
        properties:
          applicationInstanceId:
            description: |
              Unique identifier for a given instance of the publishing
              application
            type: string
      payload:
        type: object
        properties:
          user:
            $ref: '#/components/schemas/userCreate'
          signup:
            $ref: '#/components/schemas/signup'
  parameters:
    userId:
      description: Id of the user.
  correlationIds:
    default:
      description: Default Correlation ID
      location: '$message.header#/correlationId'
  messageTraits:
    commonHeaders:
      headers:
        type: object
        properties:
          my-app-header:
            type: integer
            minimum: 0
            maximum: 100
```

#### <a name="multiFormatSchemaObject"></a>Multi Format Schema Object

The Multi Format Schema Object represents a schema definition. It differs from the [Schema Object](#schemaObject) in that it supports multiple schema formats or languages (e.g., JSON Schema, Avro, etc.).

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="multiFormatSchemaObjectSchemaFormat"></a>schemaFormat | `string` | **Required**. A string containing the name of the schema format that is used to define the information. If `schemaFormat` is missing, it MUST default to `application/vnd.aai.asyncapi+json;version={{asyncapi}}` where `{{asyncapi}}` matches the [AsyncAPI Version String](#A2SVersionString). In such a case, this would make the Multi Format Schema Object equivalent to the [Schema Object](#schemaObject). When using [Reference Object](#referenceObject) within the schema, the `schemaFormat` of the resource being referenced MUST match the `schemaFormat` of the schema that contains the initial reference. For example, if you reference Avro `schema`, then `schemaFormat` of referencing resource and the resource being reference MUST match. <br/><br/>Check out the [supported schema formats table](#multiFormatSchemaFormatTable) for more information. Custom values are allowed but their implementation is OPTIONAL. A custom value MUST NOT refer to one of the schema formats listed in the [table](#multiFormatSchemaFormatTable).<br/><br/>When using [Reference Objects](#referenceObject) within the schema, the `schemaFormat` of the referenced resource MUST match the `schemaFormat` of the schema containing the reference.
<a name="multiFormatSchemaObjectSchema"></a>schema | `any` | **Required**. Definition of the message payload. It can be of any type but defaults to [Schema Object](#schemaObject). It MUST match the schema format defined in [`schemaFormat`](#multiFormatSchemaObjectSchemaFormat), including the encoding type. E.g., Avro should be inlined as either a YAML or JSON object instead of as a string to be parsed as YAML or JSON. Non-JSON-based schemas (e.g., Protobuf or XSD) MUST be inlined as a string.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### <a name="multiFormatSchemaFormatTable"></a>Schema formats table

The following table contains a set of values that every implementation MUST support.

Name | Allowed values | Notes
---|:---:|---
[AsyncAPI 3.1.0 Schema Object](#schemaObject) | `application/vnd.aai.asyncapi;version=3.1.0`, `application/vnd.aai.asyncapi+json;version=3.1.0`, `application/vnd.aai.asyncapi+yaml;version=3.1.0` | This is the default when a `schemaFormat` is not provided.
[JSON Schema Draft 07](https://json-schema.org/specification-links.html#draft-7) | `application/schema+json;version=draft-07`, `application/schema+yaml;version=draft-07` |

The following table contains a set of values that every implementation is RECOMMENDED to support.

Name | Allowed values | Notes
---|:---:|---
[Avro 1.9.0 schema](https://avro.apache.org/docs/1.9.0/spec.html#schemas) | `application/vnd.apache.avro;version=1.9.0`, `application/vnd.apache.avro+json;version=1.9.0`, `application/vnd.apache.avro+yaml;version=1.9.0` |
[OpenAPI 3.0.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.0.0`, `application/vnd.oai.openapi+json;version=3.0.0`, `application/vnd.oai.openapi+yaml;version=3.0.0` |
[RAML 1.0 data type](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/) | `application/raml+yaml;version=1.0` |
[Protocol Buffers](https://protobuf.dev/) | `application/vnd.google.protobuf;version=2`, `application/vnd.google.protobuf;version=3` |

##### Multi Format Schema Object Examples

###### Multi Format Schema Object Example with Avro

<!-- asyncapi-example-tester:{"name":"Multi Format Schema Object - Avro","json_pointer":""} -->
```yaml
channels:
  example:
    messages:
      myMessage:
        payload:
          schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
          schema:
            type: record
            name: User
            namespace: com.company
            doc: User information
            fields:
              - name: displayName
                type: string
              - name: age
                type: int
```

#### <a name="schemaObject"></a>Schema Object

The Schema Object allows the definition of input and output data types.
These types can be objects, but also primitives and arrays. This object is a superset of the [JSON Schema Specification Draft 07](https://json-schema.org/). The empty schema (which allows any instance to validate) MAY be represented by the `boolean` value `true` and a schema which allows no instance to validate MAY be represented by the `boolean` value `false`.

Further information about the properties can be found in [JSON Schema Core](https://tools.ietf.org/html/draft-handrews-json-schema-01) and [JSON Schema Validation](https://tools.ietf.org/html/draft-handrews-json-schema-validation-01).
Unless stated otherwise, the property definitions follow the JSON Schema specification as referenced here. For other formats (e.g., Avro, RAML, etc) see [Multi Format Schema Object](#multiFormatSchemaObject).

##### Properties

The AsyncAPI Schema Object is a JSON Schema vocabulary which extends JSON Schema Core and Validation vocabularies. As such, any keyword available for those vocabularies is by definition available in AsyncAPI, and will work the exact same way, including but not limited to:

- title
- type
- required
- multipleOf
- maximum
- exclusiveMaximum
- minimum
- exclusiveMinimum
- maxLength
- minLength
- pattern (This string SHOULD be a valid regular expression, according to the [ECMA 262 regular expression](https://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5) dialect)
- maxItems
- minItems
- uniqueItems
- maxProperties
- minProperties
- enum
- const
- examples
- if / then / else
- readOnly
- writeOnly
- properties
- patternProperties
- additionalProperties
- additionalItems
- items
- propertyNames
- contains
- allOf
- oneOf
- anyOf
- not

The following properties are taken from the JSON Schema definition but their definitions were adjusted to the AsyncAPI Specification.

- description - [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
- format - See [Data Type Formats](#dataTypeFormat) for further details. While relying on JSON Schema's defined formats, the AsyncAPI Specification offers a few additional predefined formats.
- default - Use it to specify that property has a predefined value if no other value is present. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, of `type` is `string`, then `default` can be `"foo"` but cannot be `1`.

Alternatively, any time a Schema Object can be used, a [Reference Object](#referenceObject) can be used in its place. This allows referencing definitions in place of defining them inline. It is appropriate to clarify that the `$ref` keyword MUST follow the behavior described by [Reference Object](#referenceObject) instead of the one in [JSON Schema definition](https://json-schema.org/understanding-json-schema/structuring.html#ref).

In addition to the JSON Schema fields, the following AsyncAPI vocabulary fields MAY be used for further schema documentation:

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="schemaObjectDiscriminator"></a>discriminator | `string` | Adds support for polymorphism. The discriminator is the schema property name that is used to differentiate between other schema that inherit this schema. The property name used MUST be defined at this schema and it MUST be in the `required` property list. When used, the value MUST be the name of this schema or any schema that inherits it. See [Composition and Inheritance](#schemaComposition) for more details.
<a name="schemaObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this schema.
<a name="schemaObjectDeprecated"></a> deprecated | `boolean` | Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is `false`.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

###### <a name="schemaComposition"></a>Composition and Inheritance (Polymorphism)

The AsyncAPI Specification allows combining and extending model definitions using the `allOf` property of JSON Schema, in effect offering model composition.
`allOf` takes in an array of object definitions that are validated _independently_ but together compose a single object.

While composition offers model extensibility, it does not imply a hierarchy between the models.
To support polymorphism, AsyncAPI Specification adds the support of the `discriminator` field.
When used, the `discriminator` will be the name of the property used to decide which schema definition is used to validate the structure of the model.
As such, the `discriminator` field MUST be a required field.
There are two ways to define the value of a discriminator for an inheriting instance.

- Use the schema's name.
- Override the schema's name by overriding the property with a new value. If exists, this takes precedence over the schema's name.

As such, inline schema definitions, which do not have a given id, _cannot_ be used in polymorphism.

##### Schema Object Examples

###### Primitive Sample

<!-- asyncapi-example-tester:{"name":"Schema Object - Primitive","json_pointer":"/components/schemas/Email"} -->
```json
{
  "type": "string",
  "format": "email"
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - Primitive","json_pointer":"/components/schemas/Email"} -->
```yaml
type: string
format: email
```

###### Simple Model

<!-- asyncapi-example-tester:{"name":"Schema Object - Simple model","json_pointer":"/components/schemas/Person"} -->
```json
{
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "address": {
      "$ref": "#/components/schemas/Address"
    },
    "age": {
      "type": "integer",
      "format": "int32",
      "minimum": 0
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - Simple model","json_pointer":"/components/schemas/Person"} -->
```yaml
type: object
required:
- name
properties:
  name:
    type: string
  address:
    $ref: '#/components/schemas/Address'
  age:
    type: integer
    format: int32
    minimum: 0
```

###### Model with Map/Dictionary Properties

For a simple string to string mapping:

<!-- asyncapi-example-tester:{"name":"Schema Object - Map-Dictionary model","json_pointer":"/components/schemas/Additional"} -->
```json
{
  "type": "object",
  "additionalProperties": {
    "type": "string"
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - Map-Dictionary model","json_pointer":"/components/schemas/Additional"} -->
```yaml
type: object
additionalProperties:
  type: string
```

For a string to model mapping:

<!-- asyncapi-example-tester:{"name":"Schema Object - Allowing Complex model","json_pointer":"/components/schemas/WithComplex"} -->
```json
{
  "type": "object",
  "additionalProperties": {
    "$ref": "#/components/schemas/ComplexModel"
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - Allowing Complex model","json_pointer":"/components/schemas/WithComplex"} -->
```yaml
type: object
additionalProperties:
  $ref: '#/components/schemas/ComplexModel'
```

###### Model with Example

<!-- asyncapi-example-tester:{"name":"Schema Object - With examples model","json_pointer":"/components/schemas/WithExamples"} -->
```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "format": "int64"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "name"
  ],
  "examples": [
    {
      "name": "Puma",
      "id": 1
    }
  ]
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - With examples model","json_pointer":"/components/schemas/WithExamples"} -->
```yaml
type: object
properties:
  id:
    type: integer
    format: int64
  name:
    type: string
required:
- name
examples:
- name: Puma
  id: 1
```

###### Model with Boolean Schemas

<!-- asyncapi-example-tester:{"name":"Schema Object - With boolean model","json_pointer":"/components/schemas/WithBoolean"} -->
```json
{
  "type": "object",
  "required": [
    "anySchema"
  ],
  "properties": {
    "anySchema": true,
    "cannotBeDefined": false
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - With boolean model","json_pointer":"/components/schemas/WithBoolean"} -->
```yaml
type: object
required:
- anySchema
properties:
  anySchema: true
  cannotBeDefined: false
```

###### Models with Composition

<!-- asyncapi-example-tester:{"name":"Schema Object - With composition model","json_pointer":"/components/schemas/WithComposition"} -->
```json
{
  "schemas": {
    "ErrorModel": {
      "type": "object",
      "required": [
        "message",
        "code"
      ],
      "properties": {
        "message": {
          "type": "string"
        },
        "code": {
          "type": "integer",
          "minimum": 100,
          "maximum": 600
        }
      }
    },
    "ExtendedErrorModel": {
      "allOf": [
        {
          "$ref": "#/components/schemas/ErrorModel"
        },
        {
          "type": "object",
          "required": [
            "rootCause"
          ],
          "properties": {
            "rootCause": {
              "type": "string"
            }
          }
        }
      ]
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - With composition model","json_pointer":"/components/schemas/WithComposition"} -->
```yaml
schemas:
  ErrorModel:
    type: object
    required:
    - message
    - code
    properties:
      message:
        type: string
      code:
        type: integer
        minimum: 100
        maximum: 600
  ExtendedErrorModel:
    allOf:
    - $ref: '#/components/schemas/ErrorModel'
    - type: object
      required:
      - rootCause
      properties:
        rootCause:
          type: string
```

###### Models with Polymorphism Support

<!-- asyncapi-example-tester:{"name":"Schema Object - With polymorphism model","json_pointer":"/components/schemas/WithPolymorphism"} -->
```json
{
  "schemas": {
    "Pet": {
      "type": "object",
      "discriminator": "petType",
      "properties": {
        "name": {
          "type": "string"
        },
        "petType": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "petType"
      ]
    },
    "Cat": {
      "description": "A representation of a cat. Note that `Cat` will be used as the discriminator value.",
      "allOf": [
        {
          "$ref": "#/components/schemas/Pet"
        },
        {
          "type": "object",
          "properties": {
            "huntingSkill": {
              "type": "string",
              "description": "The measured skill for hunting",
              "enum": [
                "clueless",
                "lazy",
                "adventurous",
                "aggressive"
              ]
            }
          },
          "required": [
            "huntingSkill"
          ]
        }
      ]
    },
    "Dog": {
      "description": "A representation of a dog. Note that `Dog` will be used as the discriminator value.",
      "allOf": [
        {
          "$ref": "#/components/schemas/Pet"
        },
        {
          "type": "object",
          "properties": {
            "packSize": {
              "type": "integer",
              "format": "int32",
              "description": "the size of the pack the dog is from",
              "minimum": 0
            }
          },
          "required": [
            "packSize"
          ]
        }
      ]
    },
    "StickInsect": {
      "description": "A representation of an Australian walking stick. Note that `StickBug` will be used as the discriminator value.",
      "allOf": [
        {
          "$ref": "#/components/schemas/Pet"
        },
        {
          "type": "object",
          "properties": {
            "petType": {
              "const": "StickBug"
            },
            "color": {
              "type": "string"
            }
          },
          "required": [
            "color"
          ]
        }
      ]
    }
  }
}
```

<!-- asyncapi-example-tester:{"name":"Schema Object - With polymorphism model","json_pointer":"/components/schemas/WithPolymorphism"} -->
```yaml
schemas:
  Pet:
    type: object
    discriminator: petType
    properties:
      name:
        type: string
      petType:
        type: string
    required:
    - name
    - petType
  ## applies to instances with `petType: "Cat"`
  ## because that is the schema name
  Cat:
    description: A representation of a cat
    allOf:
    - $ref: '#/components/schemas/Pet'
    - type: object
      properties:
        huntingSkill:
          type: string
          description: The measured skill for hunting
          enum:
          - clueless
          - lazy
          - adventurous
          - aggressive
      required:
      - huntingSkill
  ## applies to instances with `petType: "Dog"`
  ## because that is the schema name
  Dog:
    description: A representation of a dog
    allOf:
    - $ref: '#/components/schemas/Pet'
    - type: object
      properties:
        packSize:
          type: integer
          format: int32
          description: the size of the pack the dog is from
          minimum: 0
      required:
      - packSize
  ## applies to instances with `petType: "StickBug"`
  ## because that is the required value of the discriminator field,
  ## overriding the schema name
  StickInsect:
    description: A representation of an Australian walking stick
    allOf:
    - $ref: '#/components/schemas/Pet'
    - type: object
      properties:
        petType:
          const: StickBug
        color:
          type: string
      required:
      - color
```

#### <a name="securitySchemeObject"></a>Security Scheme Object

Defines a security scheme that can be used by the operations. Supported schemes are:

- User/Password.
- API key (either as user or as password).
- X.509 certificate.
- End-to-end encryption (either symmetric or asymmetric).
- HTTP authentication.
- HTTP API key.
- OAuth2's common flows (Implicit, Resource Owner Protected Credentials, Client Credentials and Authorization Code) as defined in [RFC6749](https://tools.ietf.org/html/rfc6749).
- [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06).
- SASL (Simple Authentication and Security Layer) as defined in [RFC4422](https://tools.ietf.org/html/rfc4422).

##### Fixed Fields

Field Name | Type | Applies To | Description
---|:---:|---|---
<a name="securitySchemeObjectType"></a>type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"userPassword"`, `"apiKey"`, `"X509"`, `"symmetricEncryption"`, `"asymmetricEncryption"`, `"httpApiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`, `"plain"`, `"scramSha256"`, `"scramSha512"`, and `"gssapi"`.
<a name="securitySchemeObjectDescription"></a>description | `string` | Any | A short description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
<a name="securitySchemeObjectName"></a>name | `string` | `httpApiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used.
<a name="securitySchemeObjectIn"></a>in | `string` | `apiKey` \| `httpApiKey` | **REQUIRED**. The location of the API key. Valid values are `"user"` and `"password"` for `apiKey` and `"query"`, `"header"` or `"cookie"` for `httpApiKey`.
<a name="securitySchemeObjectScheme"></a>scheme | `string` | `http` | **REQUIRED**. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1).
<a name="securitySchemeObjectBearerFormat"></a>bearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted.  Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.
<a name="securitySchemeFlows"></a>flows | [OAuth Flows Object](#oauthFlowsObject) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported.
<a name="securitySchemeOpenIdConnectUrl"></a>openIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of an absolute URL.
<a name="securitySchemeScopes"></a>scopes | [`string`] | `oauth2` \| `openIdConnect` | List of the needed scope names. An empty array means no scopes are needed.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Security Scheme Object Example

###### User/Password Authentication Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - user-pass","json_pointer":"/components/securitySchemes/userPasswordAuth"} -->
```json
{
  "type": "userPassword"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - user-pass","json_pointer":"/components/securitySchemes/userPasswordAuth"} -->
```yaml
type: userPassword
```

###### API Key Authentication Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - API key auth","json_pointer":"/components/securitySchemes/apiKeyAuth"} -->
```json
{
  "type": "apiKey",
  "in": "user"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - API key auth","json_pointer":"/components/securitySchemes/apiKeyAuth"} -->
```yaml
type: apiKey
in: user
```

###### X.509 Authentication Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - X.509","json_pointer":"/components/securitySchemes/X509Auth"} -->
```json
{
  "type": "X509"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - X.509","json_pointer":"/components/securitySchemes/X509Auth"} -->
```yaml
type: X509
```

###### End-to-end Encryption Authentication Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - end to end encryption","json_pointer":"/components/securitySchemes/symmetricEncryptionAuth"} -->
```json
{
  "type": "symmetricEncryption"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - end to end encryption","json_pointer":"/components/securitySchemes/symmetricEncryptionAuth"} -->
```yaml
type: symmetricEncryption
```

###### Basic Authentication Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - basic","json_pointer":"/components/securitySchemes/basicAuth"} -->
```json
{
  "type": "http",
  "scheme": "basic"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - basic","json_pointer":"/components/securitySchemes/basicAuth"} -->
```yaml
type: http
scheme: basic
```

###### API Key Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - API key","json_pointer":"/components/securitySchemes/httpApiAuth"} -->
```json
{
  "type": "httpApiKey",
  "name": "api_key",
  "in": "header"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - API key","json_pointer":"/components/securitySchemes/httpApiAuth"} -->
```yaml
type: httpApiKey
name: api_key
in: header
```

###### JWT Bearer Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - JWT","json_pointer":"/components/securitySchemes/JWTAuth"} -->
```json
{
  "type": "http",
  "scheme": "bearer",
  "bearerFormat": "JWT"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - JWT","json_pointer":"/components/securitySchemes/JWTAuth"} -->
```yaml
type: http
scheme: bearer
bearerFormat: JWT
```

###### Implicit OAuth2 Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - implicity OAuth2","json_pointer":"/components/securitySchemes/oauth"} -->
```json
{
  "type": "oauth2",
  "flows": {
    "implicit": {
      "authorizationUrl": "https://example.com/api/oauth/dialog",
      "availableScopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    }
  },
  "scopes": [
    "write:pets"
  ]
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - implicity OAuth2","json_pointer":"/components/securitySchemes/oauth"} -->
```yaml
type: oauth2
flows:
  implicit:
    authorizationUrl: https://example.com/api/oauth/dialog
    availableScopes:
      write:pets: modify pets in your account
      read:pets: read your pets
scopes:
  - 'write:pets'
```

###### SASL Sample

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - SASL","json_pointer":"/components/securitySchemes/saslAuth"} -->
```json
{
  "type": "scramSha512"
}
```

<!-- asyncapi-example-tester:{"name":"Security Scheme Object - SASL","json_pointer":"/components/securitySchemes/saslAuth"} -->
```yaml
type: scramSha512
```

#### <a name="oauthFlowsObject"></a>OAuth Flows Object

Allows configuration of the supported OAuth Flows.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="oauthFlowsImplicit"></a>implicit| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Implicit flow.
<a name="oauthFlowsPassword"></a>password| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Resource Owner Protected Credentials flow.
<a name="oauthFlowsClientCredentials"></a>clientCredentials| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Client Credentials flow.
<a name="oauthFlowsAuthorizationCode"></a>authorizationCode| [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Authorization Code flow.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

#### <a name="oauthFlowObject"></a>OAuth Flow Object

Configuration details for a supported OAuth Flow

##### Fixed Fields

Field Name | Type | Applies To | Description
---|:---:|---|---
<a name="oauthFlowAuthorizationUrl"></a>authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of an absolute URL.
<a name="oauthFlowTokenUrl"></a>tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of an absolute URL.
<a name="oauthFlowRefreshUrl"></a>refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of an absolute URL.
<a name="oauthFlowScopes"></a>availableScopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### OAuth Flow Object Examples

###### clientCredentials Oauth Flow Object Example

<!-- asyncapi-example-tester:{"name":"Security Scheme OAuth Flow Object","json_pointer":"/components/securitySchemes/oauth/flows/clientCredentials"} -->
```json
{
  "tokenUrl": "https://example.com/api/oauth/token",
  "availableScopes": {
    "write:pets": "modify pets in your account",
    "read:pets": "read your pets"
  }
}
```
<!-- asyncapi-example-tester:{"name":"Security Scheme OAuth Flow Object","json_pointer":"/components/securitySchemes/oauth/flows/clientCredentials"} -->
```yaml
tokenUrl: https://example.com/api/oauth/token
availableScopes:
  write:pets: modify pets in your account
  read:pets: read your pets
```

### <a name="correlationIdObject"></a>Correlation ID Object

An object that specifies an identifier at design time that can used for message tracing and correlation.

For specifying and computing the location of a Correlation ID, a [runtime expression](#runtimeExpression) is used.

#### Fixed Fields

Field Name | Type | Description
---|:---|---
description | `string` | An optional description of the identifier. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
location | `string` | **REQUIRED.** A [runtime expression](#runtimeExpression) that specifies the location of the correlation ID.

This object MAY be extended with [Specification Extensions](#specificationExtensions).

##### Examples

<!-- asyncapi-example-tester:{"name":"Message Correlation ID Object","json_pointer":"/components/correlationIds/default"} -->
```json
{
  "description": "Default Correlation ID",
  "location": "$message.header#/correlationId"
}
```

<!-- asyncapi-example-tester:{"name":"Message Correlation ID Object","json_pointer":"/components/correlationIds/default"} -->
```yaml
description: Default Correlation ID
location: $message.header#/correlationId
```

### <a name="runtimeExpression"></a>Runtime Expression

A runtime expression allows values to be defined based on information that will be available within the message.
This mechanism is used by [Correlation ID Object](#correlationIdObject) and [Operation Reply Address Object](#operationReplyAddressObject).

The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax:

```text
      expression = ( "$message" "." source )
      source = ( header-reference | payload-reference )
      header-reference = "header" ["#" fragment]
      payload-reference = "payload" ["#" fragment]
      fragment = a JSON Pointer [RFC 6901](https://tools.ietf.org/html/rfc6901)
```

The table below provides examples of runtime expressions and examples of their use in a value:

#### <a name="runtimeExpressionExamples"></a>Examples

Source Location | Example expression  | Notes
---|:---|:---|
Message Header Property | `$message.header#/MQMD/CorrelId` | Correlation ID is set using the `CorrelId` value from the `MQMD` header.
Message Payload Property | `$message.payload#/messageId` | Correlation ID is set using the `messageId` value from the message payload.

Runtime expressions preserve the type of the referenced value.

### <a name="traitsMergeMechanism"></a>Traits Merge Mechanism

Traits MUST be merged with the target object using the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) algorithm in the same order they are defined. A property on a trait MUST NOT override the same property on the target object.

#### Example

An object like the following:

```yaml
description: A longer description.
traits:
  - name: UserSignup
    description: Description from trait.
  - tags:
      - name: user
```

Would look like the following after applying traits:

```yaml
name: UserSignup
description: A longer description.
tags:
  - name: user
```

### <a name="specificationExtensions"></a>Specification Extensions

While the AsyncAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.

The extensions properties are implemented as patterned fields that are always prefixed by `"x-"`.

Field Pattern | Type | Description
---|:---:|---
<a name="infoExtensions"></a>`^x-[\w\d\.\x2d_]+$` | Any | Allows extensions to the AsyncAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. Can have any valid JSON format value.

The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-sourced).

### <a name="dataTypeFormat"></a>Data Type Formats

Primitives have an optional modifier property: `format`.
The AsyncAPI specification uses several known formats to more finely define the data type being used.
However, the `format` property is an open `string`-valued property, and can have any value to support documentation needs.
Formats such as `"email"`, `"uuid"`, etc., can be used even though they are not defined by this specification.
Types that are not accompanied by a `format` property follow their definition from the JSON Schema.
Tools that do not recognize a specific `format` MAY default back to the `type` alone, as if the `format` was not specified.

The formats defined by the AsyncAPI Specification are:

Common Name | `type` | [`format`](#dataTypeFormat) | Comments
----------- | ------ | -------- | --------
integer | `integer` | `int32` | signed 32 bits
long | `integer` | `int64` | signed 64 bits
float | `number` | `float` | |
double | `number` | `double` | |
string | `string` | | |
byte | `string` | `byte` | base64 encoded characters
binary | `string` | `binary` | any sequence of octets
boolean | `boolean` | | |
date | `string` | `date` | As defined by `full-date` - [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6)
dateTime | `string` | `date-time` | As defined by `date-time` - [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6)
password | `string` | `password` | Used to hint UIs the input needs to be obscured.

---

# Overview
Source: https://www.asyncapi.com/docs/reference/extensions.md

# Overview

## What's an extension?

Extension is a mechanism in AsyncAPI that enables you to add custom fields to an AsyncAPI document. You can define your own extensions or use them only for your use case inside your company. You can also share your extensions with others. This way an extension that is adopted by others can one day become a core part of the AsyncAPI specification.

## Usage in an AsyncAPI document
AsyncAPI extensions are those that are preceded by `x-`. (Example: `x-linkedin`) They can be placed in the AsyncAPI document in locations specified by the documentation of a given extension.

## Adding your extension to the catalog

If you'd like to add your extension to the catalog, please submit a pull request to the [Extensions Catalog](https://github.com/asyncapi/extensions-catalog) repository. Make sure the extension doesn't exist already; otherwise, it's better to improve the existing one.

---

# linkedin
Source: https://www.asyncapi.com/docs/reference/extensions/linkedin.md

# linkedin

# Linkedin Extension
This document defines how to use `linkedin` extension in AsyncAPI documents.

## Overview 
This extension allows you to provide the Linkedin username of the account representing the team/company of the API.

## Version
Current version is `0.1.0`.

## Extension Definition

### Type: String

URL of the Linkedin Profile of the user or company.

## Extension Location 

This extension can be used in the following locations:
- [Info Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#infoObject)

## Example

```yaml
asyncapi: '3.0.0'
info
  title: AsyncAPI Initiative Example
  version: '1.0.0'
  x-linkedin: https://www.linkedin.com/company/asyncapi
```

---

# x
Source: https://www.asyncapi.com/docs/reference/extensions/x.md

# x

# Twitter/X Extension
This document defines how to use `x` extension in AsyncAPI documents.

## Overview 
This extension allows you to provide the Twitter/X username of the account representing the team/company of the API.

## Version
Current version is `0.1.0`.

## Extension Definition

### Type: String

Name of the Twitter/X username.

## Extension Location 

This extension can be used in the following locations:
- [Info Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#infoObject)

## Example

```yaml
asyncapi: '3.0.0'
info
  title: Strretlights Kafka API
  version: '1.0.0'
  x-x: StreetLightData
```

---

# amqp
Source: https://www.asyncapi.com/docs/reference/bindings/amqp.md

# amqp

# AMQP 0-9-1 Bindings

This document defines how to describe AMQP-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.3.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object contains information about the channel representation in AMQP.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="channelBindingObjectIs"></a>`is` | string | Defines what type of channel is it. Can be either `queue` or `routingKey` (default).
<a name="channelBindingObjectExchange"></a>`exchange` | Map[string, any] | When `is`=`routingKey`, this object defines the exchange properties.
<a name="channelBindingObjectExchangeName"></a>`exchange.name` | string | The name of the exchange. It MUST NOT exceed 255 characters long.
<a name="channelBindingObjectExchangeType"></a>`exchange.type` | string | The type of the exchange. Can be either `topic`, `direct`, `fanout`, `default` or `headers`.
<a name="channelBindingObjectExchangeDurable"></a>`exchange.durable` | boolean | Whether the exchange should survive broker restarts or not.
<a name="channelBindingObjectExchangeAutoDelete"></a>`exchange.autoDelete` | boolean | Whether the exchange should be deleted when the last queue is unbound from it.
<a name="channelBindingObjectExchangeVHost"></a>`exchange.vhost` | string | The virtual host of the exchange. Defaults to `/`.
<a name="channelBindingObjectQueue"></a>`queue` | Map[string, any] | When `is`=`queue`, this object defines the queue properties.
<a name="channelBindingObjectQueueName"></a>`queue.name` | string | The name of the queue. It MUST NOT exceed 255 characters long.
<a name="channelBindingObjectQueueDurable"></a>`queue.durable` | boolean | Whether the queue should survive broker restarts or not.
<a name="channelBindingObjectQueueExclusive"></a>`queue.exclusive` | boolean | Whether the queue should be used only by one connection or not.
<a name="channelBindingObjectAutoDelete"></a>`queue.autoDelete` | boolean | Whether the queue should be deleted when the last consumer unsubscribes.
<a name="channelBindingObjectQueueVHost"></a>`queue.vhost` | string | The virtual host of the queue. Defaults to `/`.
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Example

```yaml
channels:
  userSignup:
    address: 'user/signup'
    bindings:
      amqp:
        is: routingKey
        exchange:
          name: myExchange
          type: topic
          durable: true
          autoDelete: false
          vhost: /
        bindingVersion: 0.3.0
```

```yaml
channels:
  userSignup:
    address: 'user/signup'
    bindings:
      amqp:
        is: queue
        queue:
          name: my-queue-name
          durable: true
          exclusive: true
          autoDelete: false
          vhost: /
        bindingVersion: 0.3.0
```

<a name="operation"></a>

## Operation Binding Object

This object contains information about the operation representation in AMQP.

##### Fixed Fields

Field Name | Type | Applies To Action | Description
---|:---:|:---:|---
<a name="operationBindingObjectExpiration"></a>`expiration` | integer | `receive`, `send` | TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero.
<a name="operationBindingObjectUserId"></a>`userId` | string | `receive`, `send` | Identifies the user who has sent the message.
<a name="operationBindingObjectCC"></a>`cc` | [string] | `receive`, `send` | The routing keys the message should be routed to at the time of publishing.
<a name="operationBindingObjectPriority"></a>`priority` | integer | `receive`, `send` | A priority for the message.
<a name="operationBindingObjectDeliveryMode"></a>`deliveryMode` | integer | `receive`, `send` | Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent).
<a name="operationBindingObjectMandatory"></a>`mandatory` | boolean | `receive` | Whether the message is mandatory or not.
<a name="operationBindingObjectBCC"></a>`bcc` | [string] | `receive` | Like [cc](#operationBindingObjectCC) but consumers will not receive this information.
<a name="operationBindingObjectTimestamp"></a>`timestamp` | boolean | `receive`, `send` | Whether the message should include a timestamp or not.
<a name="operationBindingObjectAck"></a>`ack` | boolean | Subscribe | Whether the consumer should ack the message or not.
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | `receive`, `send` | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Example

```yaml
operations:
  userSignup:
    channel: 
      $ref: '#/channels/userSignup'
    bindings:
      amqp:
        expiration: 100000
        userId: guest
        cc: ['user.logs']
        priority: 10
        deliveryMode: 2
        mandatory: false
        bcc: ['external.audit']
        timestamp: true
        ack: false
        bindingVersion: 0.3.0
```

<a name="message"></a>

## Message Binding Object

This object contains information about the message representation in AMQP.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageBindingObjectContentEncoding"></a>`contentEncoding` | string | A MIME encoding for the message content.
<a name="messageBindingObjectMessageType"></a>`messageType` | string | Application-specific message type.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

```yaml
channels:
  userSignup:
    address: 'user/signup'
    messages:
      userSignupMessage:
        bindings:
          amqp:
            contentEncoding: gzip
            messageType: 'user.signup'
            bindingVersion: 0.3.0
```

---

# amqp1
Source: https://www.asyncapi.com/docs/reference/bindings/amqp1.md

# amqp1

# AMQP 1.0 Bindings

This document defines how to describe AMQP 1.0-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# anypointmq
Source: https://www.asyncapi.com/docs/reference/bindings/anypointmq.md

# anypointmq

# Anypoint MQ Bindings

This document defines how to describe Anypoint MQ-specific information in AsyncAPI documents. 

[Anypoint MQ](https://docs.mulesoft.com/mq/) is MuleSoft's multi-tenant, cloud messaging service and is fully integrated with [Anypoint Platform](https://www.mulesoft.com/platform/enterprise-integration).

<a name="version"></a>
## Versions

The version of this bindings specification is `0.1.0`.
This is also the `bindingVersion` for all binding objects defined by this specification.
In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification.

## Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt).

## Protocol

These bindings use the `anypointmq` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with Anypoint MQ message brokers.

The Anypoint MQ protocol is based on invocations of the [Anypoint MQ Broker REST API](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/).

## Server Object

The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows:

Server Object Field Name | Values for Anypoint MQ Protocol | Description
---|:---|:---
<a name="serverObjectProtocolFieldValueAnypointMQ"></a>`protocol`               | `anypointmq`                                                 | **REQUIRED**. MUST be `anypointmq` for the scope of this specification.
<a name="serverObjectUrlFieldValueAnypointMQ"></a>`host`                         | e.g., `https://mq-us-east-1.anypoint.mulesoft.com`       | **REQUIRED**. MUST be the endpoint HOST part of the URL of the Anypoint MQ Broker REST API. Valid examples are `https://mq-us-east-1.anypoint.mulesoft.com` and `https://mq-eu-central-1.eu1.anypoint.mulesoft.com` (and _not_ `https://mq-us-east-1.anypoint.mulesoft.com/api`, or `https://.../api/v1`).
<a name="serverObjectUrlFieldValueAnypointMQ"></a>`pathname`                         | e.g., `/api`       | **REQUIRED**. MUST be the endpoint path part of the URL of the Anypoint MQ Broker REST API _excluding_ the final major version indicator (e.g., `v1`). Valid examples are `/api` and (and _not_ `https://.../api/v1`).
<a name="serverObjectProtocolVersionFieldValueAnypointMQ"></a>`protocolVersion` | e.g., `v1`                                                   | **OPTIONAL**, defaults to `v1`. If present MUST be the major version indicator of the Anypoint MQ Broker REST API omitted from the `url`, e.g. `v1`.
<a name="serverObjectSecurityFieldValueAnypointMQ"></a>`security`               | suitably configured OAuth 2.0 client credentials grant type  | **REQUIRED**. Authentication against the MuleSoft-hosted Anypoint MQ message brokers uses the OAuth 2.0 client credentials grant type. At runtime, the client ID and client secret values of an Anypoint MQ client app must be supplied. Also, the OAuth 2.0 scopes are currently not client-configurable. The `security` field of the server object MUST correctly match these constraints.

Note that the choice of a particular Anypoint MQ client app (via its client ID and secret) decides the Anypoint Platform organization ID and environment (ID) to be those in which this client app is defined. See the [Anypoint MQ documentation](https://docs.mulesoft.com/mq/mq-client-apps) for details on how to configure Anypoint MQ client apps.

<a name="server"></a>
## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>
## Channel Binding Object

The Anypoint MQ [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="channelBindingObjectDestination"></a>`destination`       | string | **OPTIONAL**, defaults to the channel name. The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ.
<a name="channelBindingObjectType"></a>`destinationType`          | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `exchange` or `queue` or `fifo-queue`. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel.
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding.

Note that an Anypoint MQ exchange can only be sent to, not received from. To receive messages sent to an exchange, [an intermediary queue must be defined and bound to the exchange](https://docs.mulesoft.com/mq/mq-understanding#message-exchanges). In this bindings specification, these intermediary queues are not exposed in the AsyncAPI document. Instead, it is simply assumed that whenever messages must be received from an exchange, such an intermediary queue is involved yet invisible in the AsyncAPI document.

### Examples

The following example shows two channels where does not apply any bindings and the second one applying `anyointmq` bindings.

```yaml
channels:
  userSignup:
    address: 'user/signup'
    description: |
      This application receives command messages from this channel about users to sign up.
      Minimal configuration, omitting a channel binding object.
    messages: 
      #...

  userSignup:
    address: 'user/signup'
    description: |
      This application sends events to this channel about users that have signed up.
      Explicitly provides a channel binding object.
    messages: 
      #...
    bindings:
      anypointmq:
        destination:     user-signup-exchg
        destinationType: exchange
        bindingVersion: '0.1.0'
```

<a name="operation"></a>
## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>
## Message Binding Object

The Anypoint MQ [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="messageBindingObjectHeaders"></a>`headers`               | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) \| [Reference Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject) | **OPTIONAL**. A Schema object containing the definitions for Anypoint MQ-specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of Anypoint MQ protocol headers are `messageId` and `messageGroupId`.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding.

Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are transmitted in the [`properties` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/).
In contrast, protocol headers such as `messageId` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the Anypoint MQ message](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/anypoint-mq-broker/).

### Examples

The following example shows a `channels` object with two channels, each having one operation (`subscribe` or `publish`) with one message. Only the message of the `subscribe` operation has a message binding object for `anypointmq`:

```yaml
channels:
  userSignup:
    address: 'user/signup'
    messages:
      #...
  userSignup:
    address: 'user/signup'
    messages:
      userSignupMessage:
        headers:
          type: object
          properties:
            correlationId:
              description: Correlation ID set by application
              type: string
        payload:
          type: object
          properties:
            #...
        correlationId:
          description: Correlation ID is specified as a header and transmitted in the Anypoint MQ message properties section
          location:    $message.header#/correlationId
        bindings:
          anypointmq:
            headers:
              type: object
              properties:
                messageId:
                  type: string
            bindingVersion: '0.1.0'
```

## Complete Example

The following is a complete, simple AsyncAPI document illustrating the usage of all binding objects defined in this bindings specification, with all their fields.

```yaml
asyncapi: 3.0.0
info:
  title: Example with Anypoint MQ
  version: 0.0.1
servers:
  development:
    host: mq-us-east-1.anypoint.mulesoft.com
    pathname: /api
    protocol: anypointmq
    protocolVersion: v1
    description: >
      Anypoint MQ broker for development, in the US East (N. Virginia) runtime
      plane 

      under management of the US control plane.
    security:
      - $ref: '#/components/securitySchemes/oauthDev'
  production:
    host: mq-eu-central-1.eu1.anypoint.mulesoft.com
    pathname: /api
    protocol: anypointmq
    protocolVersion: v1
    description: >
      Anypoint MQ broker for production, in the EU Central (Frankfurt) runtime
      plane 

      under management of the EU control plane.
    security:
      - $ref: '#/components/securitySchemes/oauthProd'
    bindings:
      anypointmq:
        bindingVersion: 0.1.0
channels:
  user/signup:
    address: user/signup
    messages:
      signUpUser.message:
        contentType: application/json
        headers:
          type: object
          properties:
            correlationId:
              description: Correlation ID set by application
              type: string
        payload:
          type: object
          properties:
            username:
              type: string
              minLength: 3
        correlationId:
          description: >-
            Correlation ID is specified as a header and transmitted in the
            Anypoint MQ message properties section
          location: $message.header#/correlationId
        bindings:
          anypointmq:
            headers:
              type: object
              properties:
                messageId:
                  type: string
            bindingVersion: 0.1.0
    description: >
      This application receives command messages from this channel about users
      to sign up.
    bindings:
      anypointmq:
        destination: user-signup-queue
        destinationType: fifo-queue
        bindingVersion: 0.1.0
operations:
  signUpUser:
    action: receive
    channel:
      $ref: '#/channels/user~1signup'
    description: >
      This application receives command messages via this operation about users
      to sign up.
    messages:
      - $ref: '#/channels/user~1signup/messages/signUpUser.message'
components:
  securitySchemes:
    oauthDev:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: 'https://mq-us-east-1.anypoint.mulesoft.com/api/v1/authorize'
          scopes: {}
    oauthProd:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: 'https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api/v1/authorize'
          scopes: {}
```

---

# googlepubsub
Source: https://www.asyncapi.com/docs/reference/bindings/googlepubsub.md

# googlepubsub

# Google Cloud Pub/Sub Bindings

This document defines how to describe Google Cloud Pub/Sub specific information with AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.2.0`.

<a name="channel"></a>

## Channel Binding Object

The `Channel Bindings Object` is used to describe the Google Cloud Pub/Sub specific
[Topic](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create) details with AsyncAPI.

Field Name | Type | Description
---|---|---
`bindingVersion`|String|The current version is `0.2.0`
`labels`|Object|An object of key-value pairs _(These are used to categorize Cloud Resources like Cloud Pub/Sub Topics.)_
`messageRetentionDuration`|String|Indicates the minimum duration to retain a message after it is published to the topic _(Must be a valid [Duration](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration).)_
`messageStoragePolicy`|[Message Storage Policy Object](#message-storage-policy-object)|Policy constraining the set of Google Cloud Platform regions where messages published to the topic may be stored
`schemaSettings`|[Schema Settings Object](#schema-settings-object)|Settings for validating messages published against a schema

<a name="message-storage-policy-object"></a>

### Message Storage Policy Object

The `Message Storage Policy Object` is used to describe the Google Cloud Pub/Sub
[MessageStoragePolicy](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#MessageStoragePolicy)
Object with AsyncAPI.

Field Name | Type | Description
---|---|---
`allowedPersistenceRegions`|String[]|A list of IDs of GCP regions where messages that are published to the topic may be persisted in storage

<a name="schema-settings-object"></a>

### Schema Settings Object

The `Schema Settings Object` is used to describe the Google Cloud Pub/Sub
[SchemaSettings](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#SchemaSettings) Object with
AsyncAPI.

Field Name | Type | Description
---|---|---
`encoding`|String|The encoding of the message _(Must be one of the possible [Encoding](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics#encoding) values.)_
`firstRevisionId`|String|The minimum _(inclusive)_ revision allowed for validating messages
`lastRevisionId`|String|The maximum _(inclusive)_ revision allowed for validating messages
`name`|String|The name of the schema that messages published should be validated against _(The format is `projects/{project}/schemas/{schema}`.)_

<a name="channel-binding-example"></a>

### Example

```yaml
# ...
channels:
  topic-avro-schema:
    address: projects/your-project/topics/topic-avro-schema
    bindings:
      googlepubsub:
        schemaSettings:
          encoding: json
          name: projects/your-project/schemas/message-avro
# ...
  topic-proto-schema:
    address: projects/your-project/topics/topic-proto-schema
    bindings:
      googlepubsub:
        messageRetentionDuration: 86400s
        messageStoragePolicy:
          allowedPersistenceRegions:
          - us-central1
          - us-central2
          - us-east1
          - us-east4
          - us-east5
          - us-east7
          - us-south1
          - us-west1
          - us-west2
          - us-west3
          - us-west4
        schemaSettings:
          encoding: binary
          name: projects/your-project/schemas/message-proto
# ...
```

<a name="message"></a>

## Message Binding Object

The `Message Binding Object` is used to describe the Google Cloud Pub/Sub specific
[PubsubMessage](https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage) details, alongside with pertintent
parts of the Google Cloud Pub/Sub
[Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema)
Object, with AsyncAPI.

Field Name | Type | Description
---|---|---
`bindingVersion`|String|The current version is `0.2.0`
`attributes`|Object|Attributes for this message _(If this field is empty, the message must contain non-empty data. This can be used to filter messages on the subscription.)_
`orderingKey`|String|If non-empty, identifies related messages for which publish order should be respected _(For more information, see [ordering messages](https://cloud.google.com/pubsub/docs/ordering).)_
`schema`|[Schema Definition Object](#schema-definition-object)|Describes the schema used to validate the payload of this message

<a name="schema-definition-object"></a>

### Schema Definition Object

The `Schema Definition Object` is used to describe the Google Cloud Pub/Sub
[Schema]([Schema](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas#Schema)) Object with AsyncAPI.
While some of this information could be, or is, described using native AsyncAPI, for consistency it makes sense to
provide this information here at all times, especially for cases where AsyncAPI does not natively support describing
payloads using a supported Google Cloud Pub/Sub schema format like Protobuf.

Field Name | Type | Description
---|---|---
`name`|String|The name of the schema

<a name="message-binding-example"></a>

### Example

```yaml
# ...
components:
  messages:
    messageAvro:
      bindings:
        googlepubsub:
          schema:
            name: projects/your-project/schemas/message-avro
      contentType: application/json
      name: MessageAvro
      payload:
        schema:
          fields:
          - name: message
            type: string
          name: Message
          type: record
        schemaFormat: application/vnd.apache.avro+yaml;version=1.9.0
    messageProto:
      bindings:
        googlepubsub:
          schema:
            name: projects/your-project/schemas/message-proto
      contentType: application/octet-stream
      name: MessageProto
      payload:
        schema: |
          syntax = "proto3";

          message Message {
            required string message = 1;
          }
        schemaFormat: application/vnd.google.protobuf;version=3
# ...
```

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# http
Source: https://www.asyncapi.com/docs/reference/bindings/http.md

# http

# HTTP Bindings

This document defines how to describe HTTP-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.3.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object
 
##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationBindingObjectMethod"></a>`method` | string | The HTTP method for the request. Its value MUST be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`, `CONNECT`, and `TRACE`.
<a name="operationBindingObjectQuery"></a>`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key.
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Example

```yaml
channels:
  employees:
    address: /employees
operations:
  employees:
    action: send
    bindings:
      http:
        method: GET
        query:
          type: object
          required:
            - companyId
          properties:
            companyId:
              type: number
              minimum: 1
              description: The Id of the company.
          additionalProperties: false
        bindingVersion: '0.3.0'
```

<a name="message"></a>

## Message Binding Object

This object contains information about the message representation in HTTP.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="messageBindingObjectHeaders"></a>`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for HTTP-specific headers. This schema MUST be of type `object` and have a `properties` key.
<a name="messageBindingObjectStatusCode"></a>`statusCode` | number | The HTTP response status code according to [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes). `statusCode` is only relevant for messages referenced by the [Operation Reply Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationReplyObject), as it defines the status code for the response. In all other cases, this value can be safely ignored.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

```yaml
channels:
  test:
    address: /test
    messages:
      testMessage:
        bindings:
          http:
            statusCode: 200
            headers:
              type: object
              properties:
                Content-Type:
                  type: string
                  enum: ['application/json']
            bindingVersion: '0.3.0'
```

[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject
[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject

---

# Overview
Source: https://www.asyncapi.com/docs/reference/bindings.md

# Overview

## Overview

import BindingsOverview from '@/assets/docs/fragments/bindings-overview.md'

## Usage in an AsyncAPI document

To learn how to add bindings to your AsyncAPI document, read [Adding bindings](/docs/concepts/asyncapi-document/adding-bindings.md) concept document, or read the guide about using [Kafka bindings](/docs/tutorials/kafka/bindings-with-kafka.md).

## Contributing to bindings

Bindings are maintained by different community members that know and use given protocol and technology in production. If something can be improved, or some new binding is needed, open an issue in [bindings repository](https://github.com/asyncapi/bindings).

---

# ibmmq
Source: https://www.asyncapi.com/docs/reference/bindings/ibmmq.md

# ibmmq

# IBM MQ Bindings

This document defines how to describe IBM MQ specific information with AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

## Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt).

## AsyncAPI considerations

This specification binding requests that the AsyncAPI specification reserve the IBM MQ protocol to allow connections to queue manager endpoints to be defined within the server object.

AsyncAPI Object Fixed Field Name | Reserved Value for IBM MQ Protocol | Description
---|:---|:---
<a name="serverObjectProtocolFieldValueIbmmq"></a>`server.protocol` | ibmmq | IBM MQ protocol.
<a name="serverObjectProtocolFieldValueIbmmqSecure"></a>`server.protocol` | ibmmq-secure | IBM MQ protocol over TLS.

## URI scheme considerations

For the purposes of establishing an IBM MQ binding for use within AsyncAPI, this document defines the URI scheme `ibmmq://` consisting of components and generic URI syntax as specified in [RFC3986](https://tools.ietf.org/html/rfc3986)

### Defining an IBM MQ queue manager endpoint in the server object `url` field

When defining an IBM MQ `url` for a queue manager endpoint, the `ibmmq://` URI scheme MUST be used. IBM MQ URIs are defined using the following components.

URI Component | IBM MQ reference | Applicability | Description |
---|:---|:--|:--
<a name="uriObjectScheme"></a>`scheme` | `ibmmq://` | REQUIRED | The URI scheme used to represent an IBM MQ endpoint. 
<a name="uriObjectAuthority>"></a>`authority` | `<hostname or ipAddress>:port` | REQUIRED | The network IP address or hostname and port of the queue manager endpoint. |
<a name="uriObjectQueueManager>"></a>`path` | `queueManager` | OPTIONAL | The queue manager name. If no queue manager name is specified this segment is left undefined, for example `ibmmq://hostname:{port}//CHANNEL.NAME`
<a name="uriObjectChannelName>"></a>`path` | `mqChannelName` | REQUIRED | The `SVRCONN` channel to use for communication with an IBM MQ queue manager. When connecting to a queue manager, IBM MQ partitions this communication into logical channels.

URI `query` or `fragment` components MUST NOT be used within the `ibmmq://` scheme. Path components that contain characters reserved by RFC2936 such as `/` MUST be percent encoded as defined in [Section 2.2 of RFC2936](https://tools.ietf.org/html/rfc3986#section-2.2). `port` MUST be specified as part of the authority component in the `ibmmq://` scheme.

### Defining IBM MQ queue manager endpoints with the AsyncAPI Server Object

This section defines the convention for how IBM MQ queue manager endpoints are encoded within the AsyncAPI Server Object fields. A `groupId` field has been made available on the IBM MQ AsyncAPI server binding object to allow server objects to be defined as a related collection. This is necessary to group, or cluster, IBM MQ queue manager endpoints within the AsyncAPI specification and where a Client Channel Definition Table ([CCDT](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.con.doc/q132905_.html)) reference is not appropriate.
     
       
##### Example of two possible MQ servers defined using ibmmq url syntax 
```yaml
servers:
  production1:
    url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN
    protocol: ibmmq
  production2:
    url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN
    protocol: ibmmq
```

##### Example of single MQ server defined using ibmmq url syntax and with no queue manager name specified
```yaml
servers:
  production:
    url: ibmmq://qmgr1host:1414//DEV.APP.SVRCONN
    protocol: ibmmq
```

## Defining an IBM MQ queue manager endpoint CCDT in the `url` field
When defining a connection to IBM MQ, a CCDT connection file can be specified. The server url will specify the location of the file with additional information contained within the server binding to specify its usage. 

##### Example using an IBM MQ CCDT file url 

```yaml
servers:
  production1:
    url: 'http://my-ccdt-json-file'
    protocol: ibmmq
  production2:
    url: 'file://myccdt.json'
    protocol: ibmmq
```   

<a name="server"></a>

## Server Binding Object

This object contains server connection information about the IBM MQ server, referred to as an IBM MQ queue manager. This object contains additional connectivity information not possible to represent within the core AsyncAPI specification.

##### Fixed Fields

Field Name | Type | Description | Applicability \[default\] | Constraints
---|:---:|---|:---|:---
<a name="serverObjectGroupId>"></a>`groupId` | string | Defines a logical group of IBM MQ server objects. This is necessary to specify multi-endpoint configurations used in high availability deployments. If omitted, the server object is not part of a group. | OPTIONAL | MUST NOT be specified for URI Scheme `http://` or `file://`
<a name="serverObjectCCDTQueueManager"></a>`ccdtQueueManagerName` | string | The name of the IBM MQ queue manager to bind to in the CCDT file. | OPTIONAL [`*`] | MUST NOT be specified for URI Scheme `ibmmq://`
<a name="serverObjectCipherSpec"></a>`cipherSpec` | string | The recommended cipher specification used to establish a TLS connection between the client and the IBM MQ queue manager. More information on SSL/TLS cipher specifications supported by IBM MQ can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.dev.doc/q113220_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`ANY`] | MUST NOT be specified for protocol `ibmmq` or URI Scheme `file://` or `http://` 
<a name="serverObjectMultiEndpointServer:"></a>`multiEndpointServer` | boolean | If `multiEndpointServer` is `true` then multiple connections can be workload balanced and applications should not make assumptions as to where messages are processed. Where message ordering, or affinity to specific message resources is necessary, a single endpoint (`multiEndpointServer` = `false`) may be required. | OPTIONAL [`false`] | MUST NOT be specified for URI Scheme `file://` or `http://`
<a name="serverObjectEndpointHeartBeatInterval"></a>`heartBeatInterval` | integer | The recommended value (in seconds) for the heartbeat sent to the queue manager during periods of inactivity. A value of zero means that no heart beats are sent. A value of `1` means that the client will use the value defined by the queue manager. More information on heart beat interval can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q108450_.html) in the IBM MQ Knowledge Center. | OPTIONAL [`300`] | MUST be `0-999999`
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | -

This object MUST contain only the properties defined above.

##### Example for multiple endpoints defined in the AsyncAPI configuration

```yaml
servers:
  production1:
    url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN
    protocol: ibmmq-secure
    description: Production Instance 1
    bindings:
      ibmmq: 
        groupId: PRODCLSTR1
        cipherSpec: ANY_TLS12_OR_HIGHER
        bindingVersion: 0.1.0
  production2:
    url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN
    protocol: ibmmq-secure
    description: Production Instance 2
    bindings:
      ibmmq: 
        groupId: PRODCLSTR1
        bindingVersion: 0.1.0
```

##### Example using combined strategy 

```yaml
servers:
  production:
    url: 'http://my-ccdt-json-file'
    protocol: ibmmq-secure
    description: Production MQ Instance 
    bindings:
      ibmmq:
        ccdtQueueManagerName: qm1
  test:
    url: ibmmq://qmgrtest:1414/qm2/DEV.APP.SVRCONN
    protocol: ibmmq-secure
    description: Test MQ Instance
    bindings:
      ibmmq: 
        cipherSpec: ANY_TLS12_OR_HIGHER
        bindingVersion: 0.1.0
```

<a name="channel"></a>

## Channel Binding Object

This object contains information about the channel representation in IBM MQ. Each channel corresponds to a Queue or Topic within IBM MQ. 

##### Fixed Fields

Field Name | Type | Description | Applicability [default] | Constraints
---|:---:|---|:---|:---
<a name="channelBindingObjectDestinationType"></a>`destinationType` | string | Defines the type of AsyncAPI channel.  | OPTIONAL [`topic`] | MUST be either `topic` or `queue`. For type `topic`, the AsyncAPI channel name MUST be assumed for the IBM MQ topic string unless overridden.
<a name="channelBindingObjectQueue"></a>`queue` | Map[string, any] | Defines the properties of a queue. | REQUIRED if `destinationType` = `queue` | `queue` and `topic` fields MUST NOT coexist within a channel binding
<a name="channelBindingObjectQueueObjectName"></a>`queue.`<br />`objectName` | string | Defines the name of the IBM MQ queue associated with the channel. | REQUIRED | A value MUST be specified. MUST NOT exceed 48 characters in length. MUST be a valid IBM MQ queue name
<a name="channelBindingObjectisPartitioned"></a>`queue.`<br />`isPartitioned` | boolean | Defines if the queue is a cluster queue and therefore partitioned. If `true`, a binding option MAY be specified when accessing the queue. More information on binding options can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q101870_.html#q101870___BIND_ON_OPEN) in the IBM MQ Knowledge Center. | OPTIONAL [`false`] | If `false`, binding options SHOULD NOT be specified when accessing the queue.
<a name="channelBindingObjectQueueExclusive"></a>`queue.`<br />`exclusive` | boolean | Specifies if it is recommended to open the queue exclusively. | OPTIONAL [`false`] | - 
<a name="channelBindingObjectTopic"></a>`topic` | Map[string, any] | Defines the properties of a topic. | OPTIONAL if `destinationType` = `topic` | `queue` and `topic` fields MUST NOT coexist within a channel binding.
<a name="channelBindingObjectTopicString"></a>`topic.`<br />`string`  | string | The value of the IBM MQ topic string to be used. | OPTIONAL *<br />Note: if specified, SHALL override AsyncAPI channel name.* | MUST NOT exceed 10240 characters in length. MAY coexist with `topic.objectName`
<a name="channelBindingObjectTopicObjectName"></a>`topic.`<br />`objectName`  | string | The name of the IBM MQ topic object. | OPTIONAL *<br />Note: if specified, SHALL override AsyncAPI channel name.*| MUST NOT exceed 48 characters in length. MAY coexist with `topic.string`
<a name="channelBindingObjectTopicDurablePermitted"></a>`topic.`<br /> `durablePermitted` | boolean | Defines if the subscription may be durable. | OPTIONAL [`true`] | -
<a name="channelBindingObjectTopicLastMsgRetained"></a>`topic.`<br />`lastMsgRetained` | boolean | Defines if the last message published will be made available to new subscriptions. | OPTIONAL [`false`] | -
<a name="channelBindingObjectMaxMsgLength"></a>`maxMsgLength` | integer | The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered. More information on the maximum message length can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.adm.doc/q085520_.html#q085520___maxmsgl) in the IBM MQ Knowledge Center. | OPTIONAL [negotiated on IBM MQ channel]| MUST be  `0-104,857,600` bytes (100 MB).
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | -

This object MUST contain only the properties defined above.

##### Example for an IBM MQ Topic where topic string is defined by AsyncAPI channel

```yaml
channels:
  user/signedup:
```

##### Example for AsyncAPI channel mapping to an IBM MQ topic with a specified MQ Topic object

```yaml
channels:
  user/signedup:
    bindings:
      ibmmq:
        destinationType: topic
        topic:
          objectName: myTopicName
        bindingVersion: 0.1.0
```

##### Example for AsyncAPI channel mapping to an IBM MQ Queue

```yaml
channels:
  user/signedup:
    bindings:
      ibmmq:
        destinationType: queue
        queue:
          objectName: myQueueName
          exclusive: true
        bindingVersion: 0.1.0
```

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object contains information about the message representation in IBM MQ.

##### Fixed Fields

Field Name | Type  | Description | Applicability [default] | Constraints
---|:---:|---|:---|:---
<a name="messageBindingObjectType"></a>`type` | string |  The type of the message. | OPTIONAL [`string`] | MUST be either `string`, `jms` or `binary`
<a name="messageBindingObjectHeaders"></a>`headers` | string | Defines the IBM MQ message headers to include with this message. More than one header can be specified as a comma separated list. Supporting information on IBM MQ message formats can be found on this [page](https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097520_.html) in the IBM MQ Knowledge Center. | OPTIONAL if `type` = `binary` | `headers` MUST NOT be specified if `type` = `string` or `jms`
<a name="messageBindingObjectDescription"></a>`description` | string<sup>1</sup> | Provides additional information for application developers: describes the message type or format. | OPTIONAL | - 
<a name="messageBindingObjectExpiry"></a>`expiry` |  integer | The recommended setting the client should use for the TTL (Time-To-Live) of the message. This is a period of time expressed in milliseconds and set by the application that puts the message. `expiry` values are API dependant e.g., MQI and JMS use different units of time and default values for *`unlimited`*. General information on IBM MQ message expiry can be found on this [page](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q097490_.html) in the IBM MQ Knowledge Center. | OPTIONAL [*`unlimited`*] | `expiry` value MUST be either `zero` (*`unlimited`*) or greater than zero. 
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`] | - 

This object MUST contain only the properties defined above.

### Rich Text Formatting

<sup>1</sup> The `description` field of the IBM MQ message binding object MAY include CommonMark markdown formatting. A minimum markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/) is assumed. 

##### Example for plain text message

```yaml
channels:
  user/signup:
    publish:
      message:
        bindings:
          ibmmq:
            type: string
            bindingVersion: 0.1.0
```

##### Example for IBM MQ message using JMS

```yaml
channels:
  user/signup:
    publish:
      message:
        bindings:
          ibmmq:
            type: jms
            description: JMS stream message
            bindingVersion: 0.1.0
```

# AsyncAPI example with IBM MQ binding

##### Example for AsyncAPI user signup

```yaml
asyncapi: 2.0.0
info:
  title: Account Service
  version: 1.0.0
  description: This service is in charge of processing user signups
servers:
  production1:
    url: ibmmq://qmgr1host:1414/qm1/DEV.APP.SVRCONN
    protocol: ibmmq-secure
    description: Production Instance 1
    bindings:
      ibmmq: 
        groupId: PRODCLSTR1
        cipherSpec: ANY_TLS12_OR_HIGHER
        bindingVersion: 0.1.0
  production2:
    url: ibmmq://qmgr2host:1414/qm2/DEV.APP.SVRCONN
    protocol: ibmmq-secure
    description: Production Instance 2
    bindings:
      ibmmq: 
        groupId: PRODCLSTR1
        cipherSpec: ANY_TLS12_OR_HIGHER
        bindingVersion: 0.1.0
channels:
  user/signedup:
    bindings:
      ibmmq:
        topic:
          durablePermitted: true
        bindingVersion: 0.1.0
    subscribe:
      message:
        $ref: '#/components/messages/UserSignedUp'
        bindings:
          ibmmq:
            type: jms
            description: JMS bytes message
            bindingVersion: 0.1.0
components:
  messages:
    UserSignedUp:
      payload:
        type: object
        properties:
          displayName:
            type: string
            description: Name of the user
          email:
            type: string
            format: email
            description: Email of the user
```

---

# jms
Source: https://www.asyncapi.com/docs/reference/bindings/jms.md

# jms

# JMS Bindings

This document defines how to describe JMS-specific information on AsyncAPI.

<a name="version"></a>
## Versions

The version of this bindings specification is `0.0.1`.
This is also the `bindingVersion` for all binding objects defined by this specification.
In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification.

## Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt).

## Protocol

These bindings use the `jms` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with JMS message brokers.

JMS is not technically a protocol, rather it is an API. A JMS Provider implements the JMS API and may define a protocol for implementing JMS API operations. Regardless, for the purposes of AsyncAPI we can treat it like a "protocol" to enable AsyncAPI definitions that are somewhat portable between various JMS Providers. If necessary, the user is free to combine this binding with other bindings that implement a JMS Provider (e.g. [Apache Pulsar](https://github.com/asyncapi/bindings/tree/master/pulsar), [Amazon SQS](https://github.com/asyncapi/bindings/tree/master/sqs), [IBM MQ](https://github.com/asyncapi/bindings/tree/master/ibmmq), etc.) to detail JMS Provider specific configuration.

**NOTE** that from protocol version 3.0, this binding is compatible with [Jakarta Messaging](https://jakarta.ee/specifications/messaging).

## Server Object

The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows:

Server Object Field Name | Values for JMS Protocol | Description
---|:---|:---
<a name="serverObjectProtocolFieldValueJMS"></a>`protocol`               | `jms`                                                 | **REQUIRED**. MUST be `jms` for the scope of this specification.
<a name="serverObjectUrlFieldValueJMS"></a>`url`                         | e.g., `jms://host:port`       | **REQUIRED**. MUST be a URL containing the hostname and port of a JMS Broker.
<a name="serverObjectProtocolVersionFieldValueJMS"></a>`protocolVersion` | e.g., `3.1`                                                   | **OPTIONAL**, defaults to `3.1`. If present MUST be the version indicator of the JMS API. Valid values are `1.0`, `1.0.1`, `1.0.1a`, `1.0.2`, `1.0.2a`, `1.0.2b`, `1.1`, `2.0`, `2.0a`, `2.1`, or `3.0`, `3.1.`.

<a name="server"></a>

## Server Binding Object

The JMS [Server Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#server-bindings-object) is defined by a [JSON Schema](json_schemas/server.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="serverBindingObjectJMSConnectionFactory"></a>`jmsConnectionFactory` | string | **REQUIRED**. The classname of the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) implementation for the JMS Provider.
<a name="serverBindingObjectJMSProperties"></a>`properties` | [Schema Array](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaArray) | **OPTIONAL**. Additional properties to set on the JMS ConnectionFactory implementation for the JMS Provider.
<a name="serverBindingObjectJMSClientID"></a>`clientID` | string | **OPTIONAL**. A client identifier for applications that use this JMS connection factory. If the Client ID Policy is set to 'Restricted' (the default), then configuring a Client ID on the [ConnectionFactory](https://docs.oracle.com/javaee/7/api/javax/jms/ConnectionFactory.html) prevents more than one JMS client from using a connection from this factory.
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding.

### Examples

The following example shows a `servers` object with a server binding object for `jms` with JMS specific properties:

```yaml
servers:
  production:
    url: jms://my-activemq-broker:61616
    protocol: jms
    protocolVersion: '1.1'
    description: The production ActiveMQ broker accessed via JMS.
    bindings:
      jms:
        # JMS protocol specific server details
        jmsConnectionFactory: org.apache.activemq.ActiveMQConnectionFactory
        properties:
          - name: disableTimeStampsByDefault
            value: false
        clientID: my-application-1
```

<a name="channel"></a>
## Channel Binding Object

The JMS [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="channelBindingObjectDestination"></a>`destination`       | string | **OPTIONAL**, defaults to the channel name. The destination (queue) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name according to the JMS Provider.
<a name="channelBindingObjectDestinationType"></a>`destinationType`          | string | **OPTIONAL**, defaults to `queue`. The type of destination, which MUST be either `queue`, or `fifo-queue`. SHOULD be specified to document the messaging model (point-to-point, or strict message ordering) supported by this channel.
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding.

### Examples

The following example shows a `channels` object with two channels, the second having a channel binding object for `jms`:

```yaml
channels:
  user.signup:
    description: This application receives command messages from this channel about users to sign up.
    bindings:
      jms:
        destination:     user-sign-up
        destinationType: fifo-queue
        bindingVersion:  '0.0.1'
    publish:
      #...
```

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

The JMS [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) is defined by a [JSON Schema](json_schemas/message.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="messageBindingObjectHeaders"></a>`headers`               | [Schema Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject) | **OPTIONAL**. A Schema object containing the definitions for JMS specific headers (so-called protocol headers). This schema MUST be of type `object` and have a `properties` key. Examples of JMS protocol headers are `JMSMessageID`, `JMSTimestamp`, and `JMSCorrelationID`.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | **OPTIONAL**, defaults to `latest`. The version of this binding.

Note that application headers must be specified in the [`headers` field of the standard Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObjectHeaders) and are set as [Message Properties](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Properties) of the JMS Message; how they are transmitted is defined by the JMS Provider and need not be considered here.
In contrast, protocol headers such as `JMSMessageID` must be specified in the [`headers` field of the message binding object](#messageBindingObjectHeaders) and are transmitted in the [`headers` section of the JMS message](https://docs.oracle.com/javaee/7/api/javax/jms/Message.html#Message%20Headers).

### Examples

The following example shows a `message` object with both application specific headers, and a message binding object for `jms` with JMS specific headers:

```yaml
message:
  messageId: my-message-1
  bindings:
    jms:
      headers:
        # JMS protocol specific message headers
        required:
          - JMSMessageID
      properties:
        JMSMessageID:
          name: JMSMessageID
          description: A unique message identifier. This may be set by your JMS Provider on your behalf.
          type: string
        JMSReplyTo:
          name: JMSReplyTo
          description: The queue or topic that the message sender expects replies to.
          type: string
  headers:
    # Application specific message headers
    required:
      - MyToken
      - MyOperationID
    properties:
      MyToken:
        name: MyToken
        description: Some sort of identificaton token for the publishing application.
        type: string
      MyOperationID:
        name: MyOperationID
        description: Some sort of unique identifier for the application operation to perform.
        type: string
```

---

# kafka
Source: https://www.asyncapi.com/docs/reference/bindings/kafka.md

# kafka

# Kafka Bindings

This document defines how to describe Kafka-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.5.0`.

<a name="server"></a>

## Server Binding Object

This object contains information about the server representation in Kafka.

##### Fixed Fields

Field Name | Type | Description | Applicability [default] | Constraints
---|:---:|:---:|:---:|---
`schemaRegistryUrl` | string (url) | API URL for the Schema Registry used when producing Kafka messages (if a Schema Registry was used) | OPTIONAL | -
`schemaRegistryVendor` | string | The vendor of Schema Registry and Kafka serdes library that should be used (e.g. `apicurio`, `confluent`, `ibm`, or `karapace`) | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. | OPTIONAL [`latest`]

##### Example

```yaml
servers:
  production:
    bindings:
      kafka:
        schemaRegistryUrl: 'https://my-schema-registry.com'
        schemaRegistryVendor: 'confluent'
        bindingVersion: '0.5.0'
```

<a name="channel"></a>

## Channel Binding Object

This object contains information about the channel representation in Kafka (eg. a Kafka topic).

##### Fixed Fields

Field Name |                       Type                       |                                               Description                                               | Applicability [default] | Constraints
---|:------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|---
<a name="channelBindingObjectTopic"></a>`topic` |                      string                      |                            Kafka topic name if different from channel name.                             |        OPTIONAL         | -
<a name="channelBindingObjectPartitions"></a>`partitions` |                     integer                      | Number of partitions configured on this topic (useful to know how many parallel consumers you may run). |        OPTIONAL         | Must be positive
<a name="channelBindingObjectReplicas"></a>`replicas` |                     integer                      |                              Number of replicas configured on this topic.                               |        OPTIONAL         | MUST be positive
<a name="channelBindingObjectTopicConfiguration"></a>`topicConfiguration` | [TopicConfiguration Object](#topicConfiguration) |                   Topic configuration properties that are relevant for the API.                    |       OPTIONAL       | -
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` |                      string                      |                   The version of this binding. If omitted, "latest" MUST be assumed.                    |   OPTIONAL [`latest`]   | -

This object MUST contain only the properties defined above.

##### Example

```yaml
channels:
  user-signedup:
    bindings:
      kafka:
        topic: 'my-specific-topic-name'
        partitions: 20
        replicas: 3
        topicConfiguration:
          cleanup.policy: ["delete", "compact"]
          retention.ms: 604800000
          retention.bytes: 1000000000
          delete.retention.ms: 86400000
          max.message.bytes: 1048588
        bindingVersion: '0.5.0'
```
<a name="topicConfiguration"></a>
## TopicConfiguration Object

This objects contains information about the API relevant topic configuration in Kafka.

Field Name |  Type   |                                                                             Description                                                                              | Applicability [default] | Constraints
---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|---
<a name="topicConfigurationCleanupPolicy"></a>`cleanup.policy` |  array  |                            The [`cleanup.policy`](https://kafka.apache.org/documentation/#topicconfigs_cleanup.policy) configuration option.                          |        OPTIONAL         | array may only contain `delete` and/or `compact`
<a name="topicConfigurationRetentionMs"></a>`retention.ms` | long |                               The [`retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_retention.ms) configuration option.                                    |        OPTIONAL         | see kafka documentation
<a name="topicConfigurationRetentionBytes"></a>`retention.bytes` | long |                       The [`retention.bytes`](https://kafka.apache.org/documentation/#topicconfigs_retention.bytes) configuration option.                                                           |        OPTIONAL         | see kafka documentation
<a name="topicConfigurationDeleteRetentionBytes"></a>`delete.retention.ms` | long |             The [`delete.retention.ms`](https://kafka.apache.org/documentation/#topicconfigs_delete.retention.ms) configuration option.                                               |        OPTIONAL         | see kafka documentation
<a name="topicConfigurationMaxMessageBytes"></a>`max.message.bytes` | integer |                    The [`max.message.bytes`](https://kafka.apache.org/documentation/#topicconfigs_max.message.bytes) configuration option.                                      |        OPTIONAL         | see kafka documentation
<a name="topicConfigurationConfluentKeySchemaValidation"></a>`confluent.key.schema.validation`  | boolean |                    It shows whether the schema validation for the message key is enabled. Vendor specific config.                                      |        OPTIONAL         | -
<a name="topicConfigurationConfluentKeySubjectNameStrategy"></a>`confluent.key.subject.name.strategy` | string |                    The name of the schema lookup strategy for the message key. Vendor specific config.                                     |        OPTIONAL         | Clients should default to the vendor default if not supplied.
<a name="topicConfigurationConfluentValueSchemaValidation"></a>`confluent.value.schema.validation` | boolean |                    It shows whether the schema validation for the message value is enabled. Vendor specific config.                                      |        OPTIONAL         | -
<a name="topicConfigurationConfluentValueSubjectNameStrategy"></a>`confluent.value.subject.name.strategy` | string |                    The name of the schema lookup strategy for the message value. Vendor specific config.                                      |        OPTIONAL         | Clients should default to the vendor default if not supplied.

This object MAY contain the properties defined above including optional additional properties.

##### Example

```yaml
topicConfiguration:
  cleanup.policy: ["delete", "compact"]
  retention.ms: 604800000
  retention.bytes: 1000000000
  delete.retention.ms: 86400000
  max.message.bytes: 1048588
  confluent.key.schema.validation: true
  confluent.key.subject.name.strategy: "TopicNameStrategy"
  confluent.value.schema.validation: true
  confluent.value.subject.name.strategy: "TopicNameStrategy"
```

<a name="operation"></a>

## Operation Binding Object

This object contains information about the operation representation in Kafka (eg. the way to consume messages)

##### Fixed Fields

Field Name | Type | Description | Applicability [default] | Constraints
---|:---:|:---:|:---:|---
<a name="operationBindingObjectGroupId"></a>`groupId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer group. | OPTIONAL | -
<a name="operationBindingObjectClientId"></a>`clientId` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | Id of the consumer inside a consumer group. | OPTIONAL | -
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | -

This object MUST contain only the properties defined above.

##### Example

```yaml
channels:
  user-signedup:
operations:
  userSignup:
    action: receive
    bindings:
      kafka:
        groupId:
          type: string
          enum: ['myGroupId']
        clientId:
          type: string
          enum: ['myClientId']
        bindingVersion: '0.5.0'
```

<a name="message"></a>

## Message Binding Object

This object contains information about the message representation in Kafka.

##### Fixed Fields

Field Name |  Type   |                                                                             Description                                                                              | Applicability [default] | Constraints
---|:-------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------:|---
<a name="messageBindingObjectKey"></a>`key` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| [AVRO Schema Object](https://avro.apache.org/docs/current/spec.html) | The message key. **NOTE**: You can also use the [reference object](referenceObject) way. | OPTIONAL | -
<a name="messageBindingObjectSchemaIdLocation"></a>`schemaIdLocation` | string | If a Schema Registry is used when performing this operation, tells where the id of schema is stored (e.g. `header` or `payload`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level
<a name="messageBindingObjectSchemaIdPayloadEncoding"></a>`schemaIdPayloadEncoding` | string | Number of bytes or vendor specific values when schema id is encoded in payload (e.g `confluent`/ `apicurio-legacy` / `apicurio-new`). | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level
<a name="messageBindingObjectSchemaLookupStrategy"></a>`schemaLookupStrategy` | string | Freeform string for any naming strategy class to use. Clients should default to the vendor default if not supplied. | OPTIONAL | MUST NOT be specified if `schemaRegistryUrl` is not specified at the Server level
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. | OPTIONAL [`latest`] | -

This object MUST contain only the properties defined above.

This example is valid for any Confluent compatible schema registry. Here we describe the implementation using the first 4 bytes in payload to store schema identifier.

```yaml
channels:
  test:
    address: test-topic
    messages:
      testMessage:
        bindings:
          kafka:
            key:
              type: string
              enum: ['myKey']
            schemaIdLocation: 'payload'
            schemaIdPayloadEncoding: '4'
            bindingVersion: '0.5.0'
```

This is another example that describes the use if Apicurio schema registry. We describe the `apicurio-new` way of serializing without details on how it's implemented. We reference a [specific lookup strategy](https://www.apicur.io/registry/docs/apicurio-registry/2.2.x/getting-started/assembly-using-kafka-client-serdes.html#registry-serdes-concepts-strategy_registry) that may be used to retrieve schema Id from registry during serialization.

```yaml
channels:
  test:
    address: test-topic
    messages:
      testMessage:
        bindings:
          kafka:
            key:
              type: string
              enum: ['myKey']
            schemaIdLocation: 'payload'
            schemaIdPayloadEncoding: 'apicurio-new'
            schemaLookupStrategy: 'TopicIdStrategy'
            bindingVersion: '0.5.0'
```

[schemaObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#schemaObject
[referenceObject]: https://www.asyncapi.com/docs/reference/specification/v3.0.0-next-major-spec.15#referenceObject

---

# mercure
Source: https://www.asyncapi.com/docs/reference/bindings/mercure.md

# mercure

# Mercure Bindings

This document defines how to describe Mercure-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# mqtt
Source: https://www.asyncapi.com/docs/reference/bindings/mqtt.md

# mqtt

# MQTT Bindings

This document defines how to describe MQTT-specific information on AsyncAPI.

It applies to all versions of MQTT, although specific binding fields may only apply to particular versions.

<a name="version"></a>

## Version

Current version is `0.2.0`.

<a name="server"></a>

## Server Binding Object

This object contains information about the server representation in MQTT.

##### Fixed Fields

Field Name | Type | MQTT Versions | Description
---|:---:|:---:|---|
<a name="serverBindingObjectClientId"></a>`clientId` | string | 3, 5 | The client identifier.
<a name="serverBindingObjectCleanSession"></a>`cleanSession` | boolean | 3, 5 | Whether to create a persistent connection or not. When `false`, the connection will be persistent. This is called **clean start** in MQTTv5.
<a name="serverBindingObjectLastWill"></a>`lastWill` | object | 3, 5 | Last Will and Testament configuration. `topic`, `qos`, `message` and `retain` are properties of this object as shown below.
<a name="serverBindingObjectLastWillTopic"></a>`lastWill.topic` | string | 3, 5 | The topic where the Last Will and Testament message will be sent.
<a name="serverBindingObjectLastWillQoS"></a>`lastWill.qos` | integer | 3, 5 | Defines how hard the broker/client will try to ensure that the Last Will and Testament message is received. Its value MUST be either 0, 1 or 2.
<a name="serverBindingObjectLastWillMessage"></a>`lastWill.message` | string | 3, 5 | Last Will message.
<a name="serverBindingObjectLastWillRetain"></a>`lastWill.retain` | boolean | 3, 5 | Whether the broker should retain the Last Will and Testament message or not.
<a name="serverBindingObjectKeepAlive"></a>`keepAlive` | integer | 3, 5 | Interval in seconds of the longest period of time the broker and the client can endure without sending a message.
<a name="serverBindingObjectSessionExpiryInterval"></a>`sessionExpiryInterval` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Interval in seconds or a *Schema Object* containing the definition of the interval.  The broker maintains a session for a disconnected client until this interval expires.
<a name="serverBindingObjectMaximumPacketSize"></a>`maximumPacketSize` | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Number of bytes or a *Schema Object* representing the maximum packet size the client is willing to accept.
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed. |

This object MUST contain only the properties defined above.

##### Examples

```yaml
servers:
  production:
    bindings:
      mqtt:
        clientId: guest
        cleanSession: true
        lastWill:
          topic: /last-wills
          qos: 2
          message: Guest gone offline.
          retain: false
        keepAlive: 60
        sessionExpiryInterval: 600
        maximumPacketSize: 1200
        bindingVersion: 0.2.0
```
```yaml
servers:
  production:
    bindings:
      mqtt:
        sessionExpiryInterval:
          type: integer
          minimum: 30
          maximum: 1200
        maximumPacketSize:
          type: integer
          minimum: 256
        bindingVersion: 0.2.0
```

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object contains information about the operation representation in MQTT.

##### Fixed Fields

Field Name | Type | Applies To | MQTT Versions | Description
---|:---:|:---:|:---:|---
<a name="operationBindingObjectQoS"></a>`qos` | integer | Publish, Subscribe | 3, 5 | Defines the Quality of Service (QoS) levels for the message flow between client and server. Its value MUST be either 0 (At most once delivery), 1 (At least once delivery), or 2 (Exactly once delivery).
<a name="operationBindingObjectRetain"></a>`retain` | boolean | Publish | 3, 5 | Whether the broker should retain the message or not.
<a name="operationBindingObjectMessageExpiryInterval"></a>`messageExpiryInterval`  | integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject]| Publish | 5 | Interval in seconds or a *Schema Object* containing the definition of the lifetime of the message. 
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string |  | |  The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Examples

```yaml
channels:
  user/signup:
    publish:
      bindings:
        mqtt:
          qos: 2
          retain: true
          messageExpiryInterval: 60
          bindingVersion: 0.2.0
```
```yaml
channels:
  user/signup:
    publish:
      bindings:
        mqtt:
          messageExpiryInterval:
            type: integer
            minimum: 30
            maximum: 300
          bindingVersion: 0.2.0
```
```yaml
channels:
  user/signup:
    subscribe:
      bindings:
        mqtt:
          qos: 2
          bindingVersion: 0.2.0
```

<a name="message"></a>

## Message Binding Object

This object contains information about the message representation in MQTT.

##### Fixed Fields

Field Name | Type | MQTT Versions | Description
---|:---:|:---:|---
<a name="messageBindingObjectPayloadFormatIndicator"></a>`payloadFormatIndicator` | integer | 5 | Either: **0** (zero): Indicates that the payload is unspecified bytes, or **1**: Indicates that the payload is UTF-8 encoded character data. |
<a name="messageBindingObjectCorrelationData"></a>`correlationData` | [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | Correlation Data is used by the sender of the request message to identify which request the response message is for when it is received.
<a name="messageBindingObjectContentType"></a>`contentType` | string | 5 | String describing the content type of the message payload. This should not conflict with the `contentType` field of the associated AsyncAPI Message object.
<a name="messageBindingObjectResponseTopic"></a>`responseTopic` | URI string \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | 5 | The topic (channel URI) for a response message.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Examples

```yaml
channels:
  user/signup:
    subscribe:
      message:
        bindings:
          mqtt:
            contentType: "application/json"
            correlationData:
              type: string
              format: uuid
            bindingVersion: 0.2.0
```
```yaml
channels:
  userSignup:
    address: user/signup
    messages:
      userSignup:
        bindings:
          mqtt:
            payloadFormatIndicator: 1
            contentType: "application/json"
            correlationData:
              type: string
              format: uuid
            responseTopic:
              type: string
              pattern: "response/client/([a-z1-9]+)"
            bindingVersion: 0.2.0
```

[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject
[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject

---

# mqtt5
Source: https://www.asyncapi.com/docs/reference/bindings/mqtt5.md

# mqtt5

# MQTT 5 Bindings

This document defines how to describe MQTT 5-specific information on AsyncAPI.

# **Deprecation Warning**: MQTT version 5 specific bindings are deprecated in favor of [MQTT bindings](../mqtt/README.md) that are not version specific.

<a name="version"></a>

## Version

Current version is `0.2.0`.

<a name="server"></a>

## Server Binding Object

This object contains information about the server representation in MQTT5.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="serverBindingObjectSessionExpiryInterval"></a>`sessionExpiryInterval` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) \| integer | Session Expiry Interval in seconds or a Schema Object containing the definition of the interval.
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

##### Example

```yaml
servers:
  production:
    bindings:
      mqtt5:
        sessionExpiryInterval: 60
        bindingVersion: 0.2.0
```
```yaml
servers:
  production:
    bindings:
      mqtt5:
        sessionExpiryInterval:
          type: integer
          minimum: 100
        bindingVersion: 0.2.0
```

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject
[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject

---

# nats
Source: https://www.asyncapi.com/docs/reference/bindings/nats.md

# nats

# NATS Bindings

This document defines how to describe NATS-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object
This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object
This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

Field Name | Type | Description
---|:---:|---
| <a name="operationBindingObjectQueue"></a>`queue` | string | Defines the name of the queue to use. It MUST NOT exceed 255 characters. |
| <a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed. |

<a name="Message"></a>
## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# pulsar
Source: https://www.asyncapi.com/docs/reference/bindings/pulsar.md

# pulsar

# Pulsar Bindings
This document defines how to describe Apache Pulsar specific information with AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>
## Server Binding Object

This object contains information about the server representation in Pulsar.

##### Fixed Fields

Field Name | Type | Required | Description | Default value |
---|:---:|:---:|:---|:---|
`tenant` | String | No | The pulsar tenant. If omitted, "public" MUST be assumed. | `public` |
`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` |

##### Example

```yaml
servers:
  production:
    bindings:
      pulsar:
        tenant: contoso
        bindingVersion: '0.1.0'
```

<a name="channel"></a>
## Channel Binding Object
This object contains information about the channel representation in Pulsar

##### Fixed Fields

Field Name | Type | Required | Description | Default value |
---|:---:|:---:|:---|:---|
`namespace` | String | Yes |  The namespace the channel is associated with. | N/A |
`persistence` | String | Yes | Persistence of the topic in Pulsar. It MUST be either `persistent` or `non-persistent`. | N/A |
`compaction`| Integer | No | Topic compaction threshold given in Megabytes. | N/A |
`geo-replication` | String[] | No | A list of clusters the topic is replicated to. | N/A |
`retention` | [Retention Definition Object](#retention-definition-object) | No | Topic retention policy.  | N/A |
`ttl` | Integer | No |  Message time-to-live in seconds. | N/A |
`deduplication` | Boolean | No | Message deduplication. When true, it ensures that each message produced on Pulsar topics is persisted to disk only once. | N/A |
`bindingVersion` | String | No | The version of this binding. If omitted, "latest" MUST be assumed. | `latest` |

<a name="retention-definition-object"></a>
### Retention Definition Object
The `Retention Definition Object` is used to describe the Pulsar [Retention](https://pulsar.apache.org/docs/cookbooks-retention-expiry/) policy.

Field Name | Type | Required | Description | Default value |
---|:---:|:---:|:---|:---|
`time`|Integer| No | Time given in Minutes. | `0` |
`size`|Integer| No |Size given in MegaBytes. | `0` |

##### Example

```yaml
channels:
  user-signedup:
    bindings:
      pulsar:
        namespace: 'staging'
        persistence: 'persistent'
        compaction: 1000
        geo-replication:
          - 'us-east1'
          - 'us-west1'
        retention:
          time: 7
          size: 1000
        ttl: 360
        deduplication: false
        bindingVersion: '0.1.0'
```

<a name="operation"></a>
## Operation binding fields
This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>
## Message binding fields
This object MUST NOT contain any properties. Its name is reserved for future use.

---

# redis
Source: https://www.asyncapi.com/docs/reference/bindings/redis.md

# redis

# Redis Bindings

This document defines how to describe Redis-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# ros2
Source: https://www.asyncapi.com/docs/reference/bindings/ros2.md

# ros2

# ROS 2 Bindings

This document defines how to describe ROS 2-specific information in AsyncAPI.

It applies to all [distributions of ROS 2](https://docs.ros.org/en/rolling/Releases.html).

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object contains information about the server representation in ROS 2. 
ROS 2 can use a vast variety of [middleware implementations](https://docs.ros.org/en/rolling/Installation/RMW-Implementations.html). This document focuses on DDS and Zenoh middleware implementations.
DDS-based ROS 2 implementations are per default decentralized with no central server, so the field `host` can be set to `none`.
For more information on DDS tuning, you can visit the [DDS Tuning Guide](https://docs.ros.org/en/rolling/How-To-Guides/DDS-tuning.html).
When using Zenoh, the `host` field specifies the Zenoh Router IP address.

###### Fixed Fields

Field Name | Type | Description
---|:---:|---|
`rmwImplementation` | string  |  Specifies the ROS 2 middleware implementation to be used. Valid values include the different [ROS 2 middleware vendors (RMW)](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Different-Middleware-Vendors.html) like `rmw_fastrtps_cpp` (Fast DDS) or `rmw_zenoh_cpp` (Zenoh). This determines the underlying middleware implementation that handles communication.
`domainId` | integer  |  All ROS 2 nodes use domain ID 0 by default. To prevent interference between different groups of computers running ROS 2 on the same network, a group can be set with a unique domain ID. [Must be a non-negative integer less than 232](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Domain-ID.html). 

### Examples

```yaml
servers:
  ros2:
    host: none
    protocol: ros2
    protocolVersion: humble
    bindings:
      ros2:
        rmwImplementation: rmw_fastrtps_cpp
        domainId: 0
```

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object contains information about the ROS 2 node.

###### Fixed Fields

Field Name | Type | Description
---|:---:|---|
`role` | string | Specifies the ROS 2 type of the node for this operation. If the action is `send`, valid values for the role are: `publisher`, `action_client`, `service_client`. If the action is `receive`, valid values for the role are: `subscriber`, `action_server`, `service_server`. This defines how the node will interact with the associated topic, service or action.
`node` | string | The name of the ROS 2 node that implements this operation. 
`qosPolicies` | [Quality of Service Policy Object](#QoSPolicyObject) | Quality of Service (QoS) for the topic.

<a name="QoSPolicyObject"></a>

### Quality of Service Object
This object contains ROS 2 specific information about the Quality of Service policies.
More information here: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies

Field Name | Type | Description
---|:---:|---|
`reliability` | string | One of `best_effort` or `reliable`.  More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
`history` | string | One of `keep_last`, `keep_all` or `unknown`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
`durability` | string | One of `transient_local` or `volatile`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
`lifespan` | integer |  The maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired. `-1` means infinite. 
`deadline` | integer | The expected maximum amount of time between subsequent messages being published to a topic. `-1` means infinite.
`liveliness` | string | One of `automatic` or `manual`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
`leaseDuration` | integer | The maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness. `-1` means infinite.

### Examples

ROS 2 subscriber example:

```yaml
receiveCmdVel:
  action: receive
  channel:
    $ref: "#/channels/CmdVel"
  bindings:
    ros2:
      role: subscriber
      node: /turtlesim
        qosPolicies:
          history: unknown
          reliability: reliable
          durability: volatile
          lifespan: -1
          deadline: -1
          liveliness: automatic
          leaseDuration: -1
```

ROS 2 publisher example:
```yaml
 Pose:
    action: receive
    channel:
      $ref: "#/channels/Pose"
    bindings:
      ros2:
        role: publisher
        node: /turtlesim
```

ROS 2 service server example:
```yaml
SetPen:
    action: receive
    channel:
      $ref: "#/channels/SetPenRequest"
    reply:
      channel:
        $ref: "#/channels/SetPenReply"
    bindings:
      ros2:
        role: service_server
        node: /turtlesim
```

ROS 2 service client example:
```yaml
SetPen:
    action: send
    channel:
      $ref: "#/channels/SetPenRequest"
    reply:
      channel:
        $ref: "#/channels/SetPenReply"
    bindings:
      ros2:
        role: service_client
        node: /node_client
```

ROS 2 action server example:
```yaml
receiveRotateAbsolute:
  action: receive
  channel:
    $ref: "#/channels/RotateAbsoluteRequest"
  reply:
    channel:
      $ref: "#/channels/RotateAbsoluteReply"
  bindings:
    ros2:
      role: action_server
      node: /turtlesim
```

ROS 2 action client example:
```yaml
RotateAbsolute:
    action: send
    channel:
      $ref: "#/channels/RotateAbsoluteRequest"
    reply:
      channel:
        $ref: "#/channels/RotateAbsoluteReply"
    bindings:
      ros2:
        role: action_client
        node: /teleop_turtle
```

<a name="message"></a>

## Message Binding Object

While this object DOES NOT contain any ROS 2 specific properties, it is important to understand how to express the different [ROS 2 data types](https://design.ros2.org/articles/legacy_interface_definition.html#:~:text=to%20IDL%20types-,ROS%20type,string,-The%20mapping%20of) in [AsyncAPI message types and formats](https://www.asyncapi.com/docs/reference/specification/v3.0.0#dataTypeFormat:~:text=The%20formats%20defined%20by%20the%20AsyncAPI%20Specification%20are%3A).

ROS 2  Type | AsyncAPI Type | AsyncAPI Format | 
---|:---:|---|
bool | boolean | boolean
byte | string | octet
char | integer | uint8
float32 | number | float
float64 | number | double
int8 | integer | int8
uint8 | integer | uint8
int16 | integer | int16
uint16 | integer | uint16
int32 | integer | int32
uint32 | integer | uint32
int64 | integer | int64
uint64 | integer | uint64
string | string | string
array | array | --

It is important to understand that the message header of the AsyncAPI specification does not map with the message header in ROS 2.
For this reason, the AsyncAPI message header will be ignored. If you want to define the header of a message in ROS 2, you should put in the payload of the message. [Example](https://docs.ros.org/en/ros2_packages/rolling/api/point_cloud_interfaces/msg/CompressedPointCloud2.html):

```yaml
channels:
  PointCloud:
    address: /pointCloud
    messages:
      CompressedPointCloud2:
        $ref: "#/components/messages/CompressedPointCloud2"
components:
  CompressedPointCloud2:
    tags:
      - name: msg
    payload:
      type: object
      properties:
        header:
          $ref: "#/components/messages/std_msgs/header/payload"
        height:
          $ref: "#/components/messages/uint32/payload"
        width:
          $ref: "#/components/messages/uint32/payload"
        fields:
          $ref: "#/components/messages/sensor_msgs/PointField/payload"
        is_bigendian:
          $ref: "#/components/messages/bool/payload"
        point_step:
          $ref: "#/components/messages/uint32/payload"
        row_step:
          $ref: "#/components/messages/uint32/payload"
        compressed_data:
          $ref: "#/components/messages/uint8/payload"
        is_dense:
          $ref: "#/components/messages/bool/payload"
        format:
          $ref: "#/components/messages/string/payload"     
```

## Complete example:
From the AsyncAPI specification example it could be extracted that:
- It consist on a ROS 2 Jazzy application running with Fast DDS as RMW. 
-  `/turtlesim` node is a subscriber of the `/turtle1/cmd_vel` topic and its qos policies.
- The interface of the `/turtle1/cmd_vel` topic is `Twist` that has a nested type: `Vector3`. Both of them are part of the standard package `geometry_msgs`.
- `Vector3` has already the types converted to AsyncAPI types and formats (number and double), instead of using the ROS 2 types.
- There is one file (head-asyncapi.yaml) that references the different standard/custom packages. This packages contains the strucute of its messages.

  ```
  ├── interfaces
  │ ├── geometry_msgs.yaml
  │ ├── std_msgs.yaml
  │ ├── <custom_pkg_msgs>.yaml
  │ └── ....
  └── head-asyncapi.yaml
  ```

head-asyncapi.yaml

```yaml
asyncapi: 3.0.0
info:
  title: Turtlesim example for ROS 2
  version: 1.0.0

servers:
  ros2:
    host: none
    protocol: ros2
    protocolVersion: jazzy
    bindings:
      ros2:
        rmwImplementation: rmw_fastrtps_cpp
        domainId: 0

channels:
  CmdVel:
    address: /turtle1/cmd_vel
    messages:
      Twist:
        $ref: ./interfaces/geometry_msgs.yaml#/components/messages/Twist

operations:
  CmdVel:
    action: receive
    channel:
      $ref: "#/channels/CmdVel"
    bindings:
      ros2:
        role: subscriber
        node: /turtlesim
        qosPolicies:
          history: unknown
          reliability: reliable
          durability: volatile
          lifespan: -1
          deadline: -1
          liveliness: automatic
          leaseDuration: -1
```

./interfaces/geometry_msgs.yaml
```yaml
asyncapi: 3.0.0
info:
  title: geometry_msgs
  version: 1.0.0
components:
  messages:
    Twist:
      tags:
        - name: msg
      payload:
        type: object
        properties:
          linear:
            $ref: "#/components/messages/Vector3/payload"
          angular:
            $ref: "#/components/messages/Vector3/payload"
    Vector3:
      payload:
        properties:
          x:
            type: number
            format: double
          y:
            type: number
            format: double
          z:
            type: number
            format: double
```

---

# 2.x.x
Source: https://www.asyncapi.com/docs/reference/bindings/2.x.x.md

# 2.x.x

# SNS Bindings

This document defines how to describe SNS-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.2.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object contains information about the channel representation in SNS.

We represent an AsyncAPI Channel with a Topic in SNS. The bindings here allow definition of a topic within SNS. We provide properties on the binding that allow creation of a topic in infrastructure-as-code scenarios. Be aware that although the binding offers that flexibility, it may be more maintainable to specify properties such as SNS Access Control Policy outside of AsyncAPI.

SNS supports many optional properties. To mark a channel as SNS, but use default values for the channel properties, just use an empty object {}. 

### Fields

|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingObjectName"></a>`name` | string | **Required.** The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations.|
| <a name="channelBindingObjectFifo"></a>`ordering` | [ordering](#ordering)| **Optional.** By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic.  |
| <a name="channelBindingObjectPolicy"></a>`policy` |[policy](#policy) | **Optional.** The security policy for the SNS Topic |
| <a name="channelBindingObjectTags"></a>`tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the topic. |
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.|

### Schemas

#### Ordering
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingFifoObjectChannelType"></a>`type` | string | **Required.** Defines the type of SNS Topic. Can be either `standard` or `FIFO`. |
| <a name="channelBindingContentBasedDeduplication"></a>`contentBasedDeduplication` | boolean | **Optional.** Whether the de-duplication of messages should be turned on. Defaults to `false`|

#### Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyObjectPolicyStatements"></a>`statements` | [[Statement](#statement)] | **Required.** An array of Statement objects, each of which controls a permission for this topic |

#### Statement
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyStatementObjectEffect"></a>`effect` | string |**Required.** Either "Allow" or "Deny"|
| <a name="channelBindingPolicyStatementObjectPrincipal"></a>`principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish|
| <a name="channelBindingPolicyStatementObjectAction"></a>`resource` | string or array of string |**Optional.** The resource(s) that this policy applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission|

##### Examples

Just use defaults

```yaml
channels:
  user-signedup:
    description:  A user has signed up to our service
    bindings:
      sns: {} 
```

Minimal definition, just policy

```yaml
channels:
  user-signedup:
    description:  A user has signed up to our service
    bindings:
      sns:
        policy:
          statements: 
          - effect : Allow
            principal: *
            action: SNS:Publish
```

<a name="operation"></a>

## Operation Binding Object

This object contains information operation binding in SNS.

We represent SNS producers via a **subscribe** Operation Object. In simple cases this may not require configuration, and can be shown as an empty SNS Binding Object i.e. {} if you need to explicitly indicate how a producer publishes to the channel.

We represent SNS consumers via a **publish** Operation Object. These consumers need an SNS Subscription that defines how they consume from SNS i.e. the protocol that they use, and any filters applied.

The SNS binding does not describe the receiver.If you wish to define the receiver, add a **publish** Operation Binding Object for that receiver. For example, if you send message to an SQS queue from an SNS Topic, you would add a protocol of 'sqs' and an Identifier object for the queue. That identifier could be an ARN of a queue defined outside of the scope of AsyncAPI, but if you wanted to define the receiver you would use the name of a queue defined in an SQS Binding on the **publish** Operation Binding Object.

We support an array of consumers via the **consumers** field. This allows you to represent multiple protocols consuming an SNS Topic in one file. You may also use it for multiple consumers with the same protocol, instead of representing each consumer in a separate file.

### Fields

| Field Name | Type | Applies To | Description |
|---|:---:|:---:|---|
| <a name="operationBindingObjectTopic"></a>`topic` | [identifier](#identifier) |Publish, Subscribe| **Optional.** Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document.|
| <a name="operationBindingObjectConsumers"></a>`consumers` | [[Consumer](#consumer)] |Publish| **Required.** The protocols that listen to this topic and their endpoints.|
| <a name="operationBindingObjectDeliveryPolicy"></a>`deliveryPolicy` | [deliveryPolicy](#delivery-policy) |Subscribe| **Optional.** Policy for retries to HTTP. The field is the default for HTTP receivers of the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) which may be overridden by a specific consumer.|
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string |Publish, Subscribe| **Optional**, defaults to `latest`. The version of this binding.|

### Schemas

#### Consumer

| Field Name | Type | Description |
|---|:---:|---|
| <a name="operationBindingObjectProtocol"></a>`protocol` | string | **Required.** The protocol that this endpoint receives messages by. Can be `http`, `https`, `email`, `email-json`, `sms`, `sqs`, `application`, `lambda` or `firehose` |
| <a name="operationBindingObjectEndpoint"></a>`endpoint` |[identifier](#identifier)| **Required.** The endpoint messages are delivered to. |
| <a name="operationBindingObjectFilterPolicy"></a>`filterPolicy` | object | **Optional.** Only receive a subset of messages from the channel, determined by this policy. |
| <a name="operationBindingObjectFilterPolicyScope"></a>`filterPolicyScope` | string | **Optional.** Determines whether the FilterPolicy applies to MessageAttributes (default) or MessageBody. |
| <a name="operationBindingObjectRawMessageDelivery"></a>`rawMessageDelivery` | boolean | **Required.** If *true* AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If *false* the SNS attributes are included in the body. |
| <a name="operationBindingObjectRedrivePolicy"></a>`redrivePolicy` | [redrivePolicy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue. |
| <a name="operationBindingObjectDeliveryPolicy"></a>`deliveryPolicy` | [deliveryPolicy](#delivery-policy) | **Optional.** Policy for retries to HTTP. The parameter is for that [SNS Subscription](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) and overrides any policy on the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html). |
| <a name="channelBindingObjectDisplayName"></a>`displayName` | string |**Optional.** The display name to use with an SMS subscription |

#### Delivery Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingDeliveryPolicyObjectMinDelayTarget"></a>`minDelayTarget` | integer | **Optional.** The minimum delay for a retry in seconds |
| <a name="channelBindingDeliverPolicyObjectMaxDelayTarget"></a>`maxDelayTarget` | integer | **Optional.** The maximum delay for a retry in seconds |
| <a name="channelBindingDeliveryPolicyObjectNumRetries"></a>`numRetries` | integer | **Optional.** The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries |
| <a name="channelBindingDeliveryPolicyObjectNumNoDelayRetries"></a>`numNoDelayRetries` | integer | **Optional.** The number of immediate retries (with no delay) |
| <a name="channelBindingDeliveryPolicyObjectNumMinDelayRetries"></a>`numMinDelayRetries` | integer | **Optional.** The number of immediate retries (with delay) |
| <a name="channelBindingDeliveryPolicyObjectNumMaxDelayRetries"></a>`numMaxDelayRetries` | integer | **Optional.** The number of post-backoff phase retries, with the maximum delay between retries |
| <a name="channelBindingDeliveryPolicyObjectBackoffFunction"></a>`backoffFunction` | string, one of: arithmetic, exponential, geometric or linear | **Optional.** The algorithm for backoff between retries |
| <a name="channelBindingDeliveryPolicyObjectMaxReceivesPerSecond"></a>`maxReceivesPerSecond` | integer | **Optional.** The maximum number of deliveries per second, per subscription |

#### Identifier
|Field Name | Type | Description                                                                                                                                                                                                                                                                                                                               |
|---|:---:|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|<a name="identifierObjectUrl"></a>`url` |string| **Optional.** The endpoint is a URL                                                                                                                                                                                                                                                                                                       |
|<a name="identifierObjectEmail"></a>`email` |string| **Optional.** The endpoint is an email address                                                                                                                                                                                                                                                                                            |
|<a name="identifierObjectPhone"></a>`phone` |string| **Optional.** The endpoint is a phone number                                                                                                                                                                                                                                                                                              |
|<a name="identifierObjectArn"></a>`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)"         |
|<a name="identifierObjectName"></a>`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding. We don't use $ref because we are referring, not including. |

We provide an Identifer Object to support providing the identifier of an externally defined endpoint for this SNS *publication* to target, or an endpoint on another binding against this Operation Object (via the name field). 

#### Redrive Policy

|Field Name | Type | Description|
|---|:---:|---|
| <a name="redrivePolicyObjectDeadLetterQueue"></a>`deadLetterQueue` |[Identifier](#identifier)| **Required.** The SQS queue to use as a dead letter queue (DLQ). Note that you may have a Redrive Policy to put messages that cannot be delivered to an SQS queue, even if you use another protocol to consume messages from the queue, so it is defined at the level of the SNS Operation Binding Object in a Consumer Object (and is applied as part of an [SNS Subscription](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)). The SQS Binding describes how to define an SQS Binding that supports defining the target SQS of the Redrive Policy. |
| <a name="redrivePolicyObjectMaxReceiveCount"></a>`maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Defaults to 10. |

### Examples

#### SNS to SQS Pub-Sub

[<img src="https://www.asyncapi.com/img/docs/SNS-SQS-Pub-Sub.png" height = "400" width="600"/>](SNS-SQS-Pub-Sub.png)

We are producing to an SNS channel

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    binding :
      sns: {}     # Indicates that the channel is an SNS Topic
    subscribe:
      operationId: sendMessage
      description: send messages to the topic
      bindings:
        sns:
          consumers:
            - protocol: sqs
              endpoint:
                name: myQueue
              rawMessageDelivery: false
```

We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding.

In this version, the SQS queue is defined elsewhere, and we just reference via its ARN. It is worth noting that this couples the specification to the AWS *region* and *account*, which are part of the ARN, and if we moved  the queue to a new region or account was this specification would need to be updated to reflect that.

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    publish:
      operationId: receiveMessage
      description: receive messages from the topic
      bindings:
        sns:
          consumers:
            - protocol: sqs
              endpoint:
                arn: arn:aws:sqs:us-west-2:123456789012:UserSignedUpQueue
              rawMessageDelivery: true  
```

We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the **publish** Operation Binding.

In this version, the SQS queue is defined in this file, and we reference it by name. For brevity that definition is not shown here. See the SQS Binding Object for more. 

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    publish:
      operationId: receiveMessage
      description: receive messages from the topic
      bindings:
        sns:
          consumers:
          - protocol: sqs
            endpoint:
              name: user-signedup-queue # refers to a queue defined in this file, but not shown in this example
            rawMessageDelivery: true  
            filterPolicy:
              reason: 
                anything-but: password-reset
            redrivePolicy:
              deadLetterQueue:
                name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example
```

#### SNS to HTTP Pub Sub

[<img src="https://www.asyncapi.com/img/docs/SNS-HTTP.png" height = "400" width="600"/>](SNS-HTTP.png)

We are producing to an SNS channel. 

In this version, we define a default delivery policy for any HTTP based consumers

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    bindings:
      sns:
        policy:
          statements: 
          - effect : Allow
            principal: *
            action: SNS:Publish 
    subscribe:
      operationId: sendMessage
      description: send messages to the topic
      bindings:
        sns:
          deliveryPolicy:
            minDelayTarget: 1
            maxDelayTarget: 60
            numRetries: 50
            numNoDelayRetries: 3
            numMinDelayRetries: 2
            numMaxDelayRetries: 35
            backoffFunction: exponential
            maxReceivesPerSecond: 10
```

We are consuming an SNS channel, using an HTTP endpoint, which is defined in this AsyncAPI file. For brevity we do not show an http endpoint here. The delivery policy here is defined for the http consumer and overrides any policy set by the producer

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    bindings:
      sns: {}    # Indicates that the channel is an SNS Topic, but assumes defined by producer
    publish:
      operationId: receiveMessage
      description: receive messages from the topic
      bindings:
        sns:
        - protocol: http
          endpoint:
            url: http://login.my.com/user/new
          filterPolicy:
            reason: 
              anything-but: password-reset
          filterPolicyScope: MessageBody
          deliveryPolicy:
            minDelayTarget: 1
            maxDelayTarget: 120
            numRetries: 30
            numNoDelayRetries: 3
            numMinDelayRetries: 2
            numMaxDelayRetries: 25
            backoffFunction: exponential
            maxReceivesPerSecond: 20
          redrivePolicy:
            deadLetterQueue:
              name: user-signedup-queue-dlq # refers toa queue defined in this file, but not show in this example
```

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# 3.0.0
Source: https://www.asyncapi.com/docs/reference/bindings/3.0.0.md

# 3.0.0

# SNS Bindings

This document defines how to describe SNS-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `1.0.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object contains information about the channel representation in SNS.

We represent an AsyncAPI Channel with a Topic in SNS. The bindings here allow definition of a topic within SNS. We provide properties on the binding that allow creation of a topic in infrastructure-as-code scenarios. Be aware that although the binding offers that flexibility, it may be more maintainable to specify properties such as SNS Access Control Policy outside of AsyncAPI.

SNS supports many optional properties. To mark a channel as SNS, but use default values for the channel properties, just use an empty object {}. 

### Fields

|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingObjectName"></a>`name` | string | **Required.** The name of the topic. Can be different from the channel name to allow flexibility around AWS resource naming limitations.|
| <a name="channelBindingObjectFifo"></a>`ordering` | [ordering](#ordering)| **Optional.** By default, we assume an unordered SNS topic. This field allows configuration of a FIFO SNS Topic.  |
| <a name="channelBindingObjectPolicy"></a>`policy` |[policy](#policy) | **Optional.** The security policy for the SNS Topic |
| <a name="channelBindingObjectTags"></a>`tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the topic. |
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.|

### Schemas

#### Ordering
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingFifoObjectChannelType"></a>`type` | string | **Required.** Defines the type of SNS Topic. Can be either `standard` or `FIFO`. |
| <a name="channelBindingContentBasedDeduplication"></a>`contentBasedDeduplication` | boolean | **Optional.** Whether the de-duplication of messages should be turned on. Defaults to `false`|

#### Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyObjectPolicyStatements"></a>`statements` | [[Statement](#statement)] | **Required.** An array of Statement objects, each of which controls a permission for this topic |

#### Statement
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyStatementObjectEffect"></a>`effect` | string |**Required.** Either "Allow" or "Deny"|
| <a name="channelBindingPolicyStatementObjectPrincipal"></a>`principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish|
| <a name="channelBindingPolicyStatementObjectAction"></a>`resource` | string or array of string |**Optional.** The resource(s) that this policy applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission|

##### Examples

Just use defaults

```yaml
channels:
  user-signedup:
    description:  A user has signed up to our service
    bindings:
      sns: {} 
```

Minimal definition, just policy

```yaml
channels:
  user-signedup:
    description:  A user has signed up to our service
    bindings:
      sns:
        policy:
          statements: 
          - effect : Allow
            principal: *
            action: SNS:Publish
```

<a name="operation"></a>

## Operation Binding Object

This object contains information operation binding in SNS.

We represent SNS producers via a **subscribe** Operation Object. In simple cases this may not require configuration, and can be shown as an empty SNS Binding Object i.e. {} if you need to explicitly indicate how a producer publishes to the channel.

SNS consumers need an SNS Subscription that defines how they consume from SNS i.e. the protocol that they use, and any filters applied.

The SNS binding does not describe the receiver.If you wish to define the receiver, add an Operation Binding Object for that receiver. For example, if you send message to an SQS queue from an SNS Topic, you would add a protocol of 'sqs' and an Identifier object for the queue. That identifier could be an ARN of a queue defined outside of the scope of AsyncAPI, but if you wanted to define the receiver you would use the name of a queue defined in an SQS Binding in the Operation Binding Object.

We support an array of consumers via the **consumers** field. This allows you to represent multiple protocols consuming an SNS Topic in one file. You may also use it for multiple consumers with the same protocol, instead of representing each consumer in a separate file.

### Fields

| Field Name | Type | Applies To | Description |
|---|:---:|:---:|---|
| <a name="operationBindingObjectTopic"></a>`topic` | [identifier](#identifier) |send, receive| **Optional.** Often we can assume that the SNS Topic is the channel name-we provide this field in case the you need to supply the ARN, or the Topic name is not the channel name in the AsyncAPI document.|
| <a name="operationBindingObjectConsumers"></a>`consumers` | [[Consumer](#consumer)] |receive| **Required.** The protocols that listen to this topic and their endpoints.|
| <a name="operationBindingObjectDeliveryPolicy"></a>`deliveryPolicy` | [deliveryPolicy](#delivery-policy) |send| **Optional.** Policy for retries to HTTP. The field is the default for HTTP receivers of the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) which may be overridden by a specific consumer.|
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string |send, receive| **Optional**, defaults to `latest`. The version of this binding.|

### Schemas

#### Consumer

| Field Name | Type | Description |
|---|:---:|---|
| <a name="operationBindingObjectProtocol"></a>`protocol` | string | **Required.** The protocol that this endpoint receives messages by. Can be `http`, `https`, `email`, `email-json`, `sms`, `sqs`, `application`, `lambda` or `firehose` |
| <a name="operationBindingObjectEndpoint"></a>`endpoint` |[identifier](#identifier)| **Required.** The endpoint messages are delivered to. |
| <a name="operationBindingObjectFilterPolicy"></a>`filterPolicy` | object | **Optional.** Only receive a subset of messages from the channel, determined by this policy. |
| <a name="operationBindingObjectFilterPolicyScope"></a>`filterPolicyScope` | string | **Optional.** Determines whether the FilterPolicy applies to MessageAttributes (default) or MessageBody. |
| <a name="operationBindingObjectRawMessageDelivery"></a>`rawMessageDelivery` | boolean | **Required.** If *true* AWS SNS attributes are removed from the body, and for SQS, SNS message attributes are copied to SQS message attributes. If *false* the SNS attributes are included in the body. |
| <a name="operationBindingObjectRedrivePolicy"></a>`redrivePolicy` | [redrivePolicy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue. |
| <a name="operationBindingObjectDeliveryPolicy"></a>`deliveryPolicy` | [deliveryPolicy](#delivery-policy) | **Optional.** Policy for retries to HTTP. The parameter is for that [SNS Subscription](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) and overrides any policy on the [SNS Topic](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html). |
| <a name="channelBindingObjectDisplayName"></a>`displayName` | string |**Optional.** The display name to use with an SMS subscription |

#### Delivery Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingDeliveryPolicyObjectMinDelayTarget"></a>`minDelayTarget` | integer | **Optional.** The minimum delay for a retry in seconds |
| <a name="channelBindingDeliverPolicyObjectMaxDelayTarget"></a>`maxDelayTarget` | integer | **Optional.** The maximum delay for a retry in seconds |
| <a name="channelBindingDeliveryPolicyObjectNumRetries"></a>`numRetries` | integer | **Optional.** The total number of retries, including immediate, pre-backoff, backoff, and post-backoff retries |
| <a name="channelBindingDeliveryPolicyObjectNumNoDelayRetries"></a>`numNoDelayRetries` | integer | **Optional.** The number of immediate retries (with no delay) |
| <a name="channelBindingDeliveryPolicyObjectNumMinDelayRetries"></a>`numMinDelayRetries` | integer | **Optional.** The number of immediate retries (with delay) |
| <a name="channelBindingDeliveryPolicyObjectNumMaxDelayRetries"></a>`numMaxDelayRetries` | integer | **Optional.** The number of post-backoff phase retries, with the maximum delay between retries |
| <a name="channelBindingDeliveryPolicyObjectBackoffFunction"></a>`backoffFunction` | string, one of: arithmetic, exponential, geometric or linear | **Optional.** The algorithm for backoff between retries |
| <a name="channelBindingDeliveryPolicyObjectMaxReceivesPerSecond"></a>`maxReceivesPerSecond` | integer | **Optional.** The maximum number of deliveries per second, per subscription |

#### Identifier
|Field Name | Type | Description|
|---|:---:|---|
|<a name="identifierObjectUrl"></a>`url` |string| **Optional.** The endpoint is a URL  |
|<a name="identifierObjectEmail"></a>`email` |string| **Optional.** The endpoint is an email address |
|<a name="identifierObjectPhone"></a>`phone` |string| **Optional.** The endpoint is a phone number|
|<a name="identifierObjectArn"></a>`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)"|
|<a name="identifierObjectName"></a>`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on the Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding. We don't use $ref because we are referring, not including. |

We provide an Identifer Object to support providing the identifier of an externally defined endpoint for this SNS *publication* to target, or an endpoint on another binding against this Operation Object (via the name field). 

#### Redrive Policy

|Field Name | Type | Description|
|---|:---:|---|
| <a name="redrivePolicyObjectDeadLetterQueue"></a>`deadLetterQueue` |[Identifier](#identifier)| **Required.** The SQS queue to use as a dead letter queue (DLQ). Note that you may have a Redrive Policy to put messages that cannot be delivered to an SQS queue, even if you use another protocol to consume messages from the queue, so it is defined at the level of the SNS Operation Binding Object in a Consumer Object (and is applied as part of an [SNS Subscription](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)). The SQS Binding describes how to define an SQS Binding that supports defining the target SQS of the Redrive Policy. |
| <a name="redrivePolicyObjectMaxReceiveCount"></a>`maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Defaults to 10. |

### Examples

#### SNS to SQS Pub-Sub

[<img src="https://www.asyncapi.com/img/docs/SNS-SQS-Pub-Sub.png" height = "400" width="600"/>](SNS-SQS-Pub-Sub.png)

We are producing to an SNS channel

```yaml
channels:
  userSignedUp:
    description:  A user has signed up for our service
    binding :
      sns: {}     # Indicates that the channel is an SNS Topic
operations:
  userSignedUp:
    description:  A user has signed up for our service
    operationId: sendMessage
    description: send messages to the topic
    action: send
    binding:
      sns:
        consumers:
          - protocol: sqs
            endpoint:
              name: myQueue
            rawMessageDelivery: false
    channel:
      $ref: '#/channels/userSignedUp'
```

We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the Operation Binding.

In this version, the SQS queue is defined elsewhere, and we just reference via its ARN. It is worth noting that this couples the specification to the AWS *region* and *account*, which are part of the ARN, and if we moved  the queue to a new region or account was this specification would need to be updated to reflect that.

```yaml
channels:
  userSignedUp:
    # ...(redacted for brevity)
operations:
  userSignedUp:
    description:  A user has signed up for our service
    operationId: receiveMessage
    description: receive messages from the topic
    action: receive
    bindings:
      sns:
        consumers:
          - protocol: sqs
            endpoint:
              arn: arn:aws:sqs:us-west-2:123456789012:UserSignedUpQueue
            rawMessageDelivery: true  
    channel:
      $ref: '#/channels/userSignedUp'
```

We are consuming an SNS channel, using an SQS queue. A separate file specifies the producer, and has the SNS Bindings for the channel. For this reason we do not repeat the SNS binding information for the channel here, to avoid duplicated definitions diverging. Instead we just define the Operation Binding.

In this version, the SQS queue is defined in this file, and we reference it by name. For brevity that definition is not shown here. See the SQS Binding Object for more. 

```yaml
channels:
  userSignedUp:
    # ...(redacted for brevity)
operations:
  userSignedUp:
    description:  A user has signed up for our service
    operationId: receiveMessage
    description: receive messages from the topic
    action: receive
    bindings:
      sns:
        consumers:
          - protocol: sqs
            endpoint:
              name: user-signedup-queue # refers to a queue defined in this file, but not shown in this example
            rawMessageDelivery: true  
            filterPolicy:
              reason: 
                anything-but: password-reset
            redrivePolicy:
              deadLetterQueue:
                name: user-signedup-queue-dlq # refers to a queue defined in this file, but not show in this example
    channel:
      $ref: '#/channels/userSignedUp'
```

#### SNS to HTTP Pub Sub

[<img src="https://www.asyncapi.com/img/docs/SNS-HTTP.png" height = "400" width="600"/>](SNS-HTTP.png)

We are producing to an SNS channel. 

In this version, we define a default delivery policy for any HTTP based consumers

```yaml
channels:
  userSignedUp:
    description:  A user has signed up for our service
    bindings:
      sns:
        policy:
          statements: 
          - effect : Allow
            principal: *
            action: SNS:Publish 
operations:
  userSignedUp:
    description:  A user has signed up for our service
    operationId: sendMessage
    description: send messages to the topic
    action: send
    binding:
      sns:
        deliveryPolicy:
          minDelayTarget: 1
          maxDelayTarget: 60
          numRetries: 50
          numNoDelayRetries: 3
          numMinDelayRetries: 2
          numMaxDelayRetries: 35
          backoffFunction: exponential
          maxReceivesPerSecond: 10
    channel:
      $ref: '#/channels/userSignedUp'
```

We are consuming an SNS channel, using an HTTP endpoint, which is defined in this AsyncAPI file. For brevity we do not show an http endpoint here. The delivery policy here is defined for the http consumer and overrides any policy set by the producer

```yaml
channels:
  userSignedUp:
    description:  A user has signed up for our service
    bindings:
      sns: {} # Indicates that the channel is an SNS Topic, but assumes defined by producer
operations:
  userSignedUp:
    description:  A user has signed up for our service
    operationId: receiveMessage
    description: receive messages from the topic
    action: receive
    bindings:
      sns:
        - protocol: http
          endpoint:
            url: http://login.my.com/user/new
          filterPolicy:
            reason: 
              anything-but: password-reset
          filterPolicyScope: MessageBody
          deliveryPolicy:
            minDelayTarget: 1
            maxDelayTarget: 120
            numRetries: 30
            numNoDelayRetries: 3
            numMinDelayRetries: 2
            numMaxDelayRetries: 25
            backoffFunction: exponential
            maxReceivesPerSecond: 20
          redrivePolicy:
            deadLetterQueue:
              name: user-signedup-queue-dlq # refers to a queue defined in this file, but not show in this example
    channel:
      $ref: '#/channels/userSignedUp'
```

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# solace
Source: https://www.asyncapi.com/docs/reference/bindings/solace.md

# solace

# Solace Bindings

This document defines how to describe Solace-specific information with AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.4.0`.

<a name="server"></a>

## Server Binding Object

| Field Name       | Type   | Description                                                                                                                                                        |
|------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `bindingVersion` | String | The current version is 0.4.0                                                                                                                                       |
| `msgVpn`         | String | The Virtual Private Network name on the Solace broker.                                                                                                             |
| `clientName`     | String | A unique client name to use to register to the appliance. If specified, it must be a valid Topic name, and a maximum of 160 bytes in length when encoded as UTF-8. |

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

We need the ability to support several bindings for each operation, see the [Example](#example) section below for details.

| Field Name       | Type                                                                            | Description                                                                                                                                                  |
|------------------|---------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `bindingVersion` | String                                                                          | The current version is 0.4.0                                                                                                                                 |
| `destinations`   | List of Destination Objects                                                     | Destination Objects are described next.                                                                                                                      |
| `timeToLive`     | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | Interval in milliseconds or a *Schema Object* containing the definition of the lifetime of the message.                                                      |
| `priority`       | Integer \| [Schema Object][schemaObject] \| [Reference Object][referenceObject] | The valid priority value range is 0-255 with 0 as the lowest priority and 255 as the highest or a *Schema Object* containing the definition of the priority. |
| `dmqEligible`    | Boolean                                                                         | Set the message to be eligible to be moved to a Dead Message Queue. The default value is false.                                                              |

### Destination Object

Each destination has the following structure:

| Field Name                 | Type           | Description                                                                                                                                                                                                                          |
|----------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `bindingVersion`           | String         | The current version is 0.4.0                                                                                                                                                                                                         |
| `destinationType`          | Enum           | 'queue' or 'topic'. If the type is queue, then the subscriber can bind to the queue, which in turn will subscribe to the topic as represented by the channel name or to the provided topicSubscriptions.                             |
| `deliveryMode`             | Enum           | 'direct' or 'persistent'. This determines the quality of service for publishing messages as documented [here.](https://docs.solace.com/Get-Started/Core-Concepts-Message-Delivery-Modes.htm) Default is 'persistent'.                |
| `queue.name`               | String         | The name of the queue, only applicable when destinationType is 'queue'.                                                                                                                                                              |
| `queue.topicSubscriptions` | List of String | A list of topics that the queue subscribes to, only applicable when destinationType is 'queue'. If none is given, the queue subscribes to the topic as represented by the channel name.                                              |
| `queue.accessType`         | Enum           | 'exclusive' or 'nonexclusive'. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Endpoints.htm#Queues) Only applicable when destinationType is 'queue'.                                                    |
| `queue.maxMsgSpoolSize`    | String         | The maximum amount of message spool that the given queue may use. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Message-Spooling.htm#max-spool-usage) Only applicable when destinationType is 'queue'. |
| `queue.maxTtl`             | String         | The maximum TTL to apply to messages to be spooled. This is documented [here.](https://docs.solace.com/Messaging/Guaranteed-Msg/Configuring-Queues.htm) Only applicable when destinationType is 'queue'.                             |
| `topic.topicSubscriptions` | List of String | A list of topics that the client subscribes to, only applicable when destinationType is 'topic'. If none is given, the client subscribes to the topic as represented by the channel name.                                            |

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="example"></a>

## Example with two destinations ##

Here is an example of when we could need two Solace destinations.

Imagine a system where there is a schema called Person, and there are topics:

`person/{personId}/created`

and

`person/{personId}/updated`

and you have one application that receives both events. We also want each to be on its own queue. The AsyncAPI file could look like this:

```yaml
components:
  schemas:
    Person:
      type: string        
  messages:
    PersonEvent:
      payload:
        $ref: '#/components/schemas/Person'
      schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0
      contentType: application/json
operations:
  addPerson:
    action: send
    channel:
      $ref: '#/channels/address'
    messages:
      - $ref: '#/channels/address/messages/personEvent'
    bindings:
      solace:
        bindingVersion: 0.4.0
        destinations:
          - destinationType: queue
            queue:
              name: CreatedHREvents
              topicSubscriptions:
                - person/*/created
          - destinationType: queue
            queue:
              name: UpdatedHREvents
              topicSubscriptions:
                - person/*/updated
        timeToLive: 5000
        priority: 120
        dmqEligible: true

channels:
  person:
    address: person/{personId}/{eventType}
    parameters:
      personId:
        schema:
          type: string
      eventType:
        schema:
          type: string
    messages:
      personEvent:
        $ref: '#/components/messages/PersonEvent'
asyncapi: 3.0.0
info:
  title: HRApp
  version: 0.0.1
```

The expected behavior would be that the application binds to both queues, and each queue has its own topic subscription, one to create and one to updated events.

## Example with a wildcard subscription ##

This example shows how a client could receive all the topics under `person/` using a wildcard subscription:

```yaml
components:
  schemas:
    Person:
      type: string
  messages:
    PersonEvent:
      payload:
        schemaFormat: application/vnd.aai.asyncapi+json;version=3.0.0
        schema:
          $ref: '#/components/schemas/Person'
      contentType: application/json
operations:
  addPerson:
    action: send
    channel:
      $ref: '#/channels/person'
    messages:
      - $ref: '#/channels/person/messages/personEvent'
    bindings:
      solace:
        bindingVersion: 0.4.0
        destinations:
          - destinationType: queue
            queue:
              name: CreatedHREvents
              topicSubscriptions:
                - person/*/created
          - destinationType: queue
            queue:
              name: UpdatedHREvents
              topicSubscriptions:
                - person/*/updated
        timeToLive: 5000
        priority: 120
        dmqEligible: true

channels:
  person:
    address: person/{personId}/{eventType}
    parameters:
      personId:
        description: The machine readable id of the person
      eventType:
        enum:
          - create
          - delete
    messages:
      personEvent:
        $ref: '#/components/messages/PersonEvent'
asyncapi: 3.0.0
info:
  title: HRApp
  version: 0.0.1
```

[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject
[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject

---

# sqs
Source: https://www.asyncapi.com/docs/reference/bindings/sqs.md

# sqs

# SQS Bindings

This document defines how to describe SQS-specific information on AsyncAPI.

SQS can be used both stand-alone as a point-to-point and paired with SNS and as a publish-subscribe channel (where SQS is the endpoint that SNS delivers messages to). For this reason we define a Queue schema, and reference that schema from both a Channel Binding Object and a **publish** Operation Binding Object. 

For point-to-point scenarios, use the Channel Binding Object, as producers send to the queue and consumers receive from it directly.

For publish-subscribe scenarios, use as a **publish** Operation Binding Object, as the producer sends to SNS and the consumer receives via SQS.

<a name="version"></a>

## Version

Current version is `0.3.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object 

Use the Channel Binding Operation for Point-to-Point SQS channels.

There are three likely scenarios for use of the Channel Binding Object:

- One file defines both publish and subscribe operations, for example if we were implementing the work queue pattern to offload work from an HTTP API endpoint to a worker process. In this case the channel would be defined on the Channel Object in that single file. 
- The producer and consumer both have an AsyncAPI specification file, and the producer is raising an event, for example interop between microservices, and the producer 'owns' the channel definition and thus has the SQS Binding on its Channel Object. 
- The producer and consumer both have an AsyncAPI specification file, and the consumer receives commands, for example interop between microservices, and the consumer 'owns' the channel  definition and thus has the SQS Binding on its Channel Object. 

An SQS queue can set up a Dead Letter Queue as part of a Redelivery Policy. To support this requirement, the Channel Binding Object allows you to define both a Queue Object to use as the Channel or target in a *publish* Operation and a Dead Letter Queue. You can then refer to the Dead letter Queue in the Redrive Policy using the Identifier Object and setting the *name* field to match the *name* field of your Dead Letter Queue Object. (If you define the DLQ externally, the Identifier also supports an ARN). 

### Fields
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingObjectQueue"></a>`queue` | [Queue](#queue)| **Required.** A definition of the queue that will be used as the channel. |
| <a name="channelBindingObjectDLQ"></a>`deadLetterQueue` | [Queue](#queue)| **Optional.** A definition of the queue that will be used for un-processable messages. |
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.|

### Schemas

#### Queue
|Field Name | Type | Description|
|---|:---:|---|
| <a name="queueObjectName"></a>`name` | string | **Required.** The name of the queue. When an [SNS Operation Binding Object]() references an SQS queue by name, the identifier should be the one in this field.|
| <a name="fifoQueue"></a>`fifoQueue` | boolean | **Required.**  Is this a FIFO queue? |
| <a name="deduplicationScope"></a>`deduplicationScope` | string | **Optional.**  Specifies whether message deduplication occurs at the message group or queue level. Valid values are `messageGroup` and `queue`. **This property applies only to high throughput for FIFO queues.** |
| <a name="fifoThroughputLimit"></a>`fifoThroughputLimit` | string | **Optional.**  Specifies whether the FIFO queue throughput quota applies to the entire queue or per message group. Valid values are `perQueue` and `perMessageGroupId`. **The `perMessageGroupId` value is allowed only when the value for DeduplicationScope is `messageGroup`. Setting both these values as such will enable high throughput on a FIFO queue. As above, this property applies only to high throughput for FIFO queues.** |
| <a name="queueObjectDeliveryDelay"></a>`deliveryDelay` | integer | **Optional.** The number of seconds to delay before a message sent to the queue can be received. Used to create a *delay queue*. Range is 0 to 15 minutes. Defaults to 0. |
| <a name="queueObjectVisbilityTimeout"></a>`visibilityTimeout` |integer| **Optional.** The length of time, in seconds, that a consumer locks a message - hiding it from reads - before it is unlocked and can be read again. Range from 0 to 12 hours (43200 seconds). Defaults to 30 seconds. |
| <a name="queueObjectRecieveMessageWaitTime"></a>`receiveMessageWaitTime` |integer| **Optional.** Determines if the queue uses [short polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html) or [long polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html). Set to zero (the default) the queue reads available messages and returns immediately. Set to a non-zero integer, long polling waits the specified number of seconds for messages to arrive before returning.  |
| <a name="queueObjectMessageRetentionPeriod"></a>`messageRetentionPeriod` |integer| **Optional.** How long to retain a message on the queue in seconds, unless deleted. The range is 60 (1 minute) to 1,209,600 (14 days). The default is 345,600 (4 days). |
| <a name="queueObjectRedrivePolicy"></a>`redrivePolicy` | [Redrive Policy](#redrive-policy) | **Optional.** Prevent poison pill messages by moving un-processable messages to an SQS dead letter queue.|
| <a name="queueObjectPolicy"></a>`policy` |[Policy](#policy) | **Optional.** The security policy for the SQS Queue | 
| <a name="queueObjectTags"></a>`tags` |Object | **Optional.** Key-value pairs that represent AWS tags on the queue. |

#### Identifier
|Field Name | Type | Description                                                                                                                                                                                                                                                                                                                       |
|---|:---:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|<a name="identifierObjectArn"></a>`arn` |string| **Optional.** The target is an [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). For example, for SQS, the identifier may be an ARN, which will be of the form: "[arn:aws:sqs:\{region\}:\{account-id\}:\{queueName\}](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)" |
|<a name="identifierObjectName"></a>`name` |string| **Optional.** The endpoint is identified by a name, which corresponds to an identifying field called 'name' of a binding for that protocol on this **publish** Operation Object. For example, if the protocol is 'sqs' then the name refers to the name field **sqs** binding                                                     |

#### Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyObjectPolicyStatements"></a>`Statements` | [Statement](#statement) | **Required.** An array of Statement objects, each of which controls a permission for this queue. |

#### Redrive Policy
|Field Name | Type | Description|
|---|:---:|---|
| <a name="redrivePolicyObjectDeadLetterQueue"></a>`deadLetterQueue` |[Identifier](#identifier)| The SQS queue to use as a dead letter queue (DLQ) |
| <a name="redrivePolicyObjectMaxReceiveCount"></a>`maxReceiveCount` |integer| **Optional.** The number of times a message is delivered to the source queue before being moved to the dead-letter queue. Default is 10. | 

#### Statement
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingPolicyStatementObjectEffect"></a>`effect` | string |**Required.** Either "Allow" or "Deny"|
| <a name="channelBindingPolicyStatementObjectPrincipal"></a>`principal` | string or AWS principal property containing a string or string array |**Required.** The AWS account(s) or resource ARN(s) that the statement applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`action` | string or array of string |**Required.** The SNS permission being allowed or denied e.g. sns:Publish|
| <a name="channelBindingPolicyStatementObjectAction"></a>`resource` | string or array of string |**Optional.** The resource(s) that this policy applies to|
| <a name="channelBindingPolicyStatementObjectAction"></a>`condition` | object or list of objects |**Optional.** Specific circumstances under which the policy grants permission|

<a name="operation"></a>

## Operation Binding Object

### SQS Point-To-Point

Because we have defined Queue as part of the Channel Binding Binding object, we do not require Binding information for the **publish** Operation Object of the **subscribe** Operation Object. You can use an empty Queue object ({}) to denote the Binding on the Operation Object, if you want to indicate the protocol used to send or receive for generation purposes such as Infrastructure As Code.

### SNS to SQS Pub-Sub

Use the Operation Binding Object when SQS is listening to an SNS Topic. In this case we need to define both an SQS Operation Binding Objects on the receiver **publish** Operation Object to represent the queue definition and we need to define an SNS Operation Binding Object to define the Subscription to SNS that makes your queue a receiver of that endpoint.

Assuming you have separate AsyncAPI specifications for the producer and the consumer, we would assume the following bindings would appear for an SNS producer and an SQS consumer.

Producer: SNS Channel Binding Object, SNS **subscribe** Operation Binding Object [if required]
Consumer: SNS **publish** Operation Binding Object, SQS **publish** Operation Binding Object

- We assume that the SNS binding information only needs to be present in the producer file (although defining it in both is allowable) and any infrastructure as code dependencies can recognize this.

On an Operation Binding Object we support an array of Queue objects. Members of this array may be Queue Objects that define the *endpoint* field required by an [SNS Operation Object]() delivering by the SQS protocol or Queue Objects that define the Dead Letter Queue used by either the Redrive Policy of the SNS Subscription (see the SNS Binding Object) or the [Redrive Policy of the SQS Queue](#redrive-policy). The name of the Queue Object is used by an Identifier field on either the *endpoint* field of the SNS Operation Object of *deadLetterQueue* on the Redrive Policy to identify the required member of this array.
 

### Fields
|Field Name | Type | Description|
|---|:---:|---|
| <a name="channelBindingObjectQueue"></a>`queues` | [[Queue](#queue)]| **Required.** Queue objects that are either the *endpoint* for an SNS Operation Binding Object, or the *deadLetterQueue* of the SQS Operation Binding Object |
|<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.|

### Examples

#### SQS Point-To-Point

[<img src="https://www.asyncapi.com/img/docs/SQS-Point-To-Point.png" height = "400" width="600"/>](SQS-Point-To-Point.png)

In this example, we are using SQS for a point-to-point channel. For this example, we assume that we are defining two microservices that communicate over a shared SQS channel, with the consumer receiving events over that channel and the producer owning the channel definition.

The producer file would look like this:

```yaml
channels:
  user-signedup:
    bindings:
      sqs:
        queue:
          name: user-signedup-queue
          fifoQueue: false
          receiveMessageWaitTime: 4
          redrivePolicy:
            deadLetterQueue:
              name: user-signedup-dlq
          policy:
            statements: 
            - effect : Allow
              principal: *
              action: Sqs:SendMessage
            - effect : Allow
              principal: *
              action: Sqs:ReceiveMessage
        deadLetterQueue: 
          name: user-signedup-dlq 
          messageRetentionPeriod: 1209600 
	        fifoQueue: false
    subscribe:
      operationId: sendMessage
      description: sends messages when a user has signed up
      bindings:
        sqs: {}

```
In this case we can minimize duplicated information by omitting the binding in our specification, and assume it is picked up from the producer file. We can use an empty object to indicate the SQS Binding on the **publish** Operation Object, if need a marker for generation, otherwise we could omit the Operation Binding Object.

```yaml
channels:
  user-signedup:
   publish:
      operationId: receiveMessage
      description: receives a messages when a user has signed up
      bindings:
        sqs: {}

```

#### SNS to SQS Pub-Sub

[<img src="https://www.asyncapi.com/img/docs/SNS-SQS-Pub-Sub.png" height = "400" width="600"/>](SNS-SQS-Pub-Sub.png)

In this example, we are using SNS for the channel, and SQS to receive from SNS. 

The producer files looks like this (see the [SNS Binding]() for more).

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    binding :
      sns: {}     # Indicates that the channel is an SNS Topic
    subscribe:
      operationId: sendMessage
      description: send messages to the topic
      bindings:
        sns:
          policy:
            statements: 
            - effect : Allow
              principal: *
              action: SNS:Publish
```

And the consumer file would look like this. Note that for simplicity, we choose not to repeat the SNS Binding on the Consumer as it does not 'own' the channel.

```yaml
channels:
  user-signedup:
    description:  A user has signed up for our service
    publish:
      operationId: receiveMessage
      description: receive messages from the topic
      bindings:
        sns:
          consumers:
          - protocol: sqs
            endpoint:
            name: user-signedup-queue
            rawMessageDelivery: true  
            filterPolicy:
              attributes:
                reason: 
                  anything-but: password-reset
            redrivePolicy:
              deadLetterQueue:
              name: user-signedup-queue-dlq
        sqs:
          queues:
          - name: user-signedup-queue
            fifoQueue: false
            receiveMessageWaitTime: 4
            policy:
              statements: 
              - effect : Allow
                principal: *
                action: Sqs:SendMessage
              - effect : Allow
                principal: *
                action: Sqs:ReceiveMessage 
          - name: user-signedup-dlq 
            messageRetentionPeriod: 1209600 
            fifoQueue: false
```

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# stomp
Source: https://www.asyncapi.com/docs/reference/bindings/stomp.md

# stomp

# STOMP Bindings

This document defines how to describe STOMP-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

---

# websockets
Source: https://www.asyncapi.com/docs/reference/bindings/websockets.md

# websockets

# WebSockets Bindings

This document defines how to describe WebSockets-specific information on AsyncAPI.

<a name="version"></a>

## Version

Current version is `0.1.0`.

<a name="server"></a>

## Server Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="channel"></a>

## Channel Binding Object

When using WebSockets, the channel represents the connection. Unlike other protocols that support multiple virtual channels (topics, routing keys, etc.) per connection, WebSockets doesn't support virtual channels or, put it another way, there's only one channel and its characteristics are strongly related to the protocol used for the handshake, i.e., HTTP.

##### Fixed Fields

Field Name | Type | Description
---|:---:|---
<a name="operationBindingObjectMethod"></a>`method` | string | The HTTP method to use when establishing the connection. Its value MUST be either `GET` or `POST`.
<a name="operationBindingObjectQuery"></a>`query` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions for each query parameter. This schema MUST be of type `object` and have a `properties` key.
<a name="operationBindingObjectHeaders"></a>`headers` | [Schema Object][schemaObject] \| [Reference Object](referenceObject) | A Schema object containing the definitions of the HTTP headers to use when establishing the connection. This schema MUST be of type `object` and have a `properties` key.
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | The version of this binding. If omitted, "latest" MUST be assumed.

This object MUST contain only the properties defined above.

<a name="operation"></a>

## Operation Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

<a name="message"></a>

## Message Binding Object

This object MUST NOT contain any properties. Its name is reserved for future use.

[schemaObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#schemaObject
[referenceObject]: https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#referenceObject

---

# Overview
Source: https://www.asyncapi.com/docs/migration.md

# Overview

Migration to a new major version is always difficult, and AsyncAPI is no exception, but we want to provide as smooth a transition as possible.

If you are just looking to update your AsyncAPI document, then we suggest you use the [AsyncAPI converter](https://github.com/asyncapi/converter-js). You can do this directly in the CLI with:

```bash
asyncapi convert asyncapi.json --output=new_asyncapi.json --target-version=x.x.x
```

For a detailed read-through about all the changes (non-breaking as well), please do [read the release notes](https://www.asyncapi.com/blog?tags=Release+Notes) for the desired version before hand, as it will give you some more context about the changes.

Here are all the migration guides:
- [Migrating to v3](/docs/migration/migrating-to-v3.md)

---

# Migrating to v3
Source: https://www.asyncapi.com/docs/migration/migrating-to-v3.md

# Migrating to v3

Migration to a new major version is always difficult, and AsyncAPI is no exception. To provide as smooth a transition as possible, this document shows the breaking changes between AsyncAPI v2 and v3 in an interactive manner.

If you want to update your AsyncAPI document, use the [AsyncAPI converter](https://github.com/asyncapi/converter-js) directly in the CLI with the following command:

```bash
asyncapi convert asyncapi.json --output=asyncapi_v3.json --target-version=3.0.0
```

For a detailed read-through about all the changes (non-breaking as well), read all the [v3 release notes](/blog/release-notes-3.0.0.md) first to acquire additional context about the changes introduced in v3.

## Moved metadata

In v2, two properties of `tags` and `externalDocs` were placed outside of the [Info Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#infoObject). For consistency, `info` has been moved in v3. 

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

```yml
asyncapi: 2.6.0
info: 
  ...
externalDocs:
  description: Find more info here
  url: https://www.asyncapi.com
tags:
  - name: e-commerce
```

```yml
asyncapi: 3.0.0
info:
  externalDocs:
    description: Find more info here
    url: https://www.asyncapi.com
  tags:
    - name: e-commerce
```

## Server URL splitting up
There was occasional confusion regarding what the URL of a [Server Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#serverObject) should include.

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, the URL was often a lengthy string, sometimes redundantly including details like the protocol.

In v3, the `url` property has been divided into `host`, `pathname`, and `protocol`—as was the case in v2—making the information more explicit.

```yml
asyncapi: 2.6.0
servers:
  production:
    url: "amqp://rabbitmq.in.mycompany.com:5672/production"
    protocol: "amqp"
```

```yml
asyncapi: 3.0.0
servers:
  production:
    host: "rabbitmq.in.mycompany.com:5672",
    pathname: "/production",
    protocol: "amqp",
```

## Operation, channel, and message decoupling

The decoupling of operations, channels, and messages is the most significant breaking change in v3, fundamentally altering how they relate to each other.

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, reusing channels and having multiple operations per channel, such as operation variants, was impossible.

In v3, this has become possible, emphasizing that a channel and message should be independent of the operations performed.

For message brokers like Kafka, this is akin to defining topics and their associated messages. In REST interfaces, it pertains to the path and request type (e.g., POST, GET), along with the corresponding request and response messages. For WebSocket, it encompasses all messages transmitted through the WebSocket server. For Socket.IO, it delineates all the rooms and their messages.

Channels are now reusable across multiple AsyncAPI documents, each facilitating a slightly different action.

```yml
asyncapi: 2.6.0
...
channels: 
  user/signedup:
    publish:
      message:
        payload:
          type: object
          properties:
            displayName:
              type: string
              description: Name of the user
```

```yml
asyncapi: 3.0.0
...
channels:
  UserSignup:
    address: "user/signedup"
    messages: 
      UserMessage: 
        payload:
          type: object
          properties:
            displayName:
              type: string
              description: Name of the user
operations:
  ConsumeUserSignups:
    action: receive
    channel: 
      $ref: "#/channels/UserSignup"
```

Read more about the confusion between publishing and subscribing in the [Operation keywords](#operation-keywords) section.

## Channel address and channel key

Another breaking change is that the channel key no longer represents the channel path. Instead, it's now an arbitrary unique ID. The channel paths are now defined using the `address` property within the [Channel Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#channelObject).

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, the channel's `address/topic/path` doubled as its ID, hindering reusability and preventing the definition of scenarios where the same address was used in different contexts.

In v3, the `address/topic/path` has been shifted to an `address` property, allowing the channel ID to be distinct and arbitrary. 

```yml
asyncapi: 2.6.0
...
channels: 
  test/path:
    ...
```

```yml
asyncapi: 3.0.0
channels:
  testPathChannel:
    address: "test/path"
```

## Operation keywords

Another significant change is the shift away from defining operations using `publish` and `subscribe`, which had inverse meanings for your application. Now, you directly specify your application's behavior using `send` and `receive` via the `action` property in the [Operation Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#operationObject). 

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, the `publish` and `subscribe` operations consistently caused confusion, even among those familiar with the intricacies.

When you specified `publish`, it implied that others could `publish` to this channel since your application subscribed to it. Conversely, `subscribe` meant that others could subscribe because your application was the one publishing.

In v3, these operations have been entirely replaced with an `action` property that clearly indicates what your application does. That eliminates ambiguities related to other parties or differing perspectives.

Read more information about the confusion between publishing and subscribing:
- Fran Méndez's [Proposal to solve publish/subscribe confusion](https://github.com/asyncapi/spec/issues/618)
- Nic Townsend's blog post [Demystifying the Semantics of Publish and Subscribe](https://www.asyncapi.com/blog/publish-subscribe-semantics)

Here is an example where the application both consumes and produces messages to the test channel:

```yml
asyncapi: 2.6.0
...
channels: 
  test/path:
    subscribe:
      ...
    publish:
      ...
```

```yml
asyncapi: 3.0.0
channels:
  testPathChannel:
    address: "test/path"
    ...
operations: 
  publishToTestPath:
    action: send
    channel: 
      $ref: "#/channels/testPathChannel"
  consumeFromTestPath:
    action: receive
    channel: 
      $ref: "#/channels/testPathChannel"
```

## Messages instead of message
In v2, channels were defined with one or more messages through the operation using the `oneOf` property.

In v3, messages are defined using the [Messages Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#messagesObject). For a channel with multiple messages, you specify multiple key-value pairs. For a channel with just one message, you use a single key-value pair.

```yml
asyncapi: 2.6.0
...
channels:
  user/signedup:
    publish:
      ...
      message: 
        oneOf:
          - messageId: UserMessage
            ...
          - messageId: UserMessage2
            ...

asyncapi: 2.6.0
...
channels:
  user/signedup:
    publish:
      ...
      message: 
        messageId: UserMessage
        ...
```

```yml
asyncapi: 3.0.0
...
channels:
  UserSignup:
    address: user/signedup
    messages: 
      UserMessage: 
        ...
      UserMessage2:
        ...

asyncapi: 3.0.0
...
channels:
  UserSignup:
    address: user/signedup
    messages: 
      UserMessage: 
        ...
```

We have updated the structure of the Message Object by eliminating the `messageId` property. We now use the ID of the Message Object itself as the key in the key/value pairing, rendering a separate `messageId` property redundant.

## Unifying explicit and implicit references

In v2, implicit references were allowed in certain instances. For instance, the server security configuration was identified by name, linking to a [Security Schema Object](https://www.asyncapi.com/docs/reference/specification/v2.6.0#securitySchemeObject) within the components. Similarly, a channel could reference global servers by name.

In v3, all such references MUST be explicit. As a result, we made a minor modification to the [Server Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#serverObject) `security` property, transforming it from an object to an array. The details regarding required scopes for OAuth and OpenID Connect were then relocated to the [Security Scheme Object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#securitySchemeObject). 

```yml
asyncapi: 2.6.0
servers:
  production:
    ...
    security:
      oauth_test: ["write:pets"]
...
channels: 
  test/path:
    servers:
      - production
components:
  securitySchemes:
    oauth_test: 
      type: oauth2
      flows:
        implicit:
          authorizationUrl: 'https://example.com/api/oauth/dialog'
          availableScopes:
            'write:pets': modify pets in your account
            'read:pets': read your pets
      scopes:
        - 'write:pets'
```

```yml
asyncapi: 3.0.0
servers:
  production:
    ...
    security:
      - $ref: "#/components/securitySchemes/oauth_test"
...
channels: 
  test/path:
    servers:
      - $ref: "#/servers/production"
components:
  securitySchemes:
    oauth_test:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: 'https://example.com/api/oauth/dialog'
          availableScopes:
            'write:pets': modify pets in your account
            'read:pets': read your pets
      scopes:
        - "write:pets"
```

## New trait behavior
In v2, traits invariably overwrote any duplicate properties specified both in the traits and the corresponding object. For instance, if both message traits and the message object defined headers, only the headers from the message traits would be recognized, effectively overriding those in the Message Object.

In v3, this behavior has been revised. The primary objects now take precedence over any definitions in the traits. Such an adjustment is consistent for traits in both operation and message objects.

Here is a message object and associated traits:
```yml
messageId: userSignup
description: A longer description.
payload:
  $ref: '#/components/schemas/userSignupPayload'
traits:
  - summary: Action to sign a user up.
    description: Description from trait.
```

In v2, after applying the traits, the complete message object appeared as follows. Note how the `description` was overridden:

```yml
messageId: userSignup
summary: Action to sign a user up.
description: Description from trait.
payload:
  $ref: '#/components/schemas/userSignupPayload'
```
That is the default behavior of the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) algorithm we use.

In v3, we've instituted a guideline stating, `A property on a trait MUST NOT override the same property on the target object`. Consequently, after applying the traits in v3, the complete message object appears as follows:

```yml
messageId: userSignup
summary: Action to sign a user up.
description: A longer description. # it's still description from "main" object
payload:
  $ref: '#/components/schemas/userSignupPayload'
```
Notice how the `description` is no longer overwritten.

## Schema format and schemas

One limitation with schemas has always been the inability to reuse them across different schema formats.

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, the details about which schema format the payload uses are found within the message object, rather than being directly linked to the schema itself. Such separation hampers reusability, as the two data points aren't directly correlated.

To address this in v3, we've introduced [a multi-format schema object](https://www.asyncapi.com/docs/reference/specification/v3.0.0#multiFormatSchemaObject) that consolidates this information. Consequently, whenever you utilize `schemaFormat`, you'll need to modify the schema as follows: 

```yml
asyncapi: 2.6.0
...
channels:
  user/signedup:
    publish:
      message: 
        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
        payload:
          type: record
          name: User
          namespace: com.company
          doc: User information
          fields:
            - name: displayName
              type: string
```

```yml
asyncapi: 3.0.0
...
channels:
  UserSignup:
    address: user/signedup
    messages: 
      userSignup: 
        payload:
          schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
          schema:
            type: record
            name: User
            namespace: com.company
            doc: User information
            fields:
              - name: displayName
                type: string
```

## Optional channels
In v3, defining channels has become entirely optional, eliminating the need to specify channels as an empty object (required in v2).

```yml
asyncapi: 2.6.0
...
channels: {}
```

```yml
asyncapi: 3.0.0
...
```

## Restricted parameters object

Parameters have often prioritized convenience over accurately reflecting real-world use cases.

See the interactive comparison on the HTML page: https://www.asyncapi.com/docs/migration/migrating-to-v3

In v2, we significantly streamlined the Schema Object. While the previous version offered full capability with numerous, often underutilized options, it posed challenges in serializing objects or booleans in the channel path. 

The new v3 simplifies this by consistently using the string type and limiting available properties. Now, you can only access `enum`, `default`, `description`, `examples`, and `location`, ensuring a more focused and practical approach.

```yml
asyncapi: 2.6.0
...
channels: 
  user/{user_id}/signedup:
    parameters:
      location: "$message.payload"
      description: Just a test description
      schema:
        type: string
        enum: ["test"]
        default: "test"
        examples: ["test"]
    ...
```

```yml
asyncapi: 3.0.0
...
channels: 
  userSignedUp:
    address: user/{user_id}/signedup
    parameters:
      user_id: 
        enum: ["test"]
        default: "test"
        description: Just a test description
        examples: ["test"]
        location: "$message.payload"
```

---

# About
Source: https://www.asyncapi.com/about.md

# About

## AsyncAPI

AsyncAPI is an Apache License 2.0 library under the Linux Foundation that seeks to improve the current state of event-driven architecture (EDA). The AsyncAPI Initiative is a specification and growing set of open-source tools to help developers define, build, and maintain asynchronous APIs and EDAs. 

Developers familiar with OpenAPI (aka Swagger) for RESTful APIs will see strong similarities when using AsyncAPI. One common use case is generating asynchronous API documentation (HTML or Markdown). The specification is both platform and language agnostic. The current tooling includes support for common message brokers such as Apache Kafka and RabbitMQ and languages including Python, Java, and Nodejs. 

Our long-term goal is to make working with EDAs as easy as working with REST APIs. That goes from documentation to code generation, discovery to event management, and beyond. Our 150+ Open-Source (OSS) contributors are EDA enthusiasts from all around the world.

The AsyncAPI project started at Hitch (a.k.a. API Changelog). Hitch needed a machine-readable format to describe internal message-driven microservices architecture. The goal was to benefit from it in the same way they had used OpenAPI for their HTTP APIs. Inspired by OpenAPI, [Fran Méndez](https://twitter.com/fmvilas), who worked at Hitch at the time, created the AsyncAPI specification. After publishing the first version, he noticed that he solved not only his problems but the problems of the wider community. Eventually, the AsyncAPI specification and community evolved into the AsyncAPI Initiative, a project now under the umbrella of the Linux Foundation.

## Open governance model

Free software allows users to apply, modify, and continue in the chain by distributing copies to help others and, in this case, disseminating modified versions of the specification. 

Transferring AsyncAPI to the Linux Foundation and forming [an open governance model](https://github.com/asyncapi/community/blob/master/docs/020-governance-and-policies/CHARTER.md) assures the community that a single company does not control AsyncAPI Initiative. This move takes the project to a higher level of transparency. 

In doing so, we achieve:

- Ensuring an open governance model where no single company dominates the specification and its tools.
- Making the project as democratic as possible.
- Relying on an asynchronous decision-making process that empowers the people who "work," not the companies who "pay." 

In other words, it [gives equal power to individual and corporate contributors](https://www.asyncapi.com/blog/governance-motivation).

## Maintainers 

**Committers** (also known as **Maintainers**) are the decision-makers at the repository/project level. They regularly contribute to the project and are invited by other maintainers to manage the repository, have more privileges, and approve pull requests.

The committers run the repository, but for issues that go beyond that, there is a [Technical Steering Committee (TSC)](/community/tsc). This committee comprises all the maintainers who voluntarily want to be part of this committee, thus taking responsibility for overseeing the initiative.

You can see the list of maintainers who also form part of the [AsyncAPI TSC here](/community/tsc).

## Contributors

We do our best to recognize every contribution to the project. We do it individually in every repository from [AsyncAPI GitHub organization](https://github.com/asyncapi/). There should always be a **Contributors** section in the readme, like [this one](https://github.com/asyncapi/asyncapi/blob/master/README.md#contributors). We use [All Contributors](https://allcontributors.org/en/reference/specification/) specification to handle recognitions. 

We apologize in advance if we failed to recognize your work. Feel free to contact us on [Slack](https://www.asyncapi.com/slack-invite/), and we will fix it immediately, or just talk to our [All Contributors bot](https://allcontributors.org/en/bot/).

## AsyncAPI, in numbers
Interested to know more about our growth? Feel free to check our annual summary report: 
- [Summary report 2022](https://www.asyncapi.com/blog/2022-summary)
- [Summary report 2021](https://www.asyncapi.com/blog/2021-summary)
- [Summary report 2020](https://www.asyncapi.com/blog/2020-summary)
          
## Companies support

This is the list of companies that either provide a significant financial support or delegate their employees to support AsyncAPI with maintainance:

Would you like to get on the list and support us financially? Check out all [AsyncAPI sponsoring options](https://opencollective.com/asyncapi).

Would you like to help us with the maintenance? Contact us on [AsyncAPI Slack](https://www.asyncapi.com/slack-invite/).

## Brands and companies using AsyncAPI
The total number of companies and projects using AsyncAPI as well as their identity is impossible to know. So far, we are aware that the following ones operate with it.
- [**Slack**](https://slack.com/signin#/signin): Business Communication Platform that permits to operate with multiple channels (public and private). It currently has more than 10 million daily active users worldwide. It was recently acquired by Salesforce.
- [**Adidas**](https://www.adidas.com/us): Company dedicated to manufacturing sports equipment and fashion products. It is the largest sportswear manufacturer in Europe, and the second largest in the world. This company has more than 150.000 sales outlets around the world.
- [**Salesforce**](https://login.salesforce.com/?locale=es): Business consultancy company. It provides (CRM) services and more. It manages from small businesses to FORTUNE 500 companies, and it has more than 150,000 customers.
- [**IBM**](https://www.ibm.com): Company that manufactures and markets hardware and software. It has operations in over 170 countries and provides hosting and consulting services in many areas.
- [**SAP**](https://www.sap.com/index.html): Company dedicated to the design of computer products for business management. Develops business software to manage operations and business-to-customer relationships. It’s a large company with 100,330 employees.
- [**IQVIA**](https://www.iqvia.com/): Company providing services for the combined health information technology and clinical research industries. It employs more than 58.000 people in over 100 countries.

## Values of AsyncAPI

- **Innovative**. There is no other specification that covers the messaging needs in event-driven architecture that AsyncAPI is covering. What it tries to do is to integrate with the existing tools and remove walls for communication.
- **Free**. It’s a free software project: it seeks the user's liberty by offering a tool that can be used and enhanced without restrictions.
- **Open**. As it's an open-source project, not a company or a product. It works in a change of paradigm because it does not sell anything; it moves away from fierce competition and bets for cooperation.
- **Multicultural and inclusive**. It’s an initiative with an international and multicultural vision. It’s organic, always in constant mutation and change. It also actively demands compliance with human rights, respect for racial, sexual, and cultural diversity equality. And, of course, the equality between women and men.
- **Transparent**. The initiative is built on transparency, being one of the main values of AsyncAPI, internally and externally, including its financing. All the relevant data of the project is public. All tasks are public, with participation and communication handled through Slack and GitHub.
- **Horizontal and participative**. Its structure is based on horizontality; most of the decisions are defined as a group, including the Community. Anyone can submit improvements, lines of action, or elements to be taken into account to strengthen AsyncAPI.
- **User-friendly**. AsyncAPI bets for a seamless API development experience. Users should be able to create their first API even without prior knowledge of AsyncAPI. It has to be natural, simple, and intuitive.

## Funding

AsyncAPI is an open-source project funded by both talent and voluntary contributions. It relies on the expertise and dedication of the **Community developers** who believe in the project and contribute to its evolution.

Financially, there are individual donations and contributions made by users of the project, and others from different companies and initiatives that trust and support AsyncAPI through sponsorship. The main sponsors that contribute to sustaining this initiative are Postman, IBM, IQVIA Technology, and Solace. AsyncAPI also receives different levels of contributions from other companies such as Red Hat, Slack, etc.

All the information about the project's economy, the amount of the donations, the identity of the donors, the sponsors supporting the project, and the use of this money is public via the [AsyncAPI Open Collective](https://opencollective.com/asyncapi).

## Contact details

- Press & communications info:
[**info@asyncapi.com**](mailto:info@asyncapi.com).
- [**Twitter**](https://twitter.com/asyncapispec?lang=es): It's used for disseminating all news and information regarding the project, resolving user queries, and sharing the latest updates within AsyncAPI.
- [**Slack workspace**](https://www.asyncapi.com/slack-invite): The main place of encounter for the whole community of AsyncAPI.
- [**Newsletter**](https://www.asyncapi.com/newsletter): To learn about the status of the project, news, actualizations, recorded events, and meetings.
- [**Blog**](https://www.asyncapi.com/blog): It’s used to disseminate information related to the project. It's also open to collaborations.
- [**LinkedIn**](https://es.linkedin.com/company/asyncapi): It's used to publish news related to the project or its environment. It’s also used as a source of information.
- [**YouTube Channel**](https://www.youtube.com/playlist?list=PLbi1gRlP7pijUwZJErzyYf_Rc-PWu4lXS): Where you can find conferences, AsyncAPI Open Meetings, and much more.
- [**GitHub**](https://github.com/asyncapi): Issues (bugs, feature requests, etc.) and pull requests (PRs) for fixes or new features already discussed, as per the contributing guidelines.
- [**AsyncAPI Open Meetings**](https://github.com/asyncapi): AsyncAPI hosts different meetings every week. They are focused on different topics, sometimes purely technical and sometimes about community building. Pick one and join us! [Learn more about our meetings](/community/meetings)

## FAQs
