Papercups · AsyncAPI Specification

Papercups Realtime Chat (WebSocket / Phoenix Channels)

Version 1.0.0

AsyncAPI 2.6 description of Papercups' **realtime live chat** surface. Unlike many providers, Papercups exposes a genuine, bidirectional **WebSocket** transport: the chat widget and agent dashboard connect to a Phoenix Channels socket and exchange messages in both directions. This is documented at https://docs.papercups.io/chat and described in the open-source codebase at https://github.com/papercups-io/papercups. Phoenix Channels multiplex many logical topics over a single WebSocket connection at `/socket/websocket`. A customer typically joins three channels while interacting with live chat: * `conversation:{conversation_id}` - all messages for a given conversation are broadcast here; clients send/receive the `shout` event (a new message) and `messages:seen` (read receipts). * `conversation:lobby:{customer_id}` - notifies the customer of new conversations initiated by agents. * `room:{account_id}` - broadcasts agent availability via Phoenix Presence. Phoenix wraps every frame in a 5-element message envelope `[join_ref, ref, topic, event, payload]`. The lifecycle events `phx_join`, `phx_reply`, `phx_close`, `phx_error`, and `heartbeat` (on the `phoenix` topic) are part of the Phoenix Channels protocol. Papercups is in maintenance mode (community-maintained); the realtime surface reflects the documented and open-source behavior at time of review.

View Spec View on GitHub Customer MessagingLive ChatOpen SourceSupportIntercom AlternativeAsyncAPIWebhooksEvents

Channels

conversation:{conversation_id}
publish sendShout
Send a message (and read receipts) into the conversation.
Per-conversation channel. After `phx_join`, clients send new messages with the `shout` event and read receipts with `messages:seen`, and receive the same events broadcast from other participants (agent or customer).
conversation:lobby:{customer_id}
subscribe receiveLobbyEvents
Receive new-conversation notifications.
Lobby channel through which a customer is notified of new conversations started by agents.
room:{account_id}
subscribe receivePresence
Receive Phoenix Presence state and diffs for agent availability.
Account room channel used to broadcast agent availability via Phoenix Presence.
phoenix
publish sendHeartbeat
Keep the WebSocket connection alive.
Phoenix heartbeat topic. Clients send a `heartbeat` event roughly every 30 seconds to keep the socket alive.

Messages

Shout
New message (shout)
A new chat message broadcast to a conversation channel.
MessagesSeen
Read receipt
Marks agent messages in the conversation as seen.
PhxJoin
Join channel
Phoenix channel join request.
PhxReply
Channel reply
Phoenix acknowledgement reply (status ok/error).
PresenceState
Presence state
Full Phoenix Presence state for agent availability.
PresenceDiff
Presence diff
Incremental Phoenix Presence join/leave diff.
Heartbeat
Heartbeat
Phoenix socket keepalive on the `phoenix` topic.

Servers

wss
papercups-hosted app.papercups.io/socket/websocket
Papercups hosted Phoenix Channels WebSocket endpoint. Self-hosted deployments expose the same `/socket/websocket` path on their own host. Connection params (e.g. customer or API token) are supplied as query params on the socket URL per Phoenix Channels conventions.

AsyncAPI Specification

Raw ↑
asyncapi: '2.6.0'
id: 'urn:io:papercups:realtime:chat:websocket'
info:
  title: Papercups Realtime Chat (WebSocket / Phoenix Channels)
  version: '1.0.0'
  description: |
    AsyncAPI 2.6 description of Papercups' **realtime live chat** surface.

    Unlike many providers, Papercups exposes a genuine, bidirectional
    **WebSocket** transport: the chat widget and agent dashboard connect to a
    Phoenix Channels socket and exchange messages in both directions. This is
    documented at https://docs.papercups.io/chat and described in the
    open-source codebase at https://github.com/papercups-io/papercups.

    Phoenix Channels multiplex many logical topics over a single WebSocket
    connection at `/socket/websocket`. A customer typically joins three
    channels while interacting with live chat:

      * `conversation:{conversation_id}` - all messages for a given conversation
        are broadcast here; clients send/receive the `shout` event (a new
        message) and `messages:seen` (read receipts).
      * `conversation:lobby:{customer_id}` - notifies the customer of new
        conversations initiated by agents.
      * `room:{account_id}` - broadcasts agent availability via Phoenix
        Presence.

    Phoenix wraps every frame in a 5-element message envelope
    `[join_ref, ref, topic, event, payload]`. The lifecycle events
    `phx_join`, `phx_reply`, `phx_close`, `phx_error`, and `heartbeat`
    (on the `phoenix` topic) are part of the Phoenix Channels protocol.

    Papercups is in maintenance mode (community-maintained); the realtime
    surface reflects the documented and open-source behavior at time of review.
  contact:
    name: API Evangelist
    email: kin@apievangelist.com
    url: https://apievangelist.com
  license:
    name: MIT
    url: https://github.com/papercups-io/papercups/blob/master/LICENSE
  x-transport-notes:
    transport: WebSocket (Phoenix Channels)
    protocol: wss
    direction: bidirectional
    socketPath: /socket/websocket
    envelope: '[join_ref, ref, topic, event, payload]'
    heartbeat: 'event "heartbeat" on topic "phoenix" every ~30s'
    source: https://docs.papercups.io/chat
