Nakama Realtime Socket API

Persistent WebSocket connection carrying realtime features - status presence, realtime chat channels, relayed and authoritative multiplayer matches, matchmaking, parties, and realtime notification delivery - as envelope messages authenticated with a session token supplied as a query parameter on connect.

AsyncAPI Specification

nakama-asyncapi.yml Raw ↑
asyncapi: '2.6.0'
id: 'urn:com:heroiclabs:nakama:realtime:socket'
info:
  title: Nakama Realtime Socket API (WebSocket)
  version: '1.0.0'
  description: |
    AsyncAPI 2.6 description of Nakama's **realtime socket API**.

    Unlike the request/response REST surface (modeled in
    `openapi/nakama-openapi.yml`), Nakama exposes a genuine bidirectional
    **WebSocket** transport for realtime features: status presence, realtime
    chat channels, relayed and authoritative multiplayer matches, matchmaking,
    parties, and realtime notification delivery.

    The client opens the socket at `GET /ws` (upgraded to WebSocket), passing
    the JWT session token from an authenticate call as the `token` query
    parameter, an optional `format` query parameter (`json` or `protobuf`), and
    an optional `lang` parameter. Once connected, both sides exchange
    **envelope** messages. A client envelope that includes a `cid` (correlation
    id) receives a matching server envelope carrying the same `cid`; server-
    initiated messages (such as `match_data`, `channel_message`,
    `notifications`, `status_presence_event`, and `matchmaker_matched`) arrive
    without a `cid`.

    This document models a representative subset of the envelope message types.
    The authoritative set is defined by `realtime/realtime.proto` (the
    `Envelope` message) in the heroiclabs/nakama repository.
  contact:
    name: API Evangelist
    email: kin@apievangelist.com
    url: https://apievangelist.com
  license:
    name: Apache 2.0
    url: https://github.com/heroiclabs/nakama/blob/master/LICENSE
  x-transport-notes:
    transport: WebSocket
    protocol: ws / wss
    direction: bidirectional
    path: /ws
    upgrade: 'GET /ws with Connection: Upgrade, Upgrade: websocket'
    auth: 'JWT session token passed as the ?token= query parameter on connect'
    format: 'json (default) or protobuf, selected with the ?format= query parameter'
    correlation: 'client requests set cid; the matching server reply echoes the same cid'
    source: https://heroiclabs.com/docs/nakama/concepts/client-relayed-multiplayer/
defaultContentType: application/json
servers:
  nakama:
    url: 127.0.0.1:7350
    protocol: ws
    description: |
      Default self-hosted Nakama socket endpoint. Connect to `/ws` and upgrade
      to WebSocket. Use `wss` against a TLS-terminated Heroic Cloud project URL
      in production.
    security:
      - sessionToken: []
    variables: {}
    bindings:
      ws:
        bindingVersion: '0.1.0'
channels:
  /ws:
    description: |
      The single Nakama realtime WebSocket channel. All realtime traffic flows
      as `Envelope` messages in both directions over this one connection. The
      `publish` operation below covers envelopes the client sends to the server;
      the `subscribe` operation covers envelopes the server sends to the client.
    bindings:
      ws:
        bindingVersion: '0.1.0'
        method: GET
        query:
          type: object
          properties:
            token:
              type: string
              description: The JWT session token from an authenticate call.
            format:
              type: string
              enum:
                - json
                - protobuf
              default: json
            lang:
              type: string
              default: en
    publish:
      operationId: sendEnvelope
      summary: Client-to-server realtime messages.
      description: |
        Envelopes sent by the client. Set a unique `cid` to correlate the
        server's reply. Examples include joining a chat channel, creating or
        joining a match, sending match data, updating status, and adding to
        the matchmaker.
      message:
        oneOf:
          - $ref: '#/components/messages/ChannelJoin'
          - $ref: '#/components/messages/ChannelMessageSend'
          - $ref: '#/components/messages/MatchCreate'
          - $ref: '#/components/messages/MatchJoin'
          - $ref: '#/components/messages/MatchDataSend'
          - $ref: '#/components/messages/MatchmakerAdd'
          - $ref: '#/components/messages/StatusUpdate'
    subscribe:
      operationId: receiveEnvelope
      summary: Server-to-client realtime messages.
      description: |
        Envelopes emitted by the server. Replies to client requests carry the
        originating `cid`; server-initiated events (match data, chat messages,
        matchmaker results, presence events, notifications) arrive without a
        `cid`.
      message:
        oneOf:
          - $ref: '#/components/messages/Channel'
          - $ref: '#/components/messages/ChannelMessage'
          - $ref: '#/components/messages/Match'
          - $ref: '#/components/messages/MatchData'
          - $ref: '#/components/messages/MatchmakerMatched'
          - $ref: '#/components/messages/StatusPresenceEvent'
          - $ref: '#/components/messages/Notifications'
          - $ref: '#/components/messages/Error'
