Streams

An Async API Definition For The Slack Real Time Messaging API

We are working to document different WebSocket APIs we’ve come across using the AsyncAPI specification. The specification is new, and we are just beginning to understand how it all works, and we are learning a lot from the existing work of the contributors to the AsyncAPI project. They’ve recently added the ability to document event-driven WebSocket APIs, that will differ from other message-based, and even SSE streaming APIs. They all share a number of components but have unique needs which the AsyncAPI teams have moved recently to accommodate as part of the machine-readable specification. To help demonstrate what is possible when you document a WebSocket API using AsyncAPI, we wanted to share a definition for the Slack Real Time Messaging API they’ve published as part of their working examples in the Github repository for the Async API specification.

asyncapi: '1.2.0'
info:
  title: Slack Real Time Messaging API
  version: '1.0.0'

servers:
  - url: https://slack.com/api/rtm.connect
    scheme: https
    schemeVersion: '1.1'

security:
  - token: []

events:
  receive:
    - $ref: '#/components/messages/hello'
    - $ref: '#/components/messages/connectionError'
    - $ref: '#/components/messages/accountsChanged'
    - $ref: '#/components/messages/botAdded'
    - $ref: '#/components/messages/botChanged'
    - $ref: '#/components/messages/channelArchive'
    - $ref: '#/components/messages/channelCreated'
    - $ref: '#/components/messages/channelDeleted'
    - $ref: '#/components/messages/channelHistoryChanged'
    - $ref: '#/components/messages/channelJoined'
    - $ref: '#/components/messages/channelLeft'
    - $ref: '#/components/messages/channelMarked'
    - $ref: '#/components/messages/channelRename'
    - $ref: '#/components/messages/channelUnarchive'
    - $ref: '#/components/messages/commandsChanged'
    - $ref: '#/components/messages/dndUpdated'
    - $ref: '#/components/messages/dndUpdatedUser'
    - $ref: '#/components/messages/emailDomainChanged'
    - $ref: '#/components/messages/emojiRemoved'
    - $ref: '#/components/messages/emojiAdded'
    - $ref: '#/components/messages/fileChange'
    - $ref: '#/components/messages/fileCommentAdded'
    - $ref: '#/components/messages/fileCommentDeleted'
    - $ref: '#/components/messages/fileCommentEdited'
    - $ref: '#/components/messages/fileCreated'
    - $ref: '#/components/messages/fileDeleted'
    - $ref: '#/components/messages/filePublic'
    - $ref: '#/components/messages/fileShared'
    - $ref: '#/components/messages/fileUnshared'
    - $ref: '#/components/messages/goodbye'
    - $ref: '#/components/messages/groupArchive'
    - $ref: '#/components/messages/groupClose'
    - $ref: '#/components/messages/groupHistoryChanged'
    - $ref: '#/components/messages/groupJoined'
    - $ref: '#/components/messages/groupLeft'
    - $ref: '#/components/messages/groupMarked'
    - $ref: '#/components/messages/groupOpen'
    - $ref: '#/components/messages/groupRename'
    - $ref: '#/components/messages/groupUnarchive'
    - $ref: '#/components/messages/imClose'
    - $ref: '#/components/messages/imCreated'
    - $ref: '#/components/messages/imMarked'
    - $ref: '#/components/messages/imOpen'
    - $ref: '#/components/messages/manualPresenceChange'
    - $ref: '#/components/messages/memberJoinedChannel'
    - $ref: '#/components/messages/message'
  send:
    - $ref: '#/components/messages/outgoingMessage'

