asyncapi: '2.6.0' id: 'urn:com:microsoft:azure:webpubsub' info: title: Azure Web PubSub version: '1.0.0' description: | Azure Web PubSub is a fully managed real-time messaging service from Microsoft Azure that lets clients exchange publish/subscribe messages over WebSockets without operating WebSocket infrastructure. Clients connect to the service over secure WebSocket (`wss://`) and may either use a simple WebSocket frame (text/binary) or upgrade to one of the JSON publish/subscribe subprotocols: - `json.webpubsub.azure.v1` — JSON pub/sub subprotocol that lets a *PubSub WebSocket client* join groups, publish to groups, and route custom events to upstream event handlers directly through the service. - `json.reliable.webpubsub.azure.v1` — Reliable variant of the JSON pub/sub subprotocol that adds `sequenceId` on every server-to-client `message` and requires the client to acknowledge with a `sequenceAck`. Also returns `reconnectionToken` on `connected` so clients can recover sessions across intermittent network failures using the `awps_connection_id` / `awps_reconnection_token` query parameters. The server side of an Azure Web PubSub solution receives client activity as **upstream events** delivered by the service to a configured webhook endpoint using the CloudEvents 1.0 HTTP binding (binary content mode). Event types are namespaced `azure.webpubsub.sys.*` for system events (`connect`, `connected`, `disconnected`) and `azure.webpubsub.user.*` for user events (`message` for simple clients and `` for PubSub subprotocol clients sending `type: event` frames). Web PubSub also advertises an Event Grid integration where events are published with `eventType` values like `Microsoft.SignalRService.ClientConnectionConnected` and `Microsoft.SignalRService.ClientConnectionDisconnected`; the CloudEvents `ce-type` values delivered by the Web PubSub event handler (Webhook upstream) however use the `azure.webpubsub.*` namespace as documented at https://learn.microsoft.com/en-us/azure/azure-web-pubsub/reference-cloud-events and modeled below. This AsyncAPI document models only the documented surface area of the JSON WebSocket subprotocols and the CloudEvents HTTP upstream contract. Fields not documented by Microsoft (for example, undocumented subprotocol message types, undocumented CloudEvents extensions, or REST data-plane operations — which are modeled separately in OpenAPI) are intentionally NOT included. contact: name: Azure Web PubSub Documentation url: https://learn.microsoft.com/en-us/azure/azure-web-pubsub/ license: name: Microsoft Terms of Use url: https://www.microsoft.com/en-us/legal/terms-of-use externalDocs: description: Azure Web PubSub overview url: https://learn.microsoft.com/en-us/azure/azure-web-pubsub/ defaultContentType: application/json servers: client: url: 'wss://{instance}.webpubsub.azure.com' protocol: wss description: | Azure Web PubSub client endpoint. Clients open a WebSocket connection to `wss://{instance}.webpubsub.azure.com/client/hubs/{hub}` and optionally specify one of the supported subprotocols via the `Sec-WebSocket-Protocol` header. Authentication is performed with a short-lived JWT access token passed as the `access_token` query parameter (generated by the service's REST data plane or a server SDK). variables: instance: default: example description: Web PubSub service instance name security: - clientAccessToken: [] upstream: url: 'https://{upstreamHost}' protocol: https description: | Customer-owned HTTP endpoint registered as an event handler on the hub. The Web PubSub service delivers client events to this endpoint using the CloudEvents 1.0 HTTP protocol binding (binary content mode). The endpoint must implement CloudEvents abuse-protection handshake by returning `WebHook-Allowed-Origin` in response to the `WebHook-Request-Origin` validation request. variables: upstreamHost: default: contoso.example.com description: Customer-controlled upstream webhook host channels: /client/hubs/{hub}: description: | WebSocket channel between a single client and a hub on the Web PubSub service instance. Each connection belongs to exactly one hub. Messages on this channel are JSON frames defined by the `json.webpubsub.azure.v1` or `json.reliable.webpubsub.azure.v1` subprotocol. Simple WebSocket clients (no subprotocol) exchange raw text/binary frames instead and are NOT modeled here — refer to the user event handler contract on the `upstream` server for how their frames surface to the application backend. servers: - client parameters: hub: description: Hub name. Hubs provide logical isolation within an instance. schema: type: string bindings: ws: bindingVersion: '0.1.0' query: type: object description: Query string parameters supported on the connect handshake. properties: access_token: type: string description: JWT access token authorizing the client connection. awps_connection_id: type: string description: | Reliable subprotocol only. Previously-issued connection id used to recover a dropped session. awps_reconnection_token: type: string description: | Reliable subprotocol only. Token returned on the original `connected` system message; required to recover a dropped session. headers: type: object properties: Sec-WebSocket-Protocol: type: string enum: - json.webpubsub.azure.v1 - json.reliable.webpubsub.azure.v1 description: | Optional subprotocol negotiation. If omitted the connection behaves as a *simple WebSocket client* and frames are passed through to the upstream event handler as `azure.webpubsub.user.message` events. If present, the client may exchange the JSON pub/sub frames defined in this document. publish: operationId: clientSend summary: Messages a client sends to the service over the JSON pub/sub subprotocol. message: oneOf: - $ref: '#/components/messages/JoinGroup' - $ref: '#/components/messages/LeaveGroup' - $ref: '#/components/messages/SendToGroup' - $ref: '#/components/messages/SendEvent' - $ref: '#/components/messages/Ping' - $ref: '#/components/messages/SequenceAck' subscribe: operationId: clientReceive summary: Messages the service sends back to the client. message: oneOf: - $ref: '#/components/messages/AckResponse' - $ref: '#/components/messages/MessageFromGroup' - $ref: '#/components/messages/MessageFromServer' - $ref: '#/components/messages/SystemConnected' - $ref: '#/components/messages/SystemDisconnected' - $ref: '#/components/messages/Pong' /upstream: description: | CloudEvents 1.0 HTTP delivery channel from the Web PubSub service to the customer-configured upstream webhook. The service POSTs one HTTP request per client event, using CloudEvents *binary* content mode (CloudEvents attributes are conveyed in `ce-*` HTTP headers; the event payload is the HTTP body). All requests carry `WebHook-Request-Origin: .webpubsub.azure.com` and a signed `ce-signature` header so the upstream can validate the origin of the request. servers: - upstream bindings: http: bindingVersion: '0.3.0' type: request method: POST subscribe: operationId: upstreamDeliver summary: | Events delivered by Azure Web PubSub to the upstream webhook. `connect` and user events are *blocking* events whose response the service waits for; `connected` and `disconnected` are *unblocking* (asynchronous) notifications. message: oneOf: - $ref: '#/components/messages/UpstreamSystemConnect' - $ref: '#/components/messages/UpstreamSystemConnected' - $ref: '#/components/messages/UpstreamSystemDisconnected' - $ref: '#/components/messages/UpstreamUserMessage' - $ref: '#/components/messages/UpstreamUserCustomEvent' components: securitySchemes: clientAccessToken: type: httpApiKey in: query name: access_token description: | Short-lived JWT access token passed as the `access_token` query parameter on the WebSocket handshake. Tokens are issued by the Web PubSub service data-plane REST API (`POST /api/hubs/{hub}/:generateToken`) or by a server SDK using the service AccessKey. messages: JoinGroup: name: joinGroup title: Join Group request summary: Client asks the service to add the connection to a group. contentType: application/json payload: $ref: '#/components/schemas/JoinGroupPayload' LeaveGroup: name: leaveGroup title: Leave Group request summary: Client asks the service to remove the connection from a group. contentType: application/json payload: $ref: '#/components/schemas/LeaveGroupPayload' SendToGroup: name: sendToGroup title: Send-To-Group request summary: Client publishes a message to all connections in a group. contentType: application/json payload: $ref: '#/components/schemas/SendToGroupPayload' SendEvent: name: event title: Send custom event request summary: | Client sends a custom user event that the service forwards to the upstream event handler as a CloudEvents request with `ce-type: azure.webpubsub.user.`. contentType: application/json payload: $ref: '#/components/schemas/SendEventPayload' Ping: name: ping title: Ping summary: Client liveness check. contentType: application/json payload: $ref: '#/components/schemas/PingPayload' SequenceAck: name: sequenceAck title: Sequence Ack (reliable subprotocol only) summary: | Acknowledgement of a `sequenceId` delivered on an inbound message. Required for the `json.reliable.webpubsub.azure.v1` subprotocol so the service can release in-flight messages. contentType: application/json payload: $ref: '#/components/schemas/SequenceAckPayload' AckResponse: name: ack title: Ack response summary: | Service response to a client request that carried `ackId`. Clients should inspect `success` before reading `error`. contentType: application/json payload: $ref: '#/components/schemas/AckResponsePayload' MessageFromGroup: name: messageFromGroup title: Group message summary: | Data message delivered to the client because a publisher (REST API, server SDK, or another subprotocol client) sent it to a group the client has joined. contentType: application/json payload: $ref: '#/components/schemas/MessageFromGroupPayload' MessageFromServer: name: messageFromServer title: Server message summary: | Data message delivered to the client because the server (REST API or server SDK) targeted this connection, the user, or all connections. contentType: application/json payload: $ref: '#/components/schemas/MessageFromServerPayload' SystemConnected: name: systemConnected title: System connected event summary: | Service notifies the client that the WebSocket handshake succeeded. Reliable subprotocol additionally carries `reconnectionToken` for use on session recovery. contentType: application/json payload: $ref: '#/components/schemas/SystemConnectedPayload' SystemDisconnected: name: systemDisconnected title: System disconnected event summary: | Service notifies the client that the connection was closed by the server or declined by the service. contentType: application/json payload: $ref: '#/components/schemas/SystemDisconnectedPayload' Pong: name: pong title: Pong summary: Service response to a `ping` request. contentType: application/json payload: $ref: '#/components/schemas/PongPayload' UpstreamSystemConnect: name: upstreamSystemConnect title: Upstream `connect` (blocking) summary: | Blocking CloudEvents request fired during WebSocket handshake. The upstream may approve the connection (HTTP 200 with optional `userId`/`groups`/`roles`/`subprotocol` body, or HTTP 204) or deny it (4xx). Used to perform authentication, authorization, subprotocol negotiation, and auto-join group assignment. contentType: application/json bindings: http: bindingVersion: '0.3.0' headers: $ref: '#/components/schemas/CloudEventsConnectHeaders' payload: $ref: '#/components/schemas/UpstreamConnectPayload' UpstreamSystemConnected: name: upstreamSystemConnected title: Upstream `connected` (unblocking) summary: | Asynchronous notification fired after a client has successfully completed the WebSocket handshake. Upstream is expected to return a 2xx; non-2xx responses are logged by the service but do not affect the connection. contentType: application/json bindings: http: bindingVersion: '0.3.0' headers: $ref: '#/components/schemas/CloudEventsConnectedHeaders' payload: $ref: '#/components/schemas/UpstreamEmptyJsonPayload' UpstreamSystemDisconnected: name: upstreamSystemDisconnected title: Upstream `disconnected` (unblocking) summary: | Asynchronous notification fired after a client disconnects, if the `connect` event previously returned a 2xx. The body carries the disconnect `reason`. contentType: application/json bindings: http: bindingVersion: '0.3.0' headers: $ref: '#/components/schemas/CloudEventsDisconnectedHeaders' payload: $ref: '#/components/schemas/UpstreamDisconnectedPayload' UpstreamUserMessage: name: upstreamUserMessage title: Upstream `message` for simple WebSocket clients (blocking) summary: | Blocking CloudEvents request fired for every WebSocket frame a *simple* (no subprotocol) client sends. The HTTP body is the raw payload the client sent. The upstream's response body, if any, is sent back to the client as a frame whose type follows the response `Content-Type` (`text/plain` => text frame, `application/octet-stream` => binary frame). contentType: application/octet-stream bindings: http: bindingVersion: '0.3.0' headers: $ref: '#/components/schemas/CloudEventsMessageHeaders' payload: $ref: '#/components/schemas/UpstreamUserMessagePayload' UpstreamUserCustomEvent: name: upstreamUserCustomEvent title: Upstream `` for PubSub clients (blocking) summary: | Blocking CloudEvents request fired when a PubSub subprotocol client sends a `type: event` frame. The CloudEvents `ce-type` is `azure.webpubsub.user.` and the body is the `data` field of the original frame (text, JSON, or binary, depending on `dataType`). contentType: application/json bindings: http: bindingVersion: '0.3.0' headers: $ref: '#/components/schemas/CloudEventsCustomEventHeaders' payload: $ref: '#/components/schemas/UpstreamUserCustomEventPayload' schemas: DataType: type: string enum: [json, text, binary] description: | Encoding for the `data` field. `json` accepts any JSON value; `text` requires a string; `binary` requires a base64-encoded string. JoinGroupPayload: type: object required: [type, group] properties: type: type: string const: joinGroup group: type: string description: Name of the group to join. ackId: type: integer format: int64 description: | Unique request identifier. If present, the service replies with an `ack` message carrying the same `ackId`. LeaveGroupPayload: type: object required: [type, group] properties: type: type: string const: leaveGroup group: type: string description: Name of the group to leave. ackId: type: integer format: int64 SendToGroupPayload: type: object required: [type, group, data] properties: type: type: string const: sendToGroup group: type: string description: Target group name. ackId: type: integer format: int64 noEcho: type: boolean default: false description: | If true, the publishing connection does not receive an echo of its own message. dataType: $ref: '#/components/schemas/DataType' data: description: | Payload to publish. Type depends on `dataType`: any JSON value for `json`, string for `text`, base64-encoded string for `binary`. SendEventPayload: type: object required: [type, event, data] properties: type: type: string const: event event: type: string description: | Custom event name. The service forwards this to the upstream webhook with `ce-type: azure.webpubsub.user.` and `ce-eventName: `. ackId: type: integer format: int64 dataType: $ref: '#/components/schemas/DataType' data: description: | Event payload. Type depends on `dataType`. PingPayload: type: object required: [type] properties: type: type: string const: ping SequenceAckPayload: type: object required: [type, sequenceId] properties: type: type: string const: sequenceAck sequenceId: type: integer format: int64 description: | Highest `sequenceId` the client has successfully processed from the service. Used by the reliable subprotocol so the service can release buffered messages. AckResponsePayload: type: object required: [type, ackId, success] properties: type: type: string const: ack ackId: type: integer format: int64 success: type: boolean error: type: object description: Present when `success` is false. required: [name, message] properties: name: type: string enum: [Forbidden, InternalServerError, Duplicate] message: type: string MessageFromGroupPayload: type: object required: [type, from, group, data] properties: sequenceId: type: integer format: int64 description: | Only present on the reliable subprotocol. Client must acknowledge using `sequenceAck`. type: type: string const: message from: type: string const: group group: type: string dataType: $ref: '#/components/schemas/DataType' data: description: Message payload (encoding follows `dataType`). fromUserId: type: string description: User id of the publisher, if any. MessageFromServerPayload: type: object required: [type, from, data] properties: sequenceId: type: integer format: int64 description: Only present on the reliable subprotocol. type: type: string const: message from: type: string const: server dataType: $ref: '#/components/schemas/DataType' data: description: Message payload (encoding follows `dataType`). SystemConnectedPayload: type: object required: [type, event, connectionId] properties: type: type: string const: system event: type: string const: connected userId: type: string description: Authenticated user id of the connection, if any. connectionId: type: string description: Service-assigned unique connection id. reconnectionToken: type: string description: | Only present on the reliable subprotocol. Pass back as `awps_reconnection_token` (together with `awps_connection_id`) on a new connect request to recover this session. SystemDisconnectedPayload: type: object required: [type, event] properties: type: type: string const: system event: type: string const: disconnected message: type: string description: Human-readable disconnect reason. PongPayload: type: object required: [type] properties: type: type: string const: pong CloudEventsCommonHeaders: type: object description: | Common CloudEvents 1.0 binary-mode HTTP headers attached to every upstream request from Web PubSub. Additional event-type specific headers are documented per message. required: - ce-specversion - ce-type - ce-source - ce-id - ce-time - ce-signature - ce-connectionId - ce-hub - ce-eventName - WebHook-Request-Origin properties: WebHook-Request-Origin: type: string description: '`.webpubsub.azure.com`' ce-specversion: type: string const: '1.0' ce-type: type: string description: | Event type. `azure.webpubsub.sys.` for system events; `azure.webpubsub.user.message` for simple WebSocket frames; `azure.webpubsub.user.` for PubSub subprotocol custom events. ce-source: type: string description: '`/hubs/{hub}/client/{connectionId}` (or `/client/{connectionId}` for custom events).' ce-id: type: string description: Unique event id. ce-time: type: string format: date-time ce-signature: type: string description: | `sha256={hash-primary},sha256={hash-secondary}` where each hash is `Hex(HMAC_SHA256(accessKey, connectionId))`. Upstream should validate before processing. ce-userId: type: string ce-connectionId: type: string ce-hub: type: string ce-eventName: type: string description: Event name without the `azure.webpubsub.*` prefix. ce-subprotocol: type: string description: Negotiated subprotocol, if any. ce-connectionState: type: string description: | Per-connection state propagated between events. Set by upstream on a previous blocking event response and echoed back on subsequent events. CloudEventsConnectHeaders: allOf: - $ref: '#/components/schemas/CloudEventsCommonHeaders' - type: object properties: ce-type: type: string const: azure.webpubsub.sys.connect ce-eventName: type: string const: connect CloudEventsConnectedHeaders: allOf: - $ref: '#/components/schemas/CloudEventsCommonHeaders' - type: object properties: ce-type: type: string const: azure.webpubsub.sys.connected ce-eventName: type: string const: connected CloudEventsDisconnectedHeaders: allOf: - $ref: '#/components/schemas/CloudEventsCommonHeaders' - type: object properties: ce-type: type: string const: azure.webpubsub.sys.disconnected ce-eventName: type: string const: disconnected CloudEventsMessageHeaders: allOf: - $ref: '#/components/schemas/CloudEventsCommonHeaders' - type: object properties: ce-type: type: string const: azure.webpubsub.user.message ce-eventName: type: string const: message CloudEventsCustomEventHeaders: allOf: - $ref: '#/components/schemas/CloudEventsCommonHeaders' - type: object properties: ce-type: type: string description: '`azure.webpubsub.user.`' pattern: '^azure\.webpubsub\.user\..+$' UpstreamConnectPayload: type: object description: | Body of the `connect` upstream request. Carries the client's authentication context (claims), connect-time query string, request headers, requested subprotocols, and any client TLS certificates presented during the handshake. properties: claims: type: object additionalProperties: type: array items: type: string description: Claims parsed from the client's access token. query: type: object additionalProperties: type: array items: type: string description: Query string parameters from the connect request. headers: type: object additionalProperties: type: array items: type: string description: HTTP request headers from the connect request. subprotocols: type: array items: type: string description: | Subprotocols offered by the client in `Sec-WebSocket-Protocol`. clientCertificates: type: array description: Client TLS certificates, if any. items: type: object properties: thumbprint: type: string description: SHA-1 thumbprint of the certificate. content: type: string description: PEM-encoded certificate content. UpstreamEmptyJsonPayload: type: object description: Empty JSON object. The `connected` event carries no body fields. UpstreamDisconnectedPayload: type: object required: [reason] properties: reason: type: string description: Reason the client disconnected. UpstreamUserMessagePayload: description: | Raw client frame contents. The HTTP `Content-Type` is `text/plain` for text frames and `application/octet-stream` for binary frames. oneOf: - type: string - type: string format: binary UpstreamUserCustomEventPayload: description: | The `data` value from the original `type: event` frame. The HTTP `Content-Type` reflects the original `dataType`: `text/plain` for `text`, `application/json` for `json`, `application/octet-stream` for `binary`. oneOf: - type: string - type: object additionalProperties: true - type: array items: {} - type: number - type: boolean - type: 'null' - type: string format: binary