defaultContentType: application/json
servers:
  papercups-hosted:
    url: app.papercups.io/socket/websocket
    protocol: wss
    description: |
      Papercups hosted Phoenix Channels WebSocket endpoint. Self-hosted
      deployments expose the same `/socket/websocket` path on their own host.
      Connection params (e.g. customer or API token) are supplied as query
      params on the socket URL per Phoenix Channels conventions.
channels:
  'conversation:{conversation_id}':
    description: |
      Per-conversation channel. After `phx_join`, clients send new messages
      with the `shout` event and read receipts with `messages:seen`, and
      receive the same events broadcast from other participants (agent or
      customer).
    parameters:
      conversation_id:
        description: The conversation UUID.
        schema:
          type: string
    bindings:
      ws:
        bindingVersion: '0.1.0'
    publish:
      operationId: sendShout
      summary: Send a message (and read receipts) into the conversation.
      message:
        oneOf:
          - $ref: '#/components/messages/Shout'
          - $ref: '#/components/messages/MessagesSeen'
          - $ref: '#/components/messages/PhxJoin'
    subscribe:
      operationId: receiveConversationEvents
      summary: Receive broadcast messages and acknowledgements.
      message:
        oneOf:
          - $ref: '#/components/messages/Shout'
          - $ref: '#/components/messages/MessagesSeen'
          - $ref: '#/components/messages/PhxReply'
  'conversation:lobby:{customer_id}':
    description: |
      Lobby channel through which a customer is notified of new conversations
      started by agents.
    parameters:
      customer_id:
        description: The customer UUID.
        schema:
          type: string
    bindings:
      ws:
        bindingVersion: '0.1.0'
    subscribe:
      operationId: receiveLobbyEvents
      summary: Receive new-conversation notifications.
      message:
        $ref: '#/components/messages/Shout'
  'room:{account_id}':
    description: |
      Account room channel used to broadcast agent availability via Phoenix
      Presence.
    parameters:
      account_id:
        description: The account UUID.
        schema:
          type: string
    bindings:
      ws:
        bindingVersion: '0.1.0'
    subscribe:
      operationId: receivePresence
      summary: Receive Phoenix Presence state and diffs for agent availability.
      message:
        oneOf:
          - $ref: '#/components/messages/PresenceState'
          - $ref: '#/components/messages/PresenceDiff'
  phoenix:
    description: |
      Phoenix heartbeat topic. Clients send a `heartbeat` event roughly every
      30 seconds to keep the socket alive.
    bindings:
      ws:
        bindingVersion: '0.1.0'
    publish:
      operationId: sendHeartbeat
      summary: Keep the WebSocket connection alive.
      message:
        $ref: '#/components/messages/Heartbeat'
components:
  messages:
    Shout:
      name: shout
      title: New message (shout)
      summary: A new chat message broadcast to a conversation channel.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
      examples:
        - name: customerMessage
          payload:
            - null
            - '3'
            - 'conversation:1a2b3c'
            - shout
            - body: 'Hi, I need help with my order'
              customer_id: 'cus_123'
              conversation_id: '1a2b3c'
    MessagesSeen:
      name: messages:seen
      title: Read receipt
      summary: Marks agent messages in the conversation as seen.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
    PhxJoin:
      name: phx_join
      title: Join channel
      summary: Phoenix channel join request.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
    PhxReply:
      name: phx_reply
      title: Channel reply
      summary: Phoenix acknowledgement reply (status ok/error).
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
    PresenceState:
      name: presence_state
      title: Presence state
      summary: Full Phoenix Presence state for agent availability.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
    PresenceDiff:
      name: presence_diff
      title: Presence diff
      summary: Incremental Phoenix Presence join/leave diff.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
    Heartbeat:
      name: heartbeat
      title: Heartbeat
      summary: Phoenix socket keepalive on the `phoenix` topic.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PhoenixEnvelope'
  schemas:
    PhoenixEnvelope:
      type: array
      description: >-
        Phoenix Channels v2 serializer envelope:
        [join_ref, ref, topic, event, payload].
      minItems: 5
      maxItems: 5
      items:
        - description: join_ref
          type: string
          nullable: true
        - description: ref
          type: string
          nullable: true
        - description: topic
          type: string
        - description: event
          type: string
        - description: payload
          type: object
          additionalProperties: true