components:
  securitySchemes:
    token:
      type: httpApiKey
      name: token
      in: query

  schemas:
    attachment:
      type: object
      properties:
        fallback:
          type: string
        color:
          type: string
        pretext:
          type: string
        author_name:
          type: string
        author_link:
          type: string
          format: uri
        author_icon:
          type: string
          format: uri
        title:
          type: string
        title_link:
          type: string
          format: uri
        text:
          type: string
        fields:
          type: array
          items:
            type: object
            properties:
              title:
                type: string
              value:
                type: string
              short:
                type: boolean
        image_url:
          type: string
          format: uri
        thumb_url:
          type: string
          format: uri
        footer:
          type: string
        footer_icon:
          type: string
          format: uri
        ts:
          type: number

  messages:
    hello:
      summary: First event received upon connection.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['hello']

    connectionError:
      summary: Event received when a connection error happens.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['error']
          error:
            type: object
            properties:
              code:
                type: number
              msg:
                type: string

    accountsChanged:
      summary: The list of accounts a user is signed into has changed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['accounts_changed']

    botAdded:
      summary: A bot user was added.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['bot_added']
          bot:
            type: object
            properties:
              id:
                type: string
              app_id:
                type: string
              name:
                type: string
              icons:
                type: object
                additionalProperties:
                  type: string

    botChanged:
      summary: A bot user was changed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['bot_added']
          bot:
            type: object
            properties:
              id:
                type: string
              app_id:
                type: string
              name:
                type: string
              icons:
                type: object
                additionalProperties:
                  type: string

    channelArchive:
      summary: A channel was archived.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_archive']
          channel:
            type: string
          user:
            type: string

    channelCreated:
      summary: A channel was created.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_created']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number
              creator:
                type: string

    channelDeleted:
      summary: A channel was deleted.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_deleted']
          channel:
            type: string

    channelHistoryChanged:
      summary: Bulk updates were made to a channel's history.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_history_changed']
          latest:
            type: string
          ts:
            type: string
          event_ts:
            type: string

    channelJoined:
      summary: You joined a channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_joined']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number
              creator:
                type: string

    channelLeft:
      summary: You left a channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_left']
          channel:
            type: string

    channelMarked:
      summary: Your channel read marker was updated.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_marked']
          channel:
            type: string
          ts:
            type: string

    channelRename:
      summary: A channel was renamed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_rename']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number

    channelUnarchive:
      summary: A channel was unarchived.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['channel_unarchive']
          channel:
            type: string
          user:
            type: string

    commandsChanged:
      summary: A slash command has been added or changed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['commands_changed']
          event_ts:
            type: string

    dndUpdated:
      summary: Do not Disturb settings changed for the current user.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['dnd_updated']
          user:
            type: string
          dnd_status:
            type: object
            properties:
              dnd_enabled:
                type: boolean
              next_dnd_start_ts:
                type: number
              next_dnd_end_ts:
                type: number
              snooze_enabled:
                type: boolean
              snooze_endtime:
                type: number

    dndUpdatedUser:
      summary: Do not Disturb settings changed for a member.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['dnd_updated_user']
          user:
            type: string
          dnd_status:
            type: object
            properties:
              dnd_enabled:
                type: boolean
              next_dnd_start_ts:
                type: number
              next_dnd_end_ts:
                type: number

    emailDomainChanged:
      summary: The workspace email domain has changed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['email_domain_changed']
          email_domain:
            type: string
          event_ts:
            type: string

    emojiRemoved:
      summary: A custom emoji has been removed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['emoji_changed']
          subtype:
            type: string
            enum: ['remove']
          names:
            type: array
            items:
              type: string
          event_ts:
            type: string

    emojiAdded:
      summary: A custom emoji has been added.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['emoji_changed']
          subtype:
            type: string
            enum: ['add']
          name:
            type: string
          value:
            type: string
            format: uri
          event_ts:
            type: string

    fileChange:
      summary: A file was changed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_change']
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileCommentAdded:
      summary: A file comment was added.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_comment_added']
          comment: {}
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileCommentDeleted:
      summary: A file comment was deleted.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_comment_deleted']
          comment:
            type: string
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileCommentEdited:
      summary: A file comment was edited.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_comment_edited']
          comment: {}
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileCreated:
      summary: A file was created.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_created']
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileDeleted:
      summary: A file was deleted.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_deleted']
          file_id:
            type: string
          event_ts:
            type: string

    filePublic:
      summary: A file was made public.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_public']
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileShared:
      summary: A file was shared.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_shared']
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    fileUnshared:
      summary: A file was unshared.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['file_unshared']
          file_id:
            type: string
          file:
            type: object
            properties:
              id:
                type: string

    goodbye:
      summary: The server intends to close the connection soon.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['goodbye']

    groupArchive:
      summary: A private channel was archived.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_archive']
          channel:
            type: string

    groupClose:
      summary: You closed a private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_close']
          user:
            type: string
          channel:
            type: string

    groupHistoryChanged:
      summary: Bulk updates were made to a private channel's history.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_history_changed']
          latest:
            type: string
          ts:
            type: string
          event_ts:
            type: string

    groupJoined:
      summary: You joined a private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_joined']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number
              creator:
                type: string

    groupLeft:
      summary: You left a private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_left']
          channel:
            type: string

    groupMarked:
      summary: A private channel read marker was updated.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_marked']
          channel:
            type: string
          ts:
            type: string

    groupOpen:
      summary: You opened a private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_open']
          user:
            type: string
          channel:
            type: string

    groupRename:
      summary: A private channel was renamed.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_rename']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number

    groupUnarchive:
      summary: A private channel was unarchived.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['group_unarchive']
          channel:
            type: string
          user:
            type: string

    imClose:
      summary: You closed a DM.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['im_close']
          channel:
            type: string
          user:
            type: string

    imCreated:
      summary: A DM was created.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['im_created']
          channel:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              created:
                type: number
              creator:
                type: string
          user:
            type: string

    imMarked:
      summary: A direct message read marker was updated.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['im_marked']
          channel:
            type: string
          ts:
            type: string

    imOpen:
      summary: You opened a DM.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['im_open']
          channel:
            type: string
          user:
            type: string

    manualPresenceChange:
      summary: You manually updated your presence.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['manual_presence_change']
          presence:
            type: string

    memberJoinedChannel:
      summary: A user joined a public or private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['member_joined_channel']
          user:
            type: string
          channel:
            type: string
          channel_type:
            type: string
            enum:
              - C
              - G
          team:
            type: string
          inviter:
            type: string

    memberLeftChannel:
      summary: A user left a public or private channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['member_left_channel']
          user:
            type: string
          channel:
            type: string
          channel_type:
            type: string
            enum:
              - C
              - G
          team:
            type: string

    message:
      summary: A message was sent to a channel.
      payload:
        type: object
        properties:
          type:
            type: string
            enum: ['message']
          user:
            type: string
          channel:
            type: string
          text:
            type: string
          ts:
            type: string
          attachments:
            type: array
            items:
              $ref: '#/components/schemas/attachment'
          edited:
            type: object
            properties:
              user:
                type: string
              ts:
                type: string

    outgoingMessage:
      summary: A message was sent to a channel.
      payload:
        type: object
        properties:
          id:
            type: number
          type:
            type: string
            enum: ['message']
          channel:
            type: string
          text:
            type: string

The specification is pretty verbose, but it provides a great example of a robust WebSockets API, that we can all reverse engineer and learn about how to properly define WebSocket APIs using the specification format. Outlining how to properly define the events, and their corresponding messages, providing a machine-readable definition for a WebSocket API.

We have 50 WebSocket APIs we’ve worked to craft AsyncAPI definitions for. We are working to publish them as a single collection of definitions as part of the Streamdata.io API Gallery. Once up, we’ll publish a story on the collection, providing other examples of WebSocket APIs that have been documented using AsyncAPI. We see AsyncAPI being just as important to the evolution of the API sectors as OpenAPI, but providing an accompanying specification for defining streaming, event, and message-based APIs. If you are in the business of delivering streaming, event-based, or message-based APIs we recommend getting involved and contribute to the community.

Slack real time messaging

**Original source: streamdata.io blog