components:
  securitySchemes:
    sessionToken:
      type: httpApiKey
      in: query
      name: token
      description: |
        The JWT session token returned by a Nakama authenticate call, supplied
        as the `token` query parameter when the WebSocket connection is opened.
  messages:
    ChannelJoin:
      name: ChannelJoin
      title: Join a realtime chat channel
      summary: Client request to join a chat channel (room, direct message, or group).
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeChannelJoin'
      examples:
        - name: joinRoom
          payload:
            cid: '1'
            channel_join:
              target: global-room
              type: 1
              persistence: true
              hidden: false
    ChannelMessageSend:
      name: ChannelMessageSend
      title: Send a chat message
      summary: Client request to send a message to a joined channel.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeChannelMessageSend'
      examples:
        - name: sendHello
          payload:
            cid: '2'
            channel_message_send:
              channel_id: 'channel-id-123'
              content: '{"text":"Hello world"}'
    MatchCreate:
      name: MatchCreate
      title: Create a relayed match
      summary: Client request to create a new client-relayed multiplayer match.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchCreate'
      examples:
        - name: create
          payload:
            cid: '3'
            match_create: {}
    MatchJoin:
      name: MatchJoin
      title: Join a match
      summary: Client request to join a match by id or by matchmaker token.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchJoin'
      examples:
        - name: joinById
          payload:
            cid: '4'
            match_join:
              match_id: 'match-id-abc'
    MatchDataSend:
      name: MatchDataSend
      title: Send match data
      summary: Client sends an opcode-tagged data frame to all or some match participants.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchDataSend'
      examples:
        - name: move
          payload:
            match_data_send:
              match_id: 'match-id-abc'
              op_code: '1'
              data: 'eyJ4IjoxMCwieSI6MjB9'
    MatchmakerAdd:
      name: MatchmakerAdd
      title: Add to the matchmaker
      summary: Client request to enter the matchmaking pool with a query and constraints.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchmakerAdd'
      examples:
        - name: findGame
          payload:
            cid: '5'
            matchmaker_add:
              query: '*'
              min_count: 2
              max_count: 4
    StatusUpdate:
      name: StatusUpdate
      title: Update status
      summary: Client updates its presence status string.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeStatusUpdate'
      examples:
        - name: online
          payload:
            status_update:
              status: '{"status":"online"}'
    Channel:
      name: Channel
      title: Channel joined
      summary: Server reply describing a joined chat channel.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeChannel'
    ChannelMessage:
      name: ChannelMessage
      title: Incoming chat message
      summary: Server-initiated delivery of a message on a joined channel.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeChannelMessage'
    Match:
      name: Match
      title: Match state
      summary: Server reply describing a created or joined match, including presences.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatch'
    MatchData:
      name: MatchData
      title: Incoming match data
      summary: Server-initiated delivery of an opcode-tagged data frame from a match participant.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchData'
    MatchmakerMatched:
      name: MatchmakerMatched
      title: Matchmaker matched
      summary: Server-initiated notification that a suitable set of opponents was found.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeMatchmakerMatched'
    StatusPresenceEvent:
      name: StatusPresenceEvent
      title: Status presence event
      summary: Server-initiated event describing users who came online or went offline.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeStatusPresenceEvent'
    Notifications:
      name: Notifications
      title: Realtime notifications
      summary: Server-initiated delivery of one or more in-app notifications.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeNotifications'
    Error:
      name: Error
      title: Error
      summary: Server error envelope, echoing the cid of the failed request when applicable.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/EnvelopeError'
      examples:
        - name: badRequest
          payload:
            cid: '4'
            error:
              code: 3
              message: 'Match not found'
  schemas:
    Presence:
      type: object
      description: A realtime presence for a user in a match, channel, or status feed.
      properties:
        user_id:
          type: string
        session_id:
          type: string
        username:
          type: string
        persistence:
          type: boolean
        status:
          type: string
    EnvelopeChannelJoin:
      type: object
      properties:
        cid:
          type: string
        channel_join:
          type: object
          required:
            - target
            - type
          properties:
            target:
              type: string
              description: The name of a room, or the id of a user or a group.
            type:
              type: integer
              format: int32
              description: '1 room, 2 direct message, 3 group.'
            persistence:
              type: boolean
              description: Whether messages sent on this channel should be stored.
            hidden:
              type: boolean
              description: Whether the user should be hidden from the channel's presence list.
    EnvelopeChannelMessageSend:
      type: object
      properties:
        cid:
          type: string
        channel_message_send:
          type: object
          required:
            - channel_id
            - content
          properties:
            channel_id:
              type: string
            content:
              type: string
              description: A JSON-encoded message payload.
    EnvelopeMatchCreate:
      type: object
      properties:
        cid:
          type: string
        match_create:
          type: object
          properties:
            name:
              type: string
              description: Optional name to create or join a named relayed match.
    EnvelopeMatchJoin:
      type: object
      properties:
        cid:
          type: string
        match_join:
          type: object
          properties:
            match_id:
              type: string
            token:
              type: string
              description: A matchmaker token to join an authoritative match.
            metadata:
              type: object
              additionalProperties:
                type: string
    EnvelopeMatchDataSend:
      type: object
      properties:
        match_data_send:
          type: object
          required:
            - match_id
            - op_code
            - data
          properties:
            match_id:
              type: string
            op_code:
              type: string
              format: int64
              description: Application-defined operation code.
            data:
              type: string
              format: byte
              description: Base64-encoded data payload.
            presences:
              type: array
              description: Subset of match presences to send to. Empty sends to all.
              items:
                $ref: '#/components/schemas/Presence'
    EnvelopeMatchmakerAdd:
      type: object
      properties:
        cid:
          type: string
        matchmaker_add:
          type: object
          properties:
            query:
              type: string
            min_count:
              type: integer
              format: int32
            max_count:
              type: integer
              format: int32
            string_properties:
              type: object
              additionalProperties:
                type: string
            numeric_properties:
              type: object
              additionalProperties:
                type: number
    EnvelopeStatusUpdate:
      type: object
      properties:
        cid:
          type: string
        status_update:
          type: object
          properties:
            status:
              type: string
              description: Status string to set. Absent clears status.
    EnvelopeChannel:
      type: object
      properties:
        cid:
          type: string
        channel:
          type: object
          properties:
            id:
              type: string
            presences:
              type: array
              items:
                $ref: '#/components/schemas/Presence'
            self:
              $ref: '#/components/schemas/Presence'
            room_name:
              type: string
    EnvelopeChannelMessage:
      type: object
      properties:
        channel_message:
          type: object
          properties:
            channel_id:
              type: string
            message_id:
              type: string
            sender_id:
              type: string
            username:
              type: string
            content:
              type: string
            create_time:
              type: string
              format: date-time
    EnvelopeMatch:
      type: object
      properties:
        cid:
          type: string
        match:
          type: object
          properties:
            match_id:
              type: string
            authoritative:
              type: boolean
            label:
              type: string
            size:
              type: integer
              format: int32
            presences:
              type: array
              items:
                $ref: '#/components/schemas/Presence'
            self:
              $ref: '#/components/schemas/Presence'
    EnvelopeMatchData:
      type: object
      properties:
        match_data:
          type: object
          properties:
            match_id:
              type: string
            presence:
              $ref: '#/components/schemas/Presence'
            op_code:
              type: string
              format: int64
            data:
              type: string
              format: byte
    EnvelopeMatchmakerMatched:
      type: object
      properties:
        matchmaker_matched:
          type: object
          properties:
            ticket:
              type: string
            match_id:
              type: string
            token:
              type: string
              description: Token used to join the resulting authoritative match.
            users:
              type: array
              items:
                type: object
                properties:
                  presence:
                    $ref: '#/components/schemas/Presence'
    EnvelopeStatusPresenceEvent:
      type: object
      properties:
        status_presence_event:
          type: object
          properties:
            joins:
              type: array
              items:
                $ref: '#/components/schemas/Presence'
            leaves:
              type: array
              items:
                $ref: '#/components/schemas/Presence'
    EnvelopeNotifications:
      type: object
      properties:
        notifications:
          type: object
          properties:
            notifications:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  subject:
                    type: string
                  content:
                    type: string
                  code:
                    type: integer
                    format: int32
                  sender_id:
                    type: string
                  create_time:
                    type: string
                    format: date-time
                  persistent:
                    type: boolean
    EnvelopeError:
      type: object
      properties:
        cid:
          type: string
        error:
          type: object
          properties:
            code:
              type: integer
              format: int32
              description: The error code, mirroring gRPC status codes.
            message:
              type: string
            context:
              type: object
              additionalProperties:
                type: string