Ably · AsyncAPI Specification

Ably Realtime Protocol

Version 1.2.0

AsyncAPI 3.0 description of the Ably realtime messaging surface. Ably exposes pub/sub channels, presence, push notifications, and history over a native WebSocket-based protocol, with additional access via Server-Sent Events (SSE) and protocol adapters (MQTT, AMQP, STOMP, Pusher, PubNub). This document covers the native Ably realtime protocol (WebSocket) and the SSE streaming endpoint. ProtocolMessage actions, channel state lifecycle, presence actions, and message envelopes are modeled directly from the official Ably documentation at https://ably.com/docs.

View Spec View on GitHub RealtimeWebSocketsPub/SubMessagingStreamingPush NotificationsChatLiveSyncAsyncAPIWebhooksEvents

Channels

connection
Control-plane ProtocolMessages exchanged on the WebSocket connection itself (not scoped to a channel). Carries CONNECT, CONNECTED, HEARTBEAT, DISCONNECT, DISCONNECTED, CLOSE, CLOSED, ERROR, and AUTH actions.
channel
A named Ably channel. Channels are identified by an arbitrary string name and may live inside a namespace (e.g. `chat:room42`). Clients ATTACH to a channel before publishing or subscribing, and DETACH when finished. The channel address travels in the `channel` field of every ProtocolMessage for actions ATTACH, ATTACHED, DETACH, DETACHED, MESSAGE, PRESENCE, SYNC.
sseStream
Server-Sent Events stream for subscribing to one or more channels. Each event has `id`, `event`, `data` (JSON-encoded Ably Message) and `lastEventId` for resumption via the `lastEvent` query parameter.

Messages

Connected
CONNECTED
Server confirmation that the realtime connection is established.
Heartbeat
HEARTBEAT
Keep-alive ping. Ably sends heartbeats every 15s by default.
Disconnect
DISCONNECT
Disconnected
DISCONNECTED
Connection has dropped. SDK will attempt to reconnect.
Close
CLOSE
Client request to gracefully close the connection.
Closed
CLOSED
Error
ERROR
Protocol-level or channel-scoped error.
Auth
AUTH
Mid-connection auth refresh (token reauth).
Attach
ATTACH
Client request to attach to a channel.
Attached
ATTACHED
Server confirmation that the channel is attached.
Detach
DETACH
Detached
DETACHED
Message
MESSAGE
Carries one or more user-published Message objects on a channel.
PresenceMessage
PRESENCE
Carries one or more PresenceMessage objects. Action enum: 0 ABSENT, 1 PRESENT, 2 ENTER, 3 LEAVE, 4 UPDATE.
Sync
SYNC
Presence set synchronization frames.
SseMessage
SSE message event
A single SSE event whose `data` field is a JSON-encoded Ably Message.

Servers

wss
realtime
The primary Ably realtime endpoint. Clients establish a single persistent WebSocket connection to multiplex any number of channels. The connection query string carries authentication and connection options (see bindings).
https
sse
Ably exposes a Server-Sent Events endpoint for lightweight one-way subscription. event.data is a JSON-encoded Ably Message. Supports `channels`, `v`, `key`, `accessToken`, `lastEvent`, `enveloped`, `rewind`, and `delta` query parameters.

AsyncAPI Specification

Raw ↑
asyncapi: 3.0.0
info:
  title: Ably Realtime Protocol
  version: 1.2.0
  description: |
    AsyncAPI 3.0 description of the Ably realtime messaging surface. Ably exposes
    pub/sub channels, presence, push notifications, and history over a native
    WebSocket-based protocol, with additional access via Server-Sent Events (SSE)
    and protocol adapters (MQTT, AMQP, STOMP, Pusher, PubNub).

    This document covers the native Ably realtime protocol (WebSocket) and the
    SSE streaming endpoint. ProtocolMessage actions, channel state lifecycle,
    presence actions, and message envelopes are modeled directly from the
    official Ably documentation at https://ably.com/docs.
  contact:
    name: Ably
    url: https://ably.com/docs
    email: [email protected]
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  externalDocs:
    description: Ably documentation index
    url: https://ably.com/docs
  tags:
    - name: realtime
    - name: pubsub
    - name: websocket
    - name: sse
    - name: presence
    - name: push

