Hasura · AsyncAPI Specification

Hasura GraphQL Subscriptions over WebSocket

Version 2.0.0

AsyncAPI definition for Hasura GraphQL Engine real-time subscriptions delivered over WebSocket at the `/v1/graphql` endpoint. Hasura supports two WebSocket subprotocols, negotiated via the `Sec-WebSocket-Protocol` HTTP header during the WebSocket handshake: * `graphql-transport-ws` — the modern protocol implemented by the [graphql-ws](https://github.com/enisdenjo/graphql-ws) library. * `graphql-ws` — the legacy protocol implemented by the [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws) library (kept for backwards compatibility with Apollo clients). Both protocols share a JSON envelope, but message `type` values, the subscription start/stop semantics, and the keep-alive mechanism differ. Authentication is performed either via the `connection_init` `payload` (where Hasura accepts headers such as `Authorization`, `x-hasura-admin-secret`, and any `x-hasura-*` session variables), or via query-string parameters on the WebSocket URL.

View Spec View on GitHub Data AccessGraphQLAsyncAPIWebhooksEvents

Channels

/v1/graphql
publish clientMessages
Messages published by the client to Hasura.
Single WebSocket channel used for all Hasura GraphQL subscription, query, and mutation traffic. The channel multiplexes any number of concurrent operations identified by a client-generated `id`.

Messages

ConnectionInit
connection_init
Client → Server. First message sent after the WebSocket is open. Optionally carries a payload with auth headers and connection parameters that Hasura forwards to its auth layer.
ConnectionAck
connection_ack
Server → Client. Sent after Hasura accepts the connection and the auth handshake completes.
PingClient
ping (client)
Client → Server. Optional keep-alive / latency probe. The peer MUST respond with a `pong`. May also be sent unsolicited as a heartbeat.
PingServer
ping (server)
Server → Client. Optional keep-alive / latency probe. The peer MUST respond with a `pong`. May also be sent unsolicited as a heartbeat.
PongClient
pong (client)
Client → Server. Response to a `ping`. May also be sent unsolicited as a unidirectional heartbeat.
PongServer
pong (server)
Server → Client. Response to a `ping`. May also be sent unsolicited as a unidirectional heartbeat.
Subscribe
subscribe
Client → Server. Requests execution of a GraphQL operation (query, mutation, or subscription). The `id` MUST be unique across the WebSocket session; Hasura streams results back tagged with the same `id`.
Next
next
Server → Client. Carries a single GraphQL execution result for the operation identified by `id`.
Error
error
Server → Client. Communicates one or more GraphQL errors that occurred before execution started (validation or operation errors). Terminates the operation; no further messages with this `id` will be sent.
CompleteClient
complete (client)
Client → Server. Signals that the client wishes to stop the operation identified by `id`. Used to unsubscribe.
CompleteServer
complete (server)
Server → Client. Indicates the operation identified by `id` has completed and no further results will be sent.
LegacyConnectionInit
connection_init (legacy)
Client → Server. First legacy-protocol message. The payload carries `connectionParams` (auth headers / session variables).
LegacyConnectionAck
connection_ack (legacy)
Server → Client. Acknowledges a successful connection.
LegacyConnectionError
connection_error (legacy)
Server → Client. Sent when Hasura rejects the connection (auth failure, parsing error, etc.). The connection will be closed.
LegacyKeepAlive
ka (legacy)
Server → Client. Periodic keep-alive frame sent after `connection_ack` to keep the WebSocket from idling out.
LegacyConnectionTerminate
connection_terminate (legacy)
Client → Server. Asks Hasura to close the connection.
LegacyStart
start (legacy)
Client → Server. Starts a GraphQL operation identified by a unique `id`.
LegacyData
data (legacy)
Server → Client. Carries a GraphQL execution result for the operation identified by `id`.
LegacyError
error (legacy)
Server → Client. Indicates the operation identified by `id` failed before execution.
LegacyComplete
complete (legacy)
Server → Client. Indicates the operation identified by `id` has completed.
LegacyStop
stop (legacy)
Client → Server. Stops the running operation identified by `id` (unsubscribe).

Servers

wss
cloud wss://{project}.hasura.app/v1/graphql
Hasura Cloud project WebSocket endpoint for GraphQL subscriptions. Replace `{project}` with your Hasura Cloud project subdomain.
wss
self-hosted wss://{host}:{port}/v1/graphql
Self-hosted Hasura GraphQL Engine WebSocket endpoint.

AsyncAPI Specification

Raw ↑
asyncapi: 2.6.0
info:
  title: Hasura GraphQL Subscriptions over WebSocket
  version: 2.0.0
  description: >
    AsyncAPI definition for Hasura GraphQL Engine real-time subscriptions
    delivered over WebSocket at the `/v1/graphql` endpoint.


    Hasura supports two WebSocket subprotocols, negotiated via the
    `Sec-WebSocket-Protocol` HTTP header during the WebSocket handshake:


      * `graphql-transport-ws` — the modern protocol implemented by the
        [graphql-ws](https://github.com/enisdenjo/graphql-ws) library.
      * `graphql-ws` — the legacy protocol implemented by the
        [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws)
        library (kept for backwards compatibility with Apollo clients).


    Both protocols share a JSON envelope, but message `type` values, the
    subscription start/stop semantics, and the keep-alive mechanism differ.

    Authentication is performed either via the `connection_init` `payload`
    (where Hasura accepts headers such as `Authorization`,
    `x-hasura-admin-secret`, and any `x-hasura-*` session variables), or
    via query-string parameters on the WebSocket URL.
  contact:
    name: Hasura
    url: https://hasura.io/docs/
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  tags:
    - name: GraphQL
    - name: Subscriptions
    - name: WebSocket
    - name: Realtime

defaultContentType: application/json

servers:
  cloud:
    url: wss://{project}.hasura.app/v1/graphql
    protocol: wss
    description: >
      Hasura Cloud project WebSocket endpoint for GraphQL subscriptions.
      Replace `{project}` with your Hasura Cloud project subdomain.
    variables:
      project:
        description: Hasura Cloud project subdomain (e.g. `my-app`).
        default: my-project
    bindings:
      ws:
        bindingVersion: 0.1.0
        headers:
          type: object
          properties:
            Sec-WebSocket-Protocol:
              type: string
              description: >
                WebSocket subprotocol negotiated during the HTTP upgrade
                handshake. Clients MUST request one of the two protocols
                supported by Hasura.
              enum:
                - graphql-transport-ws
                - graphql-ws
            Authorization:
              type: string
              description: >
                Bearer token used by Hasura's auth webhook or JWT mode.
                May alternatively be passed inside the `connection_init`
                payload.
            x-hasura-admin-secret:
              type: string
              description: >
                Admin secret used to bypass the auth layer (admin-only
                operations). May alternatively be passed inside the
                `connection_init` payload.
  self-hosted:
    url: wss://{host}:{port}/v1/graphql
    protocol: wss
    description: Self-hosted Hasura GraphQL Engine WebSocket endpoint.
    variables:
      host:
        description: Hostname of the self-hosted Hasura instance.
        default: localhost
      port:
        description: Port of the self-hosted Hasura instance.
        default: '8080'

channels:
  /v1/graphql:
    description: >
      Single WebSocket channel used for all Hasura GraphQL subscription,
      query, and mutation traffic. The channel multiplexes any number of
      concurrent operations identified by a client-generated `id`.
    bindings:
      ws:
        bindingVersion: 0.1.0
        method: GET
        headers:
          type: object
          properties:
            Sec-WebSocket-Protocol:
              type: string
              enum:
                - graphql-transport-ws
                - graphql-ws
    publish:
      operationId: clientMessages
      summary: Messages published by the client to Hasura.
      message:
        oneOf:
          # graphql-transport-ws (modern)
          - $ref: '#/components/messages/ConnectionInit'
          - $ref: '#/components/messages/Subscribe'
          - $ref: '#/components/messages/PingClient'
          - $ref: '#/components/messages/PongClient'
          - $ref: '#/components/messages/CompleteClient'
          # graphql-ws (legacy / subscriptions-transport-ws)
          - $ref: '#/components/messages/LegacyConnectionInit'
          - $ref: '#/components/messages/LegacyStart'
          - $ref: '#/components/messages/LegacyStop'
          - $ref: '#/components/messages/LegacyConnectionTerminate'
    subscribe:
      operationId: serverMessages
      summary: Messages sent by Hasura to the client.
      message:
        oneOf:
          # graphql-transport-ws (modern)
          - $ref: '#/components/messages/ConnectionAck'
          - $ref: '#/components/messages/PingServer'
          - $ref: '#/components/messages/PongServer'
          - $ref: '#/components/messages/Next'
          - $ref: '#/components/messages/Error'
          - $ref: '#/components/messages/CompleteServer'
          # graphql-ws (legacy / subscriptions-transport-ws)
          - $ref: '#/components/messages/LegacyConnectionAck'
          - $ref: '#/components/messages/LegacyConnectionError'
          - $ref: '#/components/messages/LegacyKeepAlive'
          - $ref: '#/components/messages/LegacyData'
          - $ref: '#/components/messages/LegacyError'
          - $ref: '#/components/messages/LegacyComplete'

components:
  messages:

    # =========================================================
    # graphql-transport-ws (Sec-WebSocket-Protocol: graphql-transport-ws)
    # Source: https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
    # =========================================================

    ConnectionInit:
      name: ConnectionInit
      title: connection_init
      summary: >
        Client → Server. First message sent after the WebSocket is open.
        Optionally carries a payload with auth headers and connection
        parameters that Hasura forwards to its auth layer.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/ConnectionInitPayload'

    ConnectionAck:
      name: ConnectionAck
      title: connection_ack
      summary: >
        Server → Client. Sent after Hasura accepts the connection and
        the auth handshake completes.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/ConnectionAckPayload'

    PingClient:
      name: PingClient
      title: ping (client)
      summary: >
        Client → Server. Optional keep-alive / latency probe. The peer
        MUST respond with a `pong`. May also be sent unsolicited as a
        heartbeat.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PingPongPayload'

    PingServer:
      name: PingServer
      title: ping (server)
      summary: >
        Server → Client. Optional keep-alive / latency probe. The peer
        MUST respond with a `pong`. May also be sent unsolicited as a
        heartbeat.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PingPongPayload'

    PongClient:
      name: PongClient
      title: pong (client)
      summary: >
        Client → Server. Response to a `ping`. May also be sent
        unsolicited as a unidirectional heartbeat.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PingPongPayload'

    PongServer:
      name: PongServer
      title: pong (server)
      summary: >
        Server → Client. Response to a `ping`. May also be sent
        unsolicited as a unidirectional heartbeat.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PingPongPayload'

    Subscribe:
      name: Subscribe
      title: subscribe
      summary: >
        Client → Server. Requests execution of a GraphQL operation
        (query, mutation, or subscription). The `id` MUST be unique
        across the WebSocket session; Hasura streams results back
        tagged with the same `id`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/SubscribePayload'

    Next:
      name: Next
      title: next
      summary: >
        Server → Client. Carries a single GraphQL execution result for
        the operation identified by `id`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/NextPayload'

    Error:
      name: Error
      title: error
      summary: >
        Server → Client. Communicates one or more GraphQL errors that
        occurred before execution started (validation or operation
        errors). Terminates the operation; no further messages with
        this `id` will be sent.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/ErrorPayload'

    CompleteClient:
      name: CompleteClient
      title: complete (client)
      summary: >
        Client → Server. Signals that the client wishes to stop the
        operation identified by `id`. Used to unsubscribe.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/CompletePayload'

    CompleteServer:
      name: CompleteServer
      title: complete (server)
      summary: >
        Server → Client. Indicates the operation identified by `id`
        has completed and no further results will be sent.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/CompletePayload'

    # =========================================================
    # graphql-ws — legacy / subscriptions-transport-ws
    # Sec-WebSocket-Protocol: graphql-ws
    # Source: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md
    # =========================================================

    LegacyConnectionInit:
      name: LegacyConnectionInit
      title: connection_init (legacy)
      summary: >
        Client → Server. First legacy-protocol message. The payload
        carries `connectionParams` (auth headers / session variables).
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyConnectionInitPayload'

    LegacyConnectionAck:
      name: LegacyConnectionAck
      title: connection_ack (legacy)
      summary: Server → Client. Acknowledges a successful connection.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyConnectionAckPayload'

    LegacyConnectionError:
      name: LegacyConnectionError
      title: connection_error (legacy)
      summary: >
        Server → Client. Sent when Hasura rejects the connection (auth
        failure, parsing error, etc.). The connection will be closed.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyConnectionErrorPayload'

    LegacyKeepAlive:
      name: LegacyKeepAlive
      title: ka (legacy)
      summary: >
        Server → Client. Periodic keep-alive frame sent after
        `connection_ack` to keep the WebSocket from idling out.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyKeepAlivePayload'

    LegacyConnectionTerminate:
      name: LegacyConnectionTerminate
      title: connection_terminate (legacy)
      summary: Client → Server. Asks Hasura to close the connection.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyConnectionTerminatePayload'

    LegacyStart:
      name: LegacyStart
      title: start (legacy)
      summary: >
        Client → Server. Starts a GraphQL operation identified by a
        unique `id`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyStartPayload'

    LegacyData:
      name: LegacyData
      title: data (legacy)
      summary: >
        Server → Client. Carries a GraphQL execution result for the
        operation identified by `id`.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyDataPayload'

    LegacyError:
      name: LegacyError
      title: error (legacy)
      summary: >
        Server → Client. Indicates the operation identified by `id`
        failed before execution.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyErrorPayload'

    LegacyComplete:
      name: LegacyComplete
      title: complete (legacy)
      summary: >
        Server → Client. Indicates the operation identified by `id`
        has completed.
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyCompletePayload'

    LegacyStop:
      name: LegacyStop
      title: stop (legacy)
      summary: >
        Client → Server. Stops the running operation identified by
        `id` (unsubscribe).
      contentType: application/json
      payload:
        $ref: '#/components/schemas/LegacyStopPayload'

  schemas:

    # ---------- shared ----------
    GraphQLError:
      type: object
      description: >
        A GraphQL error object as defined by the GraphQL spec.
      properties:
        message:
          type: string
        locations:
          type: array
          items:
            type: object
            properties:
              line:
                type: integer
              column:
                type: integer
        path:
          type: array
          items:
            oneOf:
              - type: string
              - type: integer
        extensions:
          type: object
          additionalProperties: true
      required:
        - message

    ExecutionResult:
      type: object
      description: GraphQL execution result (`data` and/or `errors`).
      properties:
        data:
          type: object
          additionalProperties: true
          nullable: true
        errors:
          type: array
          items:
            $ref: '#/components/schemas/GraphQLError'
        extensions:
          type: object
          additionalProperties: true

    # ---------- graphql-transport-ws ----------

    ConnectionInitPayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: connection_init
        payload:
          type: object
          description: >
            Optional connection parameters. Hasura reads keys such as
            `headers` (an object of HTTP headers including `Authorization`
            and `x-hasura-admin-secret`) for the auth handshake.
          additionalProperties: true
          nullable: true

    ConnectionAckPayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: connection_ack
        payload:
          type: object
          additionalProperties: true
          nullable: true

    PingPongPayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - ping
            - pong
        payload:
          type: object
          additionalProperties: true
          nullable: true

    SubscribePayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
          description: Unique operation identifier within the session.
        type:
          type: string
          const: subscribe
        payload:
          type: object
          required:
            - query
          properties:
            operationName:
              type: string
              nullable: true
            query:
              type: string
              description: The GraphQL document.
            variables:
              type: object
              additionalProperties: true
              nullable: true
            extensions:
              type: object
              additionalProperties: true
              nullable: true

    NextPayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
        type:
          type: string
          const: next
        payload:
          $ref: '#/components/schemas/ExecutionResult'

    ErrorPayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
        type:
          type: string
          const: error
        payload:
          type: array
          items:
            $ref: '#/components/schemas/GraphQLError'

    CompletePayload:
      type: object
      required:
        - id
        - type
      properties:
        id:
          type: string
        type:
          type: string
          const: complete

    # ---------- graphql-ws (legacy) ----------

    LegacyConnectionInitPayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: connection_init
        payload:
          type: object
          description: >
            Optional `connectionParams`. Hasura reads `headers` and
            individual entries (e.g. `Authorization`,
            `x-hasura-admin-secret`, `x-hasura-*`).
          additionalProperties: true
          nullable: true

    LegacyConnectionAckPayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: connection_ack
        payload:
          type: object
          additionalProperties: true
          nullable: true

    LegacyConnectionErrorPayload:
      type: object
      required:
        - type
        - payload
      properties:
        type:
          type: string
          const: connection_error
        payload:
          type: object
          description: Error details describing why the connection was rejected.
          additionalProperties: true

    LegacyKeepAlivePayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: ka
          description: >
            Keep-alive frame. Sent by Hasura after `connection_ack` and
            then periodically. No payload.

    LegacyConnectionTerminatePayload:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          const: connection_terminate

    LegacyStartPayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
          description: Unique operation identifier within the session.
        type:
          type: string
          const: start
        payload:
          type: object
          required:
            - query
          properties:
            operationName:
              type: string
              nullable: true
            query:
              type: string
            variables:
              type: object
              additionalProperties: true
              nullable: true

    LegacyDataPayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
        type:
          type: string
          const: data
        payload:
          $ref: '#/components/schemas/ExecutionResult'

    LegacyErrorPayload:
      type: object
      required:
        - id
        - type
        - payload
      properties:
        id:
          type: string
        type:
          type: string
          const: error
        payload:
          description: >
            Pre-execution error (validation, parse). Hasura sends a
            GraphQL error object or array of error objects here.
          oneOf:
            - $ref: '#/components/schemas/GraphQLError'
            - type: array
              items:
                $ref: '#/components/schemas/GraphQLError'

    LegacyCompletePayload:
      type: object
      required:
        - id
        - type
      properties:
        id:
          type: string
        type:
          type: string
          const: complete

    LegacyStopPayload:
      type: object
      required:
        - id
        - type
      properties:
        id:
          type: string
        type:
          type: string
          const: stop