{
  "openapi": "3.1.0",
  "info": {
    "title": "Zorelium Realtime",
    "summary": "Managed WebSocket pub/sub gateway.",
    "description": "REST control surface for the Zorelium Realtime gateway. The data path is a WebSocket at wss://edge.zorelium.site/connect and is described at https://edge.zorelium.site/docs/.",
    "version": "1.4.2",
    "license": { "name": "Proprietary" }
  },
  "servers": [ { "url": "https://edge.zorelium.site", "description": "eu-waw" } ],
  "tags": [
    { "name": "public", "description": "No credentials required." },
    { "name": "app", "description": "Requires a bearer token minted for an application." }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": ["public"], "summary": "Liveness of this gateway", "operationId": "getHealth",
        "security": [],
        "responses": { "200": { "description": "Gateway is accepting connections",
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Health" } } } } }
      }
    },
    "/v1/time": {
      "get": {
        "tags": ["public"], "summary": "Server clock", "operationId": "getTime",
        "description": "Used by clients to correct drift before validating token expiry.",
        "security": [],
        "responses": { "200": { "description": "Current server time",
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Time" } } } } }
      }
    },
    "/v1/status": {
      "get": {
        "tags": ["public"], "summary": "Region and protocol version", "operationId": "getStatus",
        "security": [],
        "responses": { "200": { "description": "Service description",
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Status" } } } } }
      }
    },
    "/v1/regions": {
      "get": {
        "tags": ["public"], "summary": "Where the service runs", "operationId": "listRegions",
        "security": [],
        "responses": { "200": { "description": "Region list",
          "content": { "application/json": { "schema": { "type": "array",
            "items": { "$ref": "#/components/schemas/Region" } } } } } }
      }
    },
    "/v1/publish": {
      "post": {
        "tags": ["app"], "summary": "Publish one frame to a channel", "operationId": "publish",
        "requestBody": { "required": true, "content": { "application/json": {
          "schema": { "$ref": "#/components/schemas/PublishRequest" } } } },
        "responses": {
          "202": { "description": "Accepted for fan-out",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublishResult" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "413": { "description": "Body above 64 KiB" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/channels": {
      "get": {
        "tags": ["app"], "summary": "Channels with traffic in the retention window", "operationId": "listChannels",
        "parameters": [
          { "name": "prefix", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 } }
        ],
        "responses": {
          "200": { "description": "Channel list",
            "content": { "application/json": { "schema": { "type": "array",
              "items": { "$ref": "#/components/schemas/Channel" } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/channels/{name}/presence": {
      "get": {
        "tags": ["app"], "summary": "Members currently present on a channel", "operationId": "getPresence",
        "parameters": [ { "name": "name", "in": "path", "required": true, "schema": { "type": "string" } } ],
        "responses": {
          "200": { "description": "Presence set",
            "content": { "application/json": { "schema": { "type": "array", "items": { "type": "string" } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "description": "Channel has no traffic in the retention window" }
        }
      }
    },
    "/v1/tokens": {
      "post": {
        "tags": ["app"], "summary": "Mint a client token", "operationId": "mintToken",
        "description": "Called by your backend with the application secret. Never call this from a browser.",
        "requestBody": { "required": true, "content": { "application/json": {
          "schema": { "$ref": "#/components/schemas/TokenRequest" } } } },
        "responses": {
          "201": { "description": "Token minted",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Token" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, malformed or expired bearer token",
        "headers": { "WWW-Authenticate": { "schema": { "type": "string" },
          "description": "Bearer realm=\"zorelium-realtime\"" } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Application rate limit tripped",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "Health": { "type": "object", "required": ["status", "region", "ts"], "properties": {
        "status": { "type": "string", "enum": ["ok", "draining"] },
        "region": { "type": "string", "examples": ["eu-waw"] },
        "ts": { "type": "string", "format": "date-time" } } },
      "Time": { "type": "object", "required": ["ts", "epoch"], "properties": {
        "ts": { "type": "string", "format": "date-time" },
        "epoch": { "type": "string", "description": "Seconds since the epoch with millisecond precision, as a string to survive JSON number rounding." } } },
      "Status": { "type": "object", "required": ["status", "region", "proto"], "properties": {
        "status": { "type": "string", "enum": ["operational", "degraded", "draining"] },
        "region": { "type": "string" },
        "proto": { "type": "string", "examples": ["1.4"] },
        "build": { "type": "string", "examples": ["1.4.2"] },
        "ws": { "type": "string", "format": "uri" } } },
      "Region": { "type": "object", "required": ["id", "location", "status"], "properties": {
        "id": { "type": "string" }, "location": { "type": "string" },
        "status": { "type": "string", "enum": ["operational", "degraded", "planned"] } } },
      "PublishRequest": { "type": "object", "required": ["channel", "data"], "properties": {
        "channel": { "type": "string", "maxLength": 255 },
        "data": { "description": "Any JSON value up to 64 KiB once encoded." },
        "exclude_sid": { "type": "string", "description": "Do not deliver back to this session." } } },
      "PublishResult": { "type": "object", "required": ["channel", "seq"], "properties": {
        "channel": { "type": "string" }, "seq": { "type": "integer", "format": "int64" },
        "delivered_to": { "type": "integer" } } },
      "Channel": { "type": "object", "required": ["name", "seq"], "properties": {
        "name": { "type": "string" }, "seq": { "type": "integer", "format": "int64" },
        "subscribers": { "type": "integer" } } },
      "TokenRequest": { "type": "object", "required": ["scopes"], "properties": {
        "scopes": { "type": "array", "items": { "type": "string", "examples": ["room:*"] } },
        "ttl_s": { "type": "integer", "minimum": 60, "maximum": 43200, "default": 3600 },
        "sub": { "type": "string", "description": "Opaque identifier of the end user, shown in presence." } } },
      "Token": { "type": "object", "required": ["token", "exp"], "properties": {
        "token": { "type": "string" }, "exp": { "type": "integer", "format": "int64" } } },
      "Error": { "type": "object", "required": ["error"], "properties": {
        "error": { "type": "string" }, "message": { "type": "string" },
        "retry_after": { "type": "integer" } } }
    }
  },
  "security": [ { "bearer": [] } ],
  "externalDocs": { "description": "Wire protocol", "url": "https://edge.zorelium.site/docs/" }
}