defaultContentType: application/json

servers:
  realtime:
    host: realtime.ably.io
    pathname: /
    protocol: wss
    protocolVersion: '2'
    title: Ably Realtime WebSocket
    summary: Native Ably realtime protocol over secure WebSocket
    description: |
      The primary Ably realtime endpoint. Clients establish a single persistent
      WebSocket connection to multiplex any number of channels. The connection
      query string carries authentication and connection options (see bindings).
    security:
      - $ref: '#/components/securitySchemes/apiKey'
      - $ref: '#/components/securitySchemes/token'
    tags:
      - name: websocket
      - name: realtime
    bindings:
      ws:
        query:
          type: object
          properties:
            key:
              type: string
              description: API key for Basic auth (format `appID.keyID:secret`).
            accessToken:
              type: string
              description: Ably Token or JWT for token authentication.
            clientId:
              type: string
              description: Identifies the client to the Ably service.
            format:
              type: string
              enum: [json, msgpack]
              default: json
              description: Wire protocol encoding.
            heartbeats:
              type: string
              enum: ['true', 'false']
              description: Whether to use Ably protocol-level heartbeats.
            v:
              type: string
              description: Protocol version (e.g. '2').
            lib:
              type: string
              description: Client library identifier.
            echo:
              type: string
              enum: ['true', 'false']
              description: Whether messages from this connection are echoed back.
            recover:
              type: string
              description: Recovery key from a previous connection to resume.
        bindingVersion: 0.1.0
  sse:
    host: realtime.ably.io
    pathname: /sse
    protocol: https
    title: Ably SSE Streaming
    summary: Server-Sent Events stream for one-way subscribe
    description: |
      Ably exposes a Server-Sent Events endpoint for lightweight one-way
      subscription. event.data is a JSON-encoded Ably Message. Supports
      `channels`, `v`, `key`, `accessToken`, `lastEvent`, `enveloped`,
      `rewind`, and `delta` query parameters.
    security:
      - $ref: '#/components/securitySchemes/apiKey'
      - $ref: '#/components/securitySchemes/token'
    tags:
      - name: sse
      - name: streaming

channels:
  connection:
    address: '/'
    title: Connection lifecycle
    description: |
      Control-plane ProtocolMessages exchanged on the WebSocket connection
      itself (not scoped to a channel). Carries CONNECT, CONNECTED, HEARTBEAT,
      DISCONNECT, DISCONNECTED, CLOSE, CLOSED, ERROR, and AUTH actions.
    servers:
      - $ref: '#/servers/realtime'
    messages:
      connected:
        $ref: '#/components/messages/Connected'
      heartbeat:
        $ref: '#/components/messages/Heartbeat'
      disconnect:
        $ref: '#/components/messages/Disconnect'
      disconnected:
        $ref: '#/components/messages/Disconnected'
      close:
        $ref: '#/components/messages/Close'
      closed:
        $ref: '#/components/messages/Closed'
      error:
        $ref: '#/components/messages/Error'
      auth:
        $ref: '#/components/messages/Auth'

  channel:
    address: '{channelName}'
    title: Pub/Sub channel
    description: |
      A named Ably channel. Channels are identified by an arbitrary string name
      and may live inside a namespace (e.g. `chat:room42`). Clients ATTACH to
      a channel before publishing or subscribing, and DETACH when finished.
      The channel address travels in the `channel` field of every ProtocolMessage
      for actions ATTACH, ATTACHED, DETACH, DETACHED, MESSAGE, PRESENCE, SYNC.
    parameters:
      channelName:
        description: Channel name, optionally namespaced (e.g. `chat:room42`).
    servers:
      - $ref: '#/servers/realtime'
    messages:
      attach:
        $ref: '#/components/messages/Attach'
      attached:
        $ref: '#/components/messages/Attached'
      detach:
        $ref: '#/components/messages/Detach'
      detached:
        $ref: '#/components/messages/Detached'
      message:
        $ref: '#/components/messages/Message'
      presence:
        $ref: '#/components/messages/PresenceMessage'
      sync:
        $ref: '#/components/messages/Sync'
      channelError:
        $ref: '#/components/messages/Error'

  sseStream:
    address: '/sse'
    title: SSE event stream
    description: |
      Server-Sent Events stream for subscribing to one or more channels.
      Each event has `id`, `event`, `data` (JSON-encoded Ably Message) and
      `lastEventId` for resumption via the `lastEvent` query parameter.
    servers:
      - $ref: '#/servers/sse'
    messages:
      sseMessage:
        $ref: '#/components/messages/SseMessage'

operations:
  connectClient:
    action: send
    channel:
      $ref: '#/channels/connection'
    title: Open realtime connection
    summary: Client opens the WebSocket and authenticates.
    description: |
      The client initiates the WebSocket handshake to `wss://realtime.ably.io/`
      with auth and options in the query string. Ably responds with a CONNECTED
      ProtocolMessage carrying the assigned `connectionId` and `connectionKey`.
    messages:
      - $ref: '#/channels/connection/messages/connected'

  receiveConnectionEvents:
    action: receive
    channel:
      $ref: '#/channels/connection'
    title: Receive connection control messages
    summary: Server-pushed CONNECTED / HEARTBEAT / DISCONNECTED / CLOSED / ERROR / AUTH frames.
    messages:
      - $ref: '#/channels/connection/messages/connected'
      - $ref: '#/channels/connection/messages/heartbeat'
      - $ref: '#/channels/connection/messages/disconnected'
      - $ref: '#/channels/connection/messages/closed'
      - $ref: '#/channels/connection/messages/error'
      - $ref: '#/channels/connection/messages/auth'

  closeConnection:
    action: send
    channel:
      $ref: '#/channels/connection'
    title: Close realtime connection
    summary: Client sends CLOSE to gracefully terminate the connection.
    messages:
      - $ref: '#/channels/connection/messages/close'

  attachChannel:
    action: send
    channel:
      $ref: '#/channels/channel'
    title: Attach to a channel
    summary: Send ATTACH ProtocolMessage to begin pub/sub on a channel.
    description: |
      Transitions the channel from `initialized` (or `detached`/`suspended`) to
      `attaching`. On success the server replies with ATTACHED.
    messages:
      - $ref: '#/channels/channel/messages/attach'

  detachChannel:
    action: send
    channel:
      $ref: '#/channels/channel'
    title: Detach from a channel
    summary: Send DETACH ProtocolMessage to leave a channel.
    messages:
      - $ref: '#/channels/channel/messages/detach'

  publishMessage:
    action: send
    channel:
      $ref: '#/channels/channel'
    title: Publish a message
    summary: Publish a MESSAGE ProtocolMessage to a channel.
    description: |
      Carries one or more Message objects in the `messages` array. Each Message
      has `name`, `data`, optional `clientId`, and optional `extras` (push,
      headers, ephemeral, privileged).
    messages:
      - $ref: '#/channels/channel/messages/message'

  subscribeChannel:
    action: receive
    channel:
      $ref: '#/channels/channel'
    title: Subscribe to channel events
    summary: Receive MESSAGE / PRESENCE / ATTACHED / DETACHED / SYNC / ERROR frames for a channel.
    messages:
      - $ref: '#/channels/channel/messages/attached'
      - $ref: '#/channels/channel/messages/detached'
      - $ref: '#/channels/channel/messages/message'
      - $ref: '#/channels/channel/messages/presence'
      - $ref: '#/channels/channel/messages/sync'
      - $ref: '#/channels/channel/messages/channelError'

  enterPresence:
    action: send
    channel:
      $ref: '#/channels/channel'
    title: Enter / update / leave presence
    summary: Send PRESENCE ProtocolMessage to enter, update, or leave a channel's presence set.
    messages:
      - $ref: '#/channels/channel/messages/presence'

  receiveSse:
    action: receive
    channel:
      $ref: '#/channels/sseStream'
    title: Receive SSE events
    summary: Stream of `message` events whose `data` is a JSON-encoded Ably Message.
    messages:
      - $ref: '#/channels/sseStream/messages/sseMessage'

components:
  securitySchemes:
    apiKey:
      type: userPassword
      description: |
        Basic authentication using an Ably API key in `appID.keyID:secret`
        form. Intended for trusted server environments only.
    token:
      type: httpApiKey
      in: query
      name: accessToken
      description: |
        Ably Token or JWT passed via the `accessToken` query parameter on the
        WebSocket or SSE request. Tokens are short-lived and carry capability
        and clientId claims.

  messages:
    Connected:
      name: connected
      title: CONNECTED
      summary: Server confirmation that the realtime connection is established.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'
      examples:
        - name: connected
          payload:
            action: 4
            connectionId: ABC123
            connectionDetails:
              clientId: alice
              connectionKey: 12345!abc
              maxMessageSize: 65536
              maxInboundRate: 1000
              maxOutboundRate: 1000
              connectionStateTtl: 120000
              maxIdleInterval: 15000

    Heartbeat:
      name: heartbeat
      title: HEARTBEAT
      summary: Keep-alive ping. Ably sends heartbeats every 15s by default.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Disconnect:
      name: disconnect
      title: DISCONNECT
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Disconnected:
      name: disconnected
      title: DISCONNECTED
      summary: Connection has dropped. SDK will attempt to reconnect.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Close:
      name: close
      title: CLOSE
      summary: Client request to gracefully close the connection.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Closed:
      name: closed
      title: CLOSED
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Error:
      name: error
      title: ERROR
      summary: Protocol-level or channel-scoped error.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Auth:
      name: auth
      title: AUTH
      summary: Mid-connection auth refresh (token reauth).
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Attach:
      name: attach
      title: ATTACH
      summary: Client request to attach to a channel.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Attached:
      name: attached
      title: ATTACHED
      summary: Server confirmation that the channel is attached.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Detach:
      name: detach
      title: DETACH
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Detached:
      name: detached
      title: DETACHED
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Message:
      name: message
      title: MESSAGE
      summary: Carries one or more user-published Message objects on a channel.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'
      examples:
        - name: publish
          payload:
            action: 15
            channel: chat:room42
            messages:
              - name: chat.message
                clientId: alice
                data: { text: 'hello world' }

    PresenceMessage:
      name: presence
      title: PRESENCE
      summary: |
        Carries one or more PresenceMessage objects. Action enum:
        0 ABSENT, 1 PRESENT, 2 ENTER, 3 LEAVE, 4 UPDATE.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    Sync:
      name: sync
      title: SYNC
      summary: Presence set synchronization frames.
      payload:
        $ref: '#/components/schemas/ProtocolMessage'

    SseMessage:
      name: sseMessage
      title: SSE message event
      contentType: text/event-stream
      summary: A single SSE event whose `data` field is a JSON-encoded Ably Message.
      payload:
        type: object
        properties:
          id:
            type: string
            description: SSE event id (also the Ably message id).
          event:
            type: string
            description: Event type, typically `message`.
          data:
            $ref: '#/components/schemas/Message'
          lastEventId:
            type: string

  schemas:
    ProtocolMessage:
      type: object
      description: |
        The native Ably wire envelope exchanged over the WebSocket. Every frame
        in the realtime protocol is a ProtocolMessage; the `action` field
        identifies the operation.
      properties:
        action:
          type: integer
          description: |
            Action enum (Ably protocol):
            0 HEARTBEAT, 1 ACK, 2 NACK,
            3 CONNECT, 4 CONNECTED,
            5 DISCONNECT, 6 DISCONNECTED,
            7 CLOSE, 8 CLOSED,
            9 ERROR,
            10 ATTACH, 11 ATTACHED, 12 DETACH, 13 DETACHED,
            14 PRESENCE, 15 MESSAGE,
            16 SYNC, 17 AUTH.
          enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
        id:
          type: string
        channel:
          type: string
          description: Channel name (required for channel-scoped actions).
        channelSerial:
          type: string
        connectionId:
          type: string
        connectionKey:
          type: string
        msgSerial:
          type: integer
          format: int64
        timestamp:
          type: integer
          format: int64
        count:
          type: integer
        flags:
          type: integer
          description: Bitfield of channel/message flags (PRESENCE, PUBLISH, SUBSCRIBE, PRESENCE_SUBSCRIBE, RESUMED, HAS_PRESENCE, HAS_BACKLOG, etc.).
        error:
          $ref: '#/components/schemas/ErrorInfo'
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        presence:
          type: array
          items:
            $ref: '#/components/schemas/PresenceItem'
        connectionDetails:
          $ref: '#/components/schemas/ConnectionDetails'
        auth:
          type: object
          properties:
            accessToken:
              type: string
      required:
        - action

    Message:
      type: object
      description: A user message published to a channel.
      properties:
        id:
          type: string
          description: Unique message ID assigned by Ably.
        clientId:
          type: string
          description: Publisher's client identifier.
        connectionId:
          type: string
          description: Publisher's connection identifier.
        timestamp:
          type: integer
          format: int64
          description: Milliseconds since epoch at which Ably first received the message.
        name:
          type: string
          description: Event name (optional).
        data:
          description: Message payload (string, buffer, or JSON-serializable).
        encoding:
          type: string
          description: Remaining unapplied encodings, e.g. `json`, `utf-8`, `base64`, `cipher+aes-256-cbc`.
        extras:
          type: object
          description: Optional metadata.
          properties:
            push:
              type: object
              description: Push notification payload (FCM/APNs/Web).
            headers:
              type: object
              additionalProperties:
                type: string
              description: Customer metadata map of string-keyed string values.
            ephemeral:
              type: object
              description: Marks the message as ephemeral (not persisted to history).
            privileged:
              type: object
              description: Reserved for Ably integrations.

    PresenceItem:
      type: object
      description: A single presence event item.
      properties:
        id:
          type: string
        action:
          type: integer
          description: 0 ABSENT, 1 PRESENT, 2 ENTER, 3 LEAVE, 4 UPDATE.
          enum: [0, 1, 2, 3, 4]
        clientId:
          type: string
        connectionId:
          type: string
        timestamp:
          type: integer
          format: int64
        data:
          description: Optional member data.
        encoding:
          type: string

    ConnectionDetails:
      type: object
      properties:
        clientId:
          type: string
        connectionKey:
          type: string
        connectionStateTtl:
          type: integer
          description: Milliseconds the server preserves connection state for resume.
        maxIdleInterval:
          type: integer
          description: Maximum interval between server activity before client must assume disconnect.
        maxMessageSize:
          type: integer
        maxFrameSize:
          type: integer
        maxInboundRate:
          type: integer
        maxOutboundRate:
          type: integer
        serverId:
          type: string

    ErrorInfo:
      type: object
      properties:
        code:
          type: integer
          description: Ably error code (see https://github.com/ably/ably-common/blob/main/protocol/errors.json).
        statusCode:
          type: integer
          description: HTTP status code equivalent.
        message:
          type: string
        href:
          type: string
        cause:
          $ref: '#/components/schemas/ErrorInfo'