We profiled an AsyncAPI Definition For The Slack Real Time Messaging API last week, showing what is possible for profiling Websocket APIs using the machine-readable specification format. This week we wanted to showcase a slight variation by profiling an API that employs Server-Sent Events (SSE), and takes advantage of the streaming object for the AsyncAPI specification. Reusing many of the elements are similar for defining a Websocket API, but putting the stream object to work, instead of events or topics as you might for other event or message-driven APIs. This is a streaming API for the message and networking platform Gitter, which provides an SSE version of their API for listening to messages, events, and changes in rooms. The Gitter Streaming API is much simpler than the Slack Real-Time Message API was, but still provides a nice glimpse at how to use AsyncAPI for SSE streams as opposed to Websockets:
asyncapi: '1.2.0'
info:
title: Gitter Streaming API
version: '1.0.0'
servers:
- url: https://stream.gitter.im/v1/rooms/{roomId}/{resource}
scheme: https
schemeVersion: '1.1'
variables:
roomId:
description: Id of the Gitter room.
resource:
description: The resource to consume.
enum:
- chatMessages
- events
security:
- httpBearerToken: []
stream:
framing:
type: 'chunked'
delimiter: '\r\n'
read:
- $ref: '#/components/messages/chatMessage'
- $ref: '#/components/messages/heartbeat'
components:
securitySchemes:
httpBearerToken:
type: http
scheme: bearer
messages:
chatMessage:
summary: >-
A message represents an individual chat message sent to a room.
They are a sub-resource of a room.
payload:
type: object
properties:
id:
type: string
description: ID of the message.
text:
type: string
description: Original message in plain-text/markdown.
html:
type: string
description: HTML formatted message.
sent:
type: string
format: date-time
description: ISO formatted date of the message.
fromUser:
type: object
description: User that sent the message.
properties:
id:
type: string
description: Gitter User ID.
username:
type: string
description: Gitter/GitHub username.
displayName:
type: string
description: Gitter/GitHub user real name.
url:
type: string
description: Path to the user on Gitter.
avatarUrl:
type: string
format: uri
description: User avatar URI.
avatarUrlSmall:
type: string
format: uri
description: User avatar URI (small).
avatarUrlMedium:
type: string
format: uri
description: User avatar URI (medium).
v:
type: number
description: Version.
gv:
type: string
description: Stands for "Gravatar version" and is used for cache busting.
unread:
type: boolean
description: Boolean that indicates if the current user has read the message.
readBy:
type: number
description: Number of users that have read the message.
urls:
type: array
description: List of URLs present in the message.
items:
type: string
format: uri
mentions:
type: array
description: List of @Mentions in the message.
items:
type: object
properties:
screenName:
type: string
userId:
type: string
userIds:
type: array
items:
type: string
issues:
type: array
description: 'List of #Issues referenced in the message.'
items:
type: object
properties:
number:
type: string
meta:
type: array
description: Metadata. This is currently not used for anything.
items: {}
v:
type: number
description: Version.
gv:
type: string
description: Stands for "Gravatar version" and is used for cache busting.
heartbeat:
summary: Its purpose is to keep the connection alive.
payload:
type: string
enum: ["\r\n"]
While the info, services, and components collections are pretty standard for an AsyncAPI definition, notice the stream collection. Providing details about the framing type and delimiter, which then connect to the heartbeat and message schema. Providing a machine-readable definition of the messaging stream, with parameters for determining the message room, and resource being part of the server variables you can pass through when initiating the stream.
This AsyncAPI definition was created by the AsyncAPI team and can be found on their Github alongside other sample AsyncAPI definitions. We are about to publish AsyncAPI definitions for 50 APIs that we’ve proxied using Streamdata.io, providing a more comprehensive look at how you can define SSE APIs using AsyncAPI. While the Websocket APIs are taking us a bit longer to craft, the web APIs we are proxying using Streamdata.io are proving to be pretty formulaic when it comes to publishing a machine-readable AsyncAPI–something we’ll continue to showcase here on the blog in future posts.