{
  "openapi": "3.1.0",
  "info": {
    "title": "XR Agent Public Read API",
    "version": "1.0.0",
    "description": "Public, read-only research telemetry. Binary WebSocket: /public/api/live/{session}; framing: uint32 BE JSON-header length, UTF-8 metadata, original payload. No automatic replay."
  },
  "servers": [
    {
      "url": "https://rag.ingevision.cloud/xr-agent"
    }
  ],
  "security": [],
  "paths": {
    "/public/api/sessions": {
      "get": {
        "summary": "List session identifiers",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/monitor/sessions": {
      "get": {
        "summary": "Session summaries sorted by last received time",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}": {
      "get": {
        "summary": "Complete chunk index with timestamps and SHA-256",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}/latest": {
      "get": {
        "summary": "Latest values, health and stream metadata",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}/{stream}/{seq}": {
      "get": {
        "summary": "Original chunk bytes",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          },
          {
            "name": "stream",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "telemetry",
                "events",
                "android",
                "audio",
                "video",
                "scene"
              ]
            }
          },
          {
            "name": "seq",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Original bytes, before transport compression",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}/preview.jpg": {
      "get": {
        "summary": "JPEG from latest H.264 chunk",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preview image",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}/stream.ndjson": {
      "get": {
        "summary": "Replay stored samples then follow live as newline-delimited JSON",
        "description": "One sample per line; media lines link original audio/video. Deduplicate id after reconnection. Heartbeats every 15 seconds. Replay is not chronological. Readable while acquisition is paused.",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          },
          {
            "name": "replay",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "1"
            }
          },
          {
            "name": "follow",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "NDJSON stream (sample, media, parse_error or heartbeat)",
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Unknown session"
          }
        },
        "security": []
      }
    },
    "/public/api/control": {
      "get": {
        "summary": "Recording state decided in the web interface, headset heartbeat status (connected, worn, battery, video share, tracking) and XR Agent disk quota usage",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful read",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/public/api/sessions/{session}/export.tar": {
      "get": {
        "summary": "Session archive (streamed tar): README.txt, manifest.json, <session>/session.json and original chunks <session>/<stream>/<seq>.<ndjson|pcm|h264>",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{32}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Uncompressed tar with Content-Length",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-tar": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          },
          "429": {
            "description": "Two exports already running"
          }
        },
        "security": []
      }
    },
    "/public/api/export.tar": {
      "get": {
        "summary": "Archive of every session (streamed tar, same layout, one folder per session, no Content-Length)",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Uncompressed tar",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-tar": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "429": {
            "description": "Two exports already running"
          }
        },
        "security": []
      }
    }
  }
}
