Skip to content

AsyncAPI Spec Generation (and a “Standard Specs” generator that outputs OpenAPI + AsyncAPI) #789

@gunta

Description

@gunta

Summary

convex-helpers already generates an OpenAPI 3 spec from a Convex deployment, which is great for typed HTTP clients in other languages. I’m proposing a sibling AsyncAPI spec generator, and an umbrella “Standard Specs” command that outputs OpenAPI + AsyncAPI together. This pairs Convex’s HTTP pull model with a standards-based push model and unblocks non-JS runtimes (Unity/.NET, Unreal, IoT) from day one. The OpenAPI path is beta and explicitly non-reactive/non-realtime, so the AsyncAPI companion fills that gap.  


Motivation

  • OpenAPI (beta) is pull-only. Convex’s OpenAPI generation relies on the HTTP API, which means queries are not reactive/real-time. 
  • AsyncAPI is the standard for message-driven / streaming APIs and is protocol-agnostic (HTTP, WebSocket, MQTT, etc.). It’s the natural complement to OpenAPI for documenting server push. 
  • The Functions HTTP endpoint (POST /api/run/{functionIdentifier}) already consolidates server logic; an AsyncAPI doc can describe a streaming counterpart (SSE or WebSocket) without changing Convex’s function model. 

Proposal

1) New CLI: async-api-spec

Generate an AsyncAPI v3 document that describes Convex servers, security, channels, and messages.

Phase 1 (spec-only, no runtime changes required):

  • Emit an AsyncAPI doc that models stream-shaped HTTP interactions using HTTP bindings and operation reply (sufficient to describe SSE via text/event-stream). 
  • Reuse the same function discovery/validators used by the OpenAPI generator so payload schemas match.

Phase 2 (when a realtime watch endpoint ships):

  • Add a WebSocket or SSE server and channels to describe subscribe/watch operations (initial snapshot + patches + errors + heartbeats). AsyncAPI has official WebSocket bindings and HTTP bindings suitable for SSE. 

Output: specs/convex-asyncapi.yaml (AsyncAPI 3.0). 

2) New umbrella CLI: spec

npx convex-helpers spec --formats openapi,asyncapi --out specs/ → writes convex-openapi.yaml and convex-asyncapi.yaml, sharing config (servers/auth/metadata). This keeps “standards export” a single, CI-friendly step.


Design outline

Discovery & schemas

  • Reuse existing OpenAPI generation’s introspection so the AsyncAPI generator maps function args/returns to JSON Schema (mirroring OpenAPI components). 

Servers & security

  • Point to the deployment base (same as OpenAPI). Document auth the same way used by the HTTP API (/api/run/{functionIdentifier}), then add protocol bindings when WS/SSE is available. 

Channels & operations

  • Phase 1: Represent streaming/push over HTTP via operation reply and HTTP binding (describe SSE using text/event-stream). 
  • Phase 2: Add WS channels with message shapes for subscribe, init, patch, error, complete, plus a resumeToken for reconnects (just documentation initially). 

Tooling ecosystem

  • Validate with the AsyncAPI CLI/Generator and enable Modelina for code-gen (including C# models for Unity). 

Example (AsyncAPI v3 sketch, Phase 2 target)

asyncapi: 3.0.0
info:
  title: Convex Realtime (Watch)
  version: 0.1.0
defaultContentType: application/json
servers:
  ws:
    protocol: ws
    host: ${CONVEX_URL}
channels:
  query.messages.list:
    address: query.messages.list
    messages:
      Init:
        payload:
          type: object
          properties:
            items:
              type: array
              items:
                $ref: '#/components/schemas/Message'
      Patch:
        payload:
          type: object
          properties:
            ops:
              type: array
              items: { type: object }
    operations:
      receive:
        summary: Initial snapshot and subsequent patches for messages.list
components:
  schemas:
    Message:
      type: object
      properties:
        _id: { type: string }
        text: { type: string }
      required: [_id, text]

(SSE version would use an HTTP server and binding with text/event-stream.) 


CLI / DX

  • npx convex-helpers async-api-spec --out specs/convex-asyncapi.yaml
  • npx convex-helpers spec --formats openapi,asyncapi --out specs/
  • Post-run tip: “Use @asyncapi/cli or Generator to render docs or bootstrap clients; use Modelina to emit C# models.” 

Acceptance criteria

MVP (Phase 1):

  • New command outputs a valid AsyncAPI 3 document describing Convex servers, security, and HTTP-based channels (SSE represented via HTTP binding + operation reply). CI validates the spec. 
  • “Standard Specs” command emits both OpenAPI and AsyncAPI from shared config. (OpenAPI generator already present.) 
    Phase 2 (realtime watch available):
  • Add WebSocket/SSE servers + channels for live subscribe/watch. Message shapes include init, patch, error, complete, and a resumeToken. 

Why prioritize this

  • Completes the story for non-yet supported clients. OpenAPI covers pull; AsyncAPI covers push, together they document how to build typed, near-real-time clients in Unity/.NET and beyond. 
  • Low incremental cost. Reuses the OpenAPI generator’s discovery and schema mapping; Phase 1 is spec-only (no backend changes). 
  • Ecosystem leverage. Mature tooling exists today (AsyncAPI CLI/Generator; Modelina C#) to turn the spec into docs and models. 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions