{
  "openapi": "3.1.0",
  "info": {
    "title": "GatherCloud API",
    "description": "GatherCloud management REST API (v1 surface).",
    "version": "1.0.0"
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {}
  },
  "paths": {
    "/v1/accounts/signup": {
      "post": {
        "summary": "Sign up a new account",
        "tags": [
          "accounts"
        ],
        "description": "Create an email+password account, provision its first workspace, send a verification email, and set the account session cookie.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Account email address."
                  },
                  "password": {
                    "type": "string",
                    "description": "Account password (min 8 chars)."
                  },
                  "name": {
                    "type": "string",
                    "description": "Account display name."
                  }
                },
                "additionalProperties": true,
                "description": "Account signup credentials."
              }
            }
          },
          "description": "Account signup credentials."
        },
        "responses": {
          "201": {
            "description": "Created account with its workspaces (and a verifyUrl in email dev mode).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created account with its workspaces (and a verifyUrl in email dev mode)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts/login": {
      "post": {
        "summary": "Log in to an account",
        "tags": [
          "accounts"
        ],
        "description": "Verify email+password credentials and set the account session cookie.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Account email address."
                  },
                  "password": {
                    "type": "string",
                    "description": "Account password."
                  }
                },
                "additionalProperties": true,
                "description": "Account login credentials."
              }
            }
          },
          "description": "Account login credentials."
        },
        "responses": {
          "200": {
            "description": "Authenticated account with its workspaces.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Authenticated account with its workspaces."
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts/logout": {
      "post": {
        "summary": "Log out",
        "tags": [
          "accounts"
        ],
        "description": "Clear the account session cookie.",
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/accounts/me": {
      "get": {
        "summary": "Get the current account",
        "tags": [
          "accounts"
        ],
        "description": "Return the session account with its emails and workspaces.",
        "responses": {
          "200": {
            "description": "The current account, its emails, and its workspaces.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "The current account, its emails, and its workspaces."
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts/verify": {
      "post": {
        "summary": "Verify an email address",
        "tags": [
          "accounts"
        ],
        "description": "Mark an account email verified given a valid verification token.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "Email verification token."
                  }
                },
                "additionalProperties": true,
                "description": "Email verification request."
              }
            }
          },
          "description": "Email verification request."
        },
        "responses": {
          "200": {
            "description": "Verification result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Verification result."
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts/request-password-reset": {
      "post": {
        "summary": "Request a password reset",
        "tags": [
          "accounts"
        ],
        "description": "Send a password reset email if the address maps to a password account. Always responds identically to avoid account enumeration.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Account email address."
                  }
                },
                "additionalProperties": true,
                "description": "Password reset request."
              }
            }
          },
          "description": "Password reset request."
        },
        "responses": {
          "200": {
            "description": "Always-ok response (no account enumeration); resetUrl only in email dev mode.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Always-ok response (no account enumeration); resetUrl only in email dev mode."
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts/reset-password": {
      "post": {
        "summary": "Reset a password",
        "tags": [
          "accounts"
        ],
        "description": "Set a new password for an account given a valid reset token.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "Password reset token."
                  },
                  "password": {
                    "type": "string",
                    "description": "New password (min 8 chars)."
                  }
                },
                "additionalProperties": true,
                "description": "Password reset completion."
              }
            }
          },
          "description": "Password reset completion."
        },
        "responses": {
          "200": {
            "description": "Password reset result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Password reset result."
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/google/start": {
      "get": {
        "summary": "Start the Google OAuth flow",
        "tags": [
          "auth"
        ],
        "description": "Redirect to Google for consent (not configured yet).",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/auth/google/callback": {
      "get": {
        "summary": "Google OAuth callback",
        "tags": [
          "auth"
        ],
        "description": "Exchange the authorization code, find-or-create the account, set the session cookie, and redirect (not configured yet).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "code",
            "required": false,
            "description": "OAuth 2.0 authorization code."
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "state",
            "required": false,
            "description": "Opaque CSRF state echoed back by Google."
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "error",
            "required": false,
            "description": "OAuth error code, if the flow failed."
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/public/events/{id}": {
      "get": {
        "summary": "Get a public event view",
        "tags": [
          "public"
        ],
        "description": "Fetch the public lobby/stage view for an event: phases, on-stage cast (names only), and the active broadcast. Private events require a session of the owning workspace.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Public event view (lobby/stage state).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Public event view (lobby/stage state)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/events/{id}/table-summary": {
      "get": {
        "summary": "Read your own table’s notes",
        "tags": [
          "public"
        ],
        "description": "Exchange the token from a \"notes from your table\" email for that one table’s notes. Never returns another table’s content.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "t",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "event",
                    "table",
                    "recipientUserId",
                    "recipientName",
                    "summary",
                    "stats",
                    "people",
                    "generatedAt"
                  ],
                  "properties": {
                    "event": {
                      "type": "object",
                      "required": [
                        "id",
                        "title",
                        "scheduledAt"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "scheduledAt": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "additionalProperties": true
                    },
                    "table": {
                      "type": "object",
                      "required": [
                        "roomId",
                        "number",
                        "label"
                      ],
                      "properties": {
                        "roomId": {
                          "type": "string"
                        },
                        "number": {
                          "type": "integer"
                        },
                        "label": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    },
                    "recipientUserId": {
                      "type": "string"
                    },
                    "recipientName": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "summary": {
                      "type": "object",
                      "required": [
                        "tldr",
                        "themes",
                        "ideas",
                        "questions",
                        "perQuestion"
                      ],
                      "properties": {
                        "tldr": {
                          "type": "string"
                        },
                        "themes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "title",
                              "summary"
                            ],
                            "properties": {
                              "title": {
                                "type": "string"
                              },
                              "summary": {
                                "type": "string"
                              }
                            },
                            "additionalProperties": true
                          }
                        },
                        "ideas": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "questions": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "perQuestion": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "ordinal",
                              "question",
                              "discussed",
                              "summary"
                            ],
                            "properties": {
                              "ordinal": {
                                "type": "integer"
                              },
                              "question": {
                                "type": "string"
                              },
                              "discussed": {
                                "type": "boolean"
                              },
                              "summary": {
                                "type": "string"
                              }
                            },
                            "additionalProperties": true
                          }
                        }
                      },
                      "additionalProperties": true
                    },
                    "stats": {
                      "anyOf": [
                        {
                          "type": "object",
                          "required": [
                            "totalWords",
                            "promptsCovered",
                            "promptsTotal",
                            "lifetimeSeconds",
                            "headcount"
                          ],
                          "properties": {
                            "totalWords": {
                              "type": "integer"
                            },
                            "promptsCovered": {
                              "type": "integer"
                            },
                            "promptsTotal": {
                              "type": "integer"
                            },
                            "lifetimeSeconds": {
                              "type": "integer"
                            },
                            "headcount": {
                              "type": "integer"
                            }
                          },
                          "additionalProperties": true
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "people": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "userId",
                          "name",
                          "words",
                          "turns",
                          "badges"
                        ],
                        "properties": {
                          "userId": {
                            "type": "string"
                          },
                          "name": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "words": {
                            "type": "integer"
                          },
                          "turns": {
                            "type": "integer"
                          },
                          "badges": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "id",
                                "name",
                                "description",
                                "tier",
                                "icon"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "description": {
                                  "type": "string"
                                },
                                "tier": {
                                  "type": "integer"
                                },
                                "icon": {
                                  "type": "string"
                                },
                                "glyph": {
                                  "type": "string"
                                }
                              },
                              "additionalProperties": true
                            }
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "generatedAt": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/events/{id}/recap": {
      "get": {
        "summary": "Get a public event recap",
        "tags": [
          "public"
        ],
        "description": "Fetch an event’s recap: latest recording, clips, and AI summary (text + speaker stats). Private events require a session of the owning workspace.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Public event recap (recording, clips, summary).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Public event recap (recording, clips, summary)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/events/{id}/content": {
      "get": {
        "summary": "Get public post-event content",
        "tags": [
          "public"
        ],
        "description": "Fetch an event’s full post-event content (recording, derivations, generated media, cast) for the shareable replay page. Private events require a session of the owning workspace.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Public post-event content (recording, derivations, generated media) for the shareable replay page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Public post-event content (recording, derivations, generated media) for the shareable replay page."
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/assets/{id}": {
      "get": {
        "summary": "Get a public asset",
        "tags": [
          "public"
        ],
        "description": "Fetch a single asset (clip/recording) with its event context, for share-link targets. Gated on the parent event’s visibility.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Public asset view with event context.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Public asset view with event context."
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/events/{id}/register": {
      "post": {
        "summary": "Register for an event",
        "tags": [
          "public"
        ],
        "description": "Public self-registration: sign up for an event with a name and email. Rejected with `event_full` once the participant capacity is reached. Private events cannot be self-registered for.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "email": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320,
                    "format": "email"
                  }
                },
                "additionalProperties": false,
                "description": "Public self-registration for an event."
              }
            }
          },
          "description": "Public self-registration for an event."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Result of a public self-registration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "registered",
                    "alreadyRegistered"
                  ],
                  "properties": {
                    "registered": {
                      "type": "boolean"
                    },
                    "alreadyRegistered": {
                      "type": "boolean"
                    }
                  },
                  "description": "Result of a public self-registration."
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/events/{id}/enter": {
      "post": {
        "summary": "Enter an event from a registration link",
        "tags": [
          "public"
        ],
        "description": "Exchange the registration-entry token from the self-registration confirmation email for a session token, so the registrant can join the event room.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "additionalProperties": false,
                "description": "Registration-entry token exchange."
              }
            }
          },
          "description": "Registration-entry token exchange."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "A session for the registrant, minted from their entry token.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "sessionToken",
                    "eventId",
                    "name"
                  ],
                  "properties": {
                    "sessionToken": {
                      "type": "string"
                    },
                    "eventId": {
                      "type": "string"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "description": "A session for the registrant, minted from their entry token."
                }
              }
            }
          }
        }
      }
    },
    "/v1/help/chat": {
      "post": {
        "summary": "Ask the in-product help assistant",
        "tags": [
          "help"
        ],
        "description": "Answer a question about using GatherCloud, grounded in the product FAQ. Unauthenticated and rate-limited; replies are not stored or broadcast.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "messages"
                ],
                "properties": {
                  "audience": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "host"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "viewer"
                        ]
                      }
                    ],
                    "description": "Which audience the assistant should answer as."
                  },
                  "surface": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "room"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "dashboard"
                        ]
                      }
                    ],
                    "description": "Where the user is asking from."
                  },
                  "eventType": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "stage": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "prelive"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "open"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "live"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "ended"
                        ]
                      }
                    ]
                  },
                  "messages": {
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "object",
                          "required": [
                            "role",
                            "text"
                          ],
                          "properties": {
                            "role": {
                              "type": "string",
                              "enum": [
                                "user"
                              ]
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 500
                            }
                          },
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "required": [
                            "role",
                            "text"
                          ],
                          "properties": {
                            "role": {
                              "type": "string",
                              "enum": [
                                "model"
                              ]
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2200
                            }
                          },
                          "additionalProperties": false
                        }
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 8
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [],
        "responses": {
          "200": {
            "description": "The assistant reply for the latest user turn.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "reply"
                  ],
                  "properties": {
                    "reply": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true,
                  "description": "The assistant reply for the latest user turn."
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/gateway-token": {
      "post": {
        "summary": "Mint a gateway token",
        "tags": [
          "auth"
        ],
        "description": "Mint a short-lived Live Gateway WebSocket token for an event. A Bearer session token grants the caller their event role, narrowed to one the event actually has (workspace owners/admins default to host); without one, an anonymous viewer token is issued for public events that contain a broadcast phase. A signed-out caller on a call (meeting/breakout/rotation) is refused with `sign_in_required` — there is no anonymous seat to give them.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "eventId"
                ],
                "properties": {
                  "eventId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/guest-session": {
      "post": {
        "summary": "Exchange a partner JWT for a guest session",
        "tags": [
          "auth"
        ],
        "description": "Verify a partner-issued JWT against the event workspace’s registered guest integration and mint an ephemeral guest session scoped to this event. Guests get a real in-room identity from the JWT claims but no account, workspace, or persistent record. If the JWT email belongs to an existing GatherCloud account, the exchange is refused (409) and the caller must log in instead.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The raw partner-issued JWT."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/guest-integrations": {
      "post": {
        "summary": "Register a partner guest-JWT integration",
        "tags": [
          "guest-integrations"
        ],
        "description": "Register a partner platform (issuer + public key material) whose RS256-signed JWTs may join this workspace’s events as named guests. Provide exactly one of jwksUrl / publicKeyPem.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "issuer"
                ],
                "properties": {
                  "issuer": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The partner JWT's `iss` claim, verbatim."
                  },
                  "jwksUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "JWKS endpoint publishing the signing keys."
                  },
                  "publicKeyPem": {
                    "type": "string",
                    "minLength": 1,
                    "description": "SPKI PEM public key (RS256)."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List partner guest-JWT integrations",
        "tags": [
          "guest-integrations"
        ],
        "description": "List the workspace’s active (non-revoked) guest integrations.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/guest-integrations/{integrationId}": {
      "delete": {
        "summary": "Revoke a partner guest-JWT integration",
        "tags": [
          "guest-integrations"
        ],
        "description": "Revoke an integration: new guest-session exchanges for its issuer are refused immediately. Already-minted guest sessions run out their TTL.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "integrationId",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/workspaces": {
      "post": {
        "summary": "Create a workspace",
        "tags": [
          "workspaces"
        ],
        "description": "Self-serve workspace creation by any logged-in account (ADR 0007). A first \"default\" API key is generated and returned once in the response.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "slug": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created workspace plus the first API key (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created workspace plus the first API key (shown once)."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List workspaces",
        "tags": [
          "workspaces"
        ],
        "description": "List the calling account’s workspaces. With a valid x-platform-key header, lists all workspaces (platform ops).",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "workspaces"
                  ],
                  "properties": {
                    "workspaces": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Workspace resource."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}": {
      "patch": {
        "summary": "Update a workspace",
        "tags": [
          "workspaces"
        ],
        "description": "Rename a workspace and/or change its slug (owner/admin only). The slug is the workspace’s public handle, so it is kept unique and well-formed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Updated workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Updated workspace."
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/members": {
      "get": {
        "summary": "List workspace members",
        "tags": [
          "workspaces"
        ],
        "description": "List the workspace’s members with their role and primary email. Any member of the workspace may view this.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "members"
                  ],
                  "properties": {
                    "members": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/members/{memberId}": {
      "patch": {
        "summary": "Update a member role",
        "tags": [
          "workspaces"
        ],
        "description": "Change a member role between \"member\" and \"admin\" (owner/admin only). Owner roles are protected and cannot be changed via this endpoint.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "role"
                ],
                "properties": {
                  "role": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "member"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "admin"
                        ]
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "memberId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Updated member.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Updated member."
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a member",
        "tags": [
          "workspaces"
        ],
        "description": "Remove a member from the workspace (owner/admin only). Owners cannot be removed. To remove yourself use DELETE /v1/workspaces/:id/members/me.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "memberId",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/workspaces/{id}/members/me": {
      "delete": {
        "summary": "Leave a workspace",
        "tags": [
          "workspaces"
        ],
        "description": "Remove yourself from the workspace. Blocked if you are the only owner — transfer ownership or promote another member to owner first.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/workspaces/{id}/session": {
      "post": {
        "summary": "Mint a workspace session token",
        "tags": [
          "workspaces"
        ],
        "description": "THE BRIDGE (ADR 0007): exchange an account session for a workspace session token. Upserts the account’s per-workspace participant identity (users row) and mints the workspace session token.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace session token plus the bridged participant identity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Workspace session token plus the bridged participant identity."
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/api-keys": {
      "get": {
        "summary": "List workspace API keys",
        "tags": [
          "api-keys"
        ],
        "description": "List the workspace’s API keys (owner/admin only). Key secrets are never returned — only metadata and revocation state.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "apiKeys"
                  ],
                  "properties": {
                    "apiKeys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a workspace API key",
        "tags": [
          "api-keys"
        ],
        "description": "Create a new API key for the workspace (owner/admin only). The secret key value is returned once in this response and never again.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "Created API key, including the secret key value (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created API key, including the secret key value (shown once)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/api-keys/{keyId}": {
      "delete": {
        "summary": "Revoke or delete a workspace API key",
        "tags": [
          "api-keys"
        ],
        "description": "Owner/admin only. The first DELETE soft-revokes the key (the row stays auditable); a second DELETE on an already-revoked key removes it permanently.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "keyId",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/api-keys": {
      "post": {
        "summary": "Create an API key (API-key authed)",
        "tags": [
          "api-keys"
        ],
        "description": "API-first self-service: create a new API key for the workspace scoped by the calling key (x-api-key). The new secret key value is returned once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created API key, including the secret key value (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created API key, including the secret key value (shown once)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}/invites": {
      "post": {
        "summary": "Create an invite",
        "tags": [
          "invites"
        ],
        "description": "Create a workspace or event invite (admin/owner account session, or the workspace API key). The token is the authority; the link is returned once for link/dev invites.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string"
                  },
                  "kind": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "workspace"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "event"
                        ]
                      }
                    ],
                    "description": "Whether an invite grants workspace or event access.",
                    "title": "InviteKind"
                  },
                  "eventId": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "Created invite metadata plus, for link/dev invites, the invite URL (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created invite metadata plus, for link/dev invites, the invite URL (shown once)."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List workspace invites",
        "tags": [
          "invites"
        ],
        "description": "List the workspace’s invites for the members screen. Any member of the workspace may view this.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "invites"
                  ],
                  "properties": {
                    "invites": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/invites/{token}": {
      "get": {
        "summary": "Preview an invite",
        "tags": [
          "invites"
        ],
        "description": "Public preview of an invite — what the /invite/:token page renders.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "token",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Public invite preview for the /invite/:token page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Public invite preview for the /invite/:token page."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invites/{token}/accept": {
      "post": {
        "summary": "Accept an invite",
        "tags": [
          "invites"
        ],
        "description": "Accept an invite as the logged-in account. The token is the authority; an email mismatch is a UX confirmation, never an error.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "token",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Acceptance result (workspace or event binding).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Acceptance result (workspace or event binding)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invites/{token}/attend": {
      "post": {
        "summary": "Attend an event invite without an account",
        "tags": [
          "invites"
        ],
        "description": "Join an event from an invite link WITHOUT an account: name-only join. Mints a workspace session for a gc-invite participant; the link is multi-use.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "titleOrg": {
                    "type": "string",
                    "maxLength": 80
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "token",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace session token for an accountless attendee plus their participant identity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Workspace session token for an accountless attendee plus their participant identity."
                }
              }
            }
          }
        }
      }
    },
    "/v1/invites/{id}": {
      "delete": {
        "summary": "Revoke an invite",
        "tags": [
          "invites"
        ],
        "description": "Revoke an invite (admin/owner account session, or the workspace API key). Auth is dispatched inside the handler once the invite’s workspace is known.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/invites/{id}/resend": {
      "post": {
        "summary": "Resend an invite email",
        "tags": [
          "invites"
        ],
        "description": "Re-deliver an addressed invite. Mints a fresh token (the old link stops working) and renews expiry, then emails the recipient. Admin/owner account session, or the workspace API key.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Created invite metadata plus, for link/dev invites, the invite URL (shown once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Created invite metadata plus, for link/dev invites, the invite URL (shown once)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events": {
      "post": {
        "summary": "Create an event",
        "tags": [
          "events"
        ],
        "description": "Create an event, optionally with an initial ordered list of phases. A session-authed creator is enrolled as host.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type",
                  "title"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "minLength": 1
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1
                  },
                  "scheduledAt": {
                    "type": "string"
                  },
                  "scheduledEndAt": {
                    "type": "string"
                  },
                  "visibility": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "public"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "unlisted"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "private"
                        ]
                      }
                    ],
                    "description": "Event discoverability.",
                    "title": "Visibility"
                  },
                  "allowAnonymousVoting": {
                    "type": "boolean"
                  },
                  "allowAnonymousQuestions": {
                    "type": "boolean"
                  },
                  "capacity": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "properties": {
                      "design": {
                        "type": "object",
                        "properties": {
                          "background": {
                            "anyOf": [
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "url"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "image"
                                    ]
                                  },
                                  "url": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "color"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "color"
                                    ]
                                  },
                                  "color": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "css"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "gradient"
                                    ]
                                  },
                                  "css": {
                                    "type": "string"
                                  },
                                  "from": {
                                    "type": "string"
                                  },
                                  "to": {
                                    "type": "string"
                                  },
                                  "style": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "preset"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "animated"
                                    ]
                                  },
                                  "preset": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "enum": [
                                          "aurora"
                                        ]
                                      },
                                      {
                                        "type": "string",
                                        "enum": [
                                          "mesh"
                                        ]
                                      },
                                      {
                                        "type": "string",
                                        "enum": [
                                          "drift"
                                        ]
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          },
                          "accentColor": {
                            "type": "string"
                          },
                          "tileBorderColor": {
                            "type": "string"
                          },
                          "logoUrl": {
                            "type": "string"
                          },
                          "layout": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": false,
                        "description": "Host-configured stage look (RoomDesign)."
                      }
                    },
                    "additionalProperties": true,
                    "description": "Caller-supplied metadata."
                  },
                  "phases": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "modality": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "broadcast"
                              ]
                            },
                            {
                              "type": "string",
                              "enum": [
                                "breakout"
                              ]
                            },
                            {
                              "type": "string",
                              "enum": [
                                "meeting"
                              ]
                            },
                            {
                              "type": "string",
                              "enum": [
                                "rotation"
                              ]
                            }
                          ],
                          "description": "The behaviour of a phase.",
                          "title": "Modality"
                        },
                        "config": {
                          "type": "object",
                          "properties": {
                            "roomSize": {
                              "type": "number"
                            },
                            "durationSeconds": {
                              "type": "number"
                            },
                            "openConversationSeconds": {
                              "type": "number"
                            },
                            "extendable": {
                              "type": "boolean"
                            },
                            "rebalanceThreshold": {
                              "type": "number"
                            },
                            "lobby": {
                              "type": "boolean"
                            },
                            "lobbyWaitSeconds": {
                              "type": "number"
                            },
                            "rounds": {
                              "type": "number"
                            },
                            "roundSeconds": {
                              "type": "number"
                            }
                          },
                          "additionalProperties": true,
                          "description": "Modality-specific phase settings.",
                          "title": "PhaseConfig"
                        },
                        "featureSet": {
                          "type": "array",
                          "items": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "qa"
                                ]
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "chat"
                                ]
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "polls"
                                ]
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "reactions"
                                ]
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "transcript"
                                ]
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "capture"
                                ]
                              }
                            ],
                            "description": "Interactive feature toggle.",
                            "title": "Feature"
                          }
                        }
                      },
                      "description": "Phase definition."
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Event resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Event resource."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List events",
        "tags": [
          "events"
        ],
        "description": "List the workspace’s most recent events (max 100).",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "events"
                  ],
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Event resource."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}": {
      "get": {
        "summary": "Get an event",
        "tags": [
          "events"
        ],
        "description": "Fetch a single event with its ordered phases.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Event with its ordered phases.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "phases"
                  ],
                  "properties": {
                    "phases": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Phase resource."
                      }
                    }
                  },
                  "additionalProperties": true,
                  "description": "Event with its ordered phases."
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update an event",
        "tags": [
          "events"
        ],
        "description": "Patch event fields. Schedule (start/end) changes bump the calendar sequence and resend the .ics invite (ADR 0008).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "scheduledAt": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "scheduledEndAt": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "visibility": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "public"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "unlisted"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "private"
                        ]
                      }
                    ],
                    "description": "Event discoverability."
                  },
                  "allowAnonymousVoting": {
                    "type": "boolean"
                  },
                  "allowAnonymousQuestions": {
                    "type": "boolean"
                  },
                  "capacity": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "properties": {
                      "design": {
                        "type": "object",
                        "properties": {
                          "background": {
                            "anyOf": [
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "url"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "image"
                                    ]
                                  },
                                  "url": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "color"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "color"
                                    ]
                                  },
                                  "color": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "css"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "gradient"
                                    ]
                                  },
                                  "css": {
                                    "type": "string"
                                  },
                                  "from": {
                                    "type": "string"
                                  },
                                  "to": {
                                    "type": "string"
                                  },
                                  "style": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "preset"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "animated"
                                    ]
                                  },
                                  "preset": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "enum": [
                                          "aurora"
                                        ]
                                      },
                                      {
                                        "type": "string",
                                        "enum": [
                                          "mesh"
                                        ]
                                      },
                                      {
                                        "type": "string",
                                        "enum": [
                                          "drift"
                                        ]
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          },
                          "accentColor": {
                            "type": "string"
                          },
                          "tileBorderColor": {
                            "type": "string"
                          },
                          "logoUrl": {
                            "type": "string"
                          },
                          "layout": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": false,
                        "description": "Host-configured stage look (RoomDesign)."
                      }
                    },
                    "additionalProperties": true,
                    "description": "Caller-supplied metadata."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Event resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Event resource."
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete (cancel) an event",
        "tags": [
          "events"
        ],
        "description": "Delete an event. This is the cancel path: calendar invites are cancelled before the row is removed (ADR 0008).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/calendar.ics": {
      "get": {
        "summary": "Download the event as an iCalendar (.ics) file",
        "tags": [
          "events"
        ],
        "description": "Export the event as an .ics file to import into Google Calendar, Outlook or Apple Calendar. Uses the same UID and calendar sequence as the emailed invites, so re-importing after a reschedule updates the existing calendar entry in place (ADR 0008).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/publish": {
      "post": {
        "summary": "Publish an event",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/start": {
      "post": {
        "summary": "Start an event",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/advance": {
      "post": {
        "summary": "Advance to the next phase",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/end": {
      "post": {
        "summary": "End an event",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/phases": {
      "post": {
        "summary": "Append a phase to an event",
        "tags": [
          "events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "modality": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "broadcast"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "breakout"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "meeting"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "rotation"
                        ]
                      }
                    ],
                    "description": "The behaviour of a phase."
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "roomSize": {
                        "type": "number"
                      },
                      "durationSeconds": {
                        "type": "number"
                      },
                      "openConversationSeconds": {
                        "type": "number"
                      },
                      "extendable": {
                        "type": "boolean"
                      },
                      "rebalanceThreshold": {
                        "type": "number"
                      },
                      "lobby": {
                        "type": "boolean"
                      },
                      "lobbyWaitSeconds": {
                        "type": "number"
                      },
                      "rounds": {
                        "type": "number"
                      },
                      "roundSeconds": {
                        "type": "number"
                      }
                    },
                    "additionalProperties": true,
                    "description": "Modality-specific phase settings."
                  },
                  "featureSet": {
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "qa"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "chat"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "polls"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "reactions"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "transcript"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "capture"
                          ]
                        }
                      ],
                      "description": "Interactive feature toggle."
                    }
                  }
                },
                "description": "Phase definition."
              }
            }
          },
          "description": "Phase definition."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "Phase resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Phase resource."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}/extend": {
      "post": {
        "summary": "Extend the active phase timer",
        "tags": [
          "events"
        ],
        "description": "Add seconds (10–3600) to the active phase’s timer.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "seconds"
                ],
                "properties": {
                  "seconds": {
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 3600
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "extendedBySeconds"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "extendedBySeconds": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}": {
      "patch": {
        "summary": "Update a phase",
        "tags": [
          "events"
        ],
        "description": "Patch a phase’s config and/or feature set.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "modality": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "broadcast"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "breakout"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "meeting"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "rotation"
                        ]
                      }
                    ],
                    "description": "The behaviour of a phase."
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "roomSize": {
                        "type": "number"
                      },
                      "durationSeconds": {
                        "type": "number"
                      },
                      "openConversationSeconds": {
                        "type": "number"
                      },
                      "extendable": {
                        "type": "boolean"
                      },
                      "rebalanceThreshold": {
                        "type": "number"
                      },
                      "lobby": {
                        "type": "boolean"
                      },
                      "lobbyWaitSeconds": {
                        "type": "number"
                      },
                      "rounds": {
                        "type": "number"
                      },
                      "roundSeconds": {
                        "type": "number"
                      }
                    },
                    "additionalProperties": true,
                    "description": "Modality-specific phase settings."
                  },
                  "featureSet": {
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "qa"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "chat"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "polls"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "reactions"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "transcript"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "capture"
                          ]
                        }
                      ],
                      "description": "Interactive feature toggle."
                    }
                  }
                },
                "description": "Phase definition."
              }
            }
          },
          "description": "Phase definition."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Phase resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Phase resource."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/memberships": {
      "post": {
        "summary": "Assign an event membership role",
        "tags": [
          "events"
        ],
        "description": "Assign (or update) a user’s role on an event. Role designation is GatherCloud-side, never a JWT claim.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userId",
                  "role"
                ],
                "properties": {
                  "userId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "role": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "workspace_admin"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "host"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "speaker"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "participant"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "viewer"
                        ]
                      }
                    ],
                    "description": "Per-event membership role.",
                    "title": "Role"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "Membership resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Membership resource."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/attendees": {
      "get": {
        "summary": "List live attendees",
        "tags": [
          "events"
        ],
        "description": "Host view: the event’s present attendees (those who have not left).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Live attendee roster (host view).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "attendees"
                  ],
                  "properties": {
                    "attendees": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "description": "Live attendee roster (host view)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/registrations": {
      "get": {
        "summary": "List registered participants",
        "tags": [
          "events"
        ],
        "description": "Host view: everyone registered for the event (an attendee-role membership that has not left), with their name, email and registration time, plus the confirmed count against capacity. Emails are host-only, so this is gated to hosts/admins.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Registered participants with a confirmed count vs capacity (host view).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "registrations",
                    "confirmedCount",
                    "capacity"
                  ],
                  "properties": {
                    "registrations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    },
                    "confirmedCount": {
                      "type": "integer"
                    },
                    "capacity": {
                      "anyOf": [
                        {
                          "type": "integer"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "description": "Registered participants with a confirmed count vs capacity (host view)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/my-kick-status": {
      "get": {
        "summary": "Get my kick status",
        "tags": [
          "events"
        ],
        "description": "Whether the calling session has been removed from the event. Polled by attendees as a fallback when the realtime gateway is unavailable.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Whether the caller has been removed from the event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Whether the caller has been removed from the event."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/memberships/{userId}": {
      "delete": {
        "summary": "Remove (kick) an attendee",
        "tags": [
          "events"
        ],
        "description": "Host-only: remove an attendee from the event and evict them from their media room. Session callers need host/workspace_admin; API-key callers have full access.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "userId",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/breakout/overview": {
      "get": {
        "summary": "List breakout rooms with participants",
        "tags": [
          "events"
        ],
        "description": "Host view: every open room in the active phase, each with the participants currently assigned to it (name, role, membership id). Session callers need host/workspace_admin.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Open rooms of the active phase, each with its participants (host view).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rooms",
                    "self"
                  ],
                  "properties": {
                    "rooms": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    },
                    "self": {
                      "type": "object",
                      "required": [
                        "roomId",
                        "mode",
                        "canChoose"
                      ],
                      "properties": {
                        "roomId": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mode": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "participant"
                              ]
                            },
                            {
                              "type": "string",
                              "enum": [
                                "observer"
                              ]
                            }
                          ],
                          "description": "How a host enters a breakout table.",
                          "title": "BreakoutJoinMode"
                        },
                        "canChoose": {
                          "type": "boolean"
                        }
                      },
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true,
                  "description": "Open rooms of the active phase, each with its participants (host view)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/breakout/move": {
      "post": {
        "summary": "Move a participant between rooms",
        "tags": [
          "events"
        ],
        "description": "Host-only: reassign a participant (by membership) to another open room in the same active phase, evict them from their current room, and push a room event so their client reconnects to the new room.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "membershipId",
                  "toRoomId"
                ],
                "properties": {
                  "membershipId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "toRoomId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "additionalProperties": false,
                "description": "Move a participant into another open room."
              }
            }
          },
          "description": "Move a participant into another open room."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Move result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Move result."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/breakout/join": {
      "post": {
        "summary": "Enter a breakout table as a participant or observer",
        "tags": [
          "events"
        ],
        "description": "Host-only: put the caller into one of the active breakout’s open tables, either as an ordinary participant or as an observer who watches without taking part in the table. Evicts them from their previous table and pushes a room event so their own client reconnects to the new one.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "roomId",
                  "mode"
                ],
                "properties": {
                  "roomId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "mode": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "participant"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "observer"
                        ]
                      }
                    ],
                    "description": "How a host enters a breakout table."
                  }
                },
                "additionalProperties": false,
                "description": "Enter one of the active breakout’s tables as a participant or an observer."
              }
            }
          },
          "description": "Enter one of the active breakout’s tables as a participant or an observer."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The table the caller is now in, and how.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "The table the caller is now in, and how."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/breakout/leave": {
      "post": {
        "summary": "Step out of a breakout table",
        "tags": [
          "events"
        ],
        "description": "Host-only: leave the caller’s current breakout table and return to the room overview. Evicts them from the media room and clears their table assignment; other participants are unaffected.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Result of stepping out of a breakout table.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Result of stepping out of a breakout table."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/questions": {
      "get": {
        "summary": "List event questions",
        "tags": [
          "events"
        ],
        "description": "List an event’s questions with their vote tallies, top first.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "questions"
                  ],
                  "properties": {
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/assets": {
      "get": {
        "summary": "List event assets",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "assets"
                  ],
                  "properties": {
                    "assets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/segments/{id}": {
      "delete": {
        "summary": "Soft-delete a segment",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/segments/{id}/playback": {
      "get": {
        "summary": "Get a recording part’s playback URL",
        "tags": [
          "events"
        ],
        "description": "Resolve one recording segment’s playback URL on demand (derived from the Mux asset’s playback id). Returns a null URL with a status while the asset is still processing or unavailable.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "On-demand playback URL + status for one recording part.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "On-demand playback URL + status for one recording part."
                }
              }
            }
          }
        }
      }
    },
    "/v1/users": {
      "get": {
        "summary": "List workspace users",
        "tags": [
          "events"
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "users"
                  ],
                  "properties": {
                    "users": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Pre-provision a workspace user",
        "tags": [
          "events"
        ],
        "description": "Upsert a user by external subject (workspace directory bridge).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "externalSub"
                ],
                "properties": {
                  "externalSub": {
                    "type": "string",
                    "minLength": 1
                  },
                  "email": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "picture": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "User resource."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/prompts": {
      "get": {
        "summary": "List an event’s discussion prompts",
        "tags": [
          "prompts"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The event’s discussion prompts, in order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "prompts"
                  ],
                  "properties": {
                    "prompts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true,
                  "description": "The event’s discussion prompts, in order."
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Append a discussion prompt",
        "tags": [
          "prompts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "body"
                ],
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "turnSeconds": {
                    "type": "integer",
                    "minimum": 15,
                    "maximum": 1800
                  }
                },
                "additionalProperties": false,
                "description": "A discussion question to append."
              }
            }
          },
          "description": "A discussion question to append."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "201": {
            "description": "A discussion prompt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "A discussion prompt."
                }
              }
            }
          }
        }
      }
    },
    "/v1/prompts/{id}": {
      "patch": {
        "summary": "Update a discussion prompt",
        "tags": [
          "prompts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "turnSeconds": {
                    "type": "integer",
                    "minimum": 15,
                    "maximum": 1800
                  }
                },
                "additionalProperties": false,
                "description": "Patch a discussion question."
              }
            }
          },
          "description": "Patch a discussion question."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "A discussion prompt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "A discussion prompt."
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a discussion prompt",
        "tags": [
          "prompts"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/prompts/reorder": {
      "post": {
        "summary": "Reorder an event’s discussion prompts",
        "tags": [
          "prompts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "minItems": 1,
                    "uniqueItems": true
                  }
                },
                "additionalProperties": false,
                "description": "Reorder the event’s prompts."
              }
            }
          },
          "description": "Reorder the event’s prompts."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The event’s discussion prompts, in order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "prompts"
                  ],
                  "properties": {
                    "prompts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true,
                  "description": "The event’s discussion prompts, in order."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/prompts/generate": {
      "post": {
        "summary": "AI-draft discussion prompts from the event",
        "tags": [
          "prompts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  }
                },
                "additionalProperties": false,
                "description": "AI-draft discussion questions from the event."
              }
            }
          },
          "description": "AI-draft discussion questions from the event."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The event’s discussion prompts, in order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "prompts"
                  ],
                  "properties": {
                    "prompts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true,
                  "description": "The event’s discussion prompts, in order."
                }
              }
            }
          }
        }
      }
    },
    "/v1/rooms/{roomId}/prompts/advance": {
      "post": {
        "summary": "Advance this breakout table to the next discussion prompt",
        "tags": [
          "prompts"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "roomId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "A discussion prompt.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "A discussion prompt."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/media-token": {
      "post": {
        "summary": "Mint a media join token",
        "tags": [
          "media"
        ],
        "description": "Mint a media-server token for the session user to join the active phase’s room. Lazily enrolls an eligible session user as a participant (or host, for workspace admins) when they have no membership yet.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Media join token + room coordinates.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Media join token + room coordinates."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/lobby/join-now": {
      "post": {
        "summary": "Leave the lobby and join a table now",
        "tags": [
          "media"
        ],
        "description": "Skip the breakout lobby wait and place the caller into a table right away (emptiest open table, or a new one if none are open).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Media join token + room coordinates.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Media join token + room coordinates."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/extend": {
      "post": {
        "summary": "Extend the caller’s breakout table (participant)",
        "tags": [
          "media"
        ],
        "description": "Add seconds to the caller’s own breakout table’s open-conversation buffer. Allowed only when the breakout has a duration and the host enabled extensions, and the caller is seated at a table. Other tables and the phase hard limit are unaffected; cumulative extension is capped.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "seconds"
                ],
                "properties": {
                  "seconds": {
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 3600
                  }
                },
                "additionalProperties": false,
                "description": "Seconds to add to the active breakout timer."
              }
            }
          },
          "description": "Seconds to add to the active breakout timer."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Extend result (seconds added).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Extend result (seconds added)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/rooms/{id}/transcript-cues": {
      "post": {
        "summary": "Push transcript cues",
        "tags": [
          "media"
        ],
        "description": "Client-push path for on-device transcription: room participants stream cues up, which are stored and fanned out as live domain events. Only open while the room’s transcription is active (never in the green room or during a pause).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "cues": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "tsStart": {
                          "type": "number"
                        },
                        "tsEnd": {
                          "type": "number"
                        },
                        "text": {
                          "type": "string"
                        },
                        "speaker": {
                          "type": "string"
                        }
                      },
                      "description": "A single transcript cue."
                    }
                  }
                },
                "additionalProperties": false,
                "description": "Batch of transcript cues to ingest."
              }
            }
          },
          "description": "Batch of transcript cues to ingest."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Ingestion result (accepted count).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Ingestion result (accepted count)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}/broadcast/start": {
      "post": {
        "summary": "Start (or resume) a broadcast",
        "tags": [
          "broadcasts"
        ],
        "description": "Take the phase’s broadcast offline|paused → live, opening a new recording segment and returning its playback URL.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Broadcast went live; the new segment ordinal and playback URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Broadcast went live; the new segment ordinal and playback URL."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}/broadcast/pause": {
      "post": {
        "summary": "Pause a broadcast",
        "tags": [
          "broadcasts"
        ],
        "description": "Pause a live broadcast (live → paused), closing the open segment.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Broadcast paused or stopped; the closed segment’s asset id (if any).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Broadcast paused or stopped; the closed segment’s asset id (if any)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}/broadcast/stop": {
      "post": {
        "summary": "Stop a broadcast",
        "tags": [
          "broadcasts"
        ],
        "description": "Stop a live broadcast (live → offline), closing the open segment.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Broadcast paused or stopped; the closed segment’s asset id (if any).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Broadcast paused or stopped; the closed segment’s asset id (if any)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phases/{id}/broadcast/resume": {
      "post": {
        "summary": "Resume a broadcast",
        "tags": [
          "broadcasts"
        ],
        "description": "Alias for start-from-paused: redirects (307) to the broadcast start route.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/segments": {
      "get": {
        "summary": "List broadcast segments",
        "tags": [
          "broadcasts"
        ],
        "description": "List an event’s broadcast segments, ordered.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "An event’s broadcast segments, ordered.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "segments"
                  ],
                  "properties": {
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "description": "An event’s broadcast segments, ordered."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/recordings/merge": {
      "post": {
        "summary": "Merge broadcast recordings",
        "tags": [
          "broadcasts"
        ],
        "description": "Merge the remaining (non-deleted) segments into the final recap recording. Lets a host re-merge after editing the segment list.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Recap merge result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Recap merge result."
                }
              }
            }
          }
        }
      }
    },
    "/v1/assets/{id}/clip": {
      "post": {
        "summary": "Clip a recording",
        "tags": [
          "assets"
        ],
        "description": "Clip a time range out of a Mux-backed recording asset, producing a new clip asset (resolved asynchronously via the asset-check task). Participant-facing: workspace API key or a session.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "startSeconds": {
                    "type": "number"
                  },
                  "endSeconds": {
                    "type": "number"
                  }
                },
                "additionalProperties": false,
                "description": "Time range (seconds) to clip out of a recording: 0 <= start < end."
              }
            }
          },
          "description": "Time range (seconds) to clip out of a recording: 0 <= start < end."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Clip job accepted (Mux asset id + preparing status).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Clip job accepted (Mux asset id + preparing status)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/content": {
      "get": {
        "summary": "Get post-event content",
        "tags": [
          "media"
        ],
        "description": "Fetch all post-event derivations and generated media for an event, aggregated for the host dashboard.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "All post-event derivations (recap, themes, Q&A, quotes, resources, action items, key moments) plus generated media for an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "All post-event derivations (recap, themes, Q&A, quotes, resources, action items, key moments) plus generated media for an event."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/derivations": {
      "post": {
        "summary": "Run post-event derivations",
        "tags": [
          "media"
        ],
        "description": "Run the Gemini derivation fan-out (recap/Q&A/themes/…) over the event's stored transcript, gated by its event-type profile. Fills gaps by default; pass ?force=true to regenerate existing derivations. Pass ?only=quotes,key_moments to regenerate specific types in isolation, ignoring the profile. Also runs automatically after transcription when the pipeline is enabled.",
        "parameters": [
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "force",
            "required": false
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "only",
            "required": false,
            "description": "Comma-separated derivation types to regenerate in isolation (e.g. \"quotes,key_moments\"), regardless of the event-type profile. Omit to run the full profile. Unknown types are rejected with a 400."
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/resolve-speakers": {
      "post": {
        "summary": "Resolve transcript speakers",
        "tags": [
          "media"
        ],
        "description": "Map the anonymous diarization labels on the stored transcript (speaker_0, …) to the real on-stage participants, storing a speaker_map derivation that the content read model applies to quotes + transcript. Prefers matching the durable live-caption ledger by spoken text, falling back to Gemini for the rest. Fills gaps by default; ?force=true re-runs. Also runs automatically before the derivation fan-out.",
        "parameters": [
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "force",
            "required": false
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/clips": {
      "post": {
        "summary": "Cut auto-clips for an event",
        "tags": [
          "media"
        ],
        "description": "Enqueue per-answered-question clips cut from the recap (needs a qa_answers derivation + a gs:// recap recording). Returns how many clips were queued.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/quote-cards": {
      "post": {
        "summary": "Render quote cards for an event",
        "tags": [
          "media"
        ],
        "description": "Render pull-quote card images from the quotes derivation (idea H). Returns how many cards were queued.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/embeddings": {
      "post": {
        "summary": "Embed an event transcript",
        "tags": [
          "media"
        ],
        "description": "Generate + store transcript-chunk embeddings for semantic search, replacing any existing set for the event (safe to re-run). Returns rows written.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/reprocess": {
      "post": {
        "summary": "Re-run the post-event pipeline",
        "tags": [
          "media"
        ],
        "description": "Re-run derivations only ('insights', synchronous) or re-transcribe and re-run the full chain ('full', forced, enqueued). Regenerates content that already exists.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scope"
                ],
                "properties": {
                  "scope": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "insights"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "full"
                        ]
                      }
                    ],
                    "description": "'insights' regenerates the Gemini derivations (recap, themes, quotes, key moments, Q&A) from the existing transcript, synchronously. 'full' re-transcribes the recording and re-runs the whole chain (derivations, clips, quote cards, embeddings), enqueued."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Reprocess accepted (sync summary or queued).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Reprocess accepted (sync summary or queued)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/replay-status": {
      "get": {
        "summary": "Post-event pipeline status",
        "tags": [
          "media"
        ],
        "description": "Per-stage status of the post-event content pipeline (merge, transcription, derivations, clips, quote cards, embeddings, summary) plus a top-line state for the dashboard replay banner.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Per-stage post-event pipeline status for the replay banner.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "overall",
                    "hasRecording",
                    "hasTranscript",
                    "stages"
                  ],
                  "properties": {
                    "overall": {
                      "type": "string",
                      "description": "ready | running | failed | idle"
                    },
                    "hasRecording": {
                      "type": "boolean"
                    },
                    "hasTranscript": {
                      "type": "boolean"
                    },
                    "stages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "key",
                          "label",
                          "group",
                          "status",
                          "error",
                          "dependsOn"
                        ],
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "group": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "error": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "dependsOn": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  },
                  "additionalProperties": false,
                  "description": "Per-stage post-event pipeline status for the replay banner."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/share-email": {
      "post": {
        "summary": "Email the replay link",
        "tags": [
          "media"
        ],
        "description": "Send the event's public replay link (with recap teaser) to up to 10 recipients. In log-adapter/dev mode the link is echoed instead of sent.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "to"
                ],
                "properties": {
                  "to": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "minItems": 1,
                    "maxItems": 10,
                    "description": "Recipient email addresses (max 10 per send)."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Emails sent (count); replay link echoed in dev/log-adapter mode.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Emails sent (count); replay link echoed in dev/log-adapter mode."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/search": {
      "get": {
        "summary": "Semantic search a transcript",
        "tags": [
          "media"
        ],
        "description": "Rank transcript cues against ?q= by cosine similarity (needs embeddings).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/v1/events/{id}/table-summaries": {
      "get": {
        "summary": "Per-breakout-table AI notes",
        "tags": [
          "media"
        ],
        "description": "Every breakout table of the event with its notes, stats and badges, plus the cross-table synthesis. `hasTables` is false for an event that ran no breakout phase, which is how the dashboard panel knows to hide itself.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "hasTables",
                    "stage",
                    "anyShared",
                    "tables",
                    "rollup"
                  ],
                  "properties": {
                    "hasTables": {
                      "type": "boolean"
                    },
                    "stage": {
                      "type": "string",
                      "description": "pending | running | done | failed | skipped"
                    },
                    "anyShared": {
                      "type": "boolean"
                    },
                    "tables": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "roomId",
                          "number",
                          "label",
                          "phaseOrdinal",
                          "status",
                          "summary",
                          "stats",
                          "people",
                          "tableBadges",
                          "attributionWarning",
                          "engagement",
                          "source",
                          "generatedAt",
                          "sharedAt",
                          "reachable"
                        ],
                        "properties": {
                          "roomId": {
                            "type": "string"
                          },
                          "number": {
                            "type": "integer"
                          },
                          "label": {
                            "type": "string"
                          },
                          "phaseOrdinal": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string",
                            "description": "ready | thin | pending"
                          },
                          "summary": {
                            "anyOf": [
                              {
                                "type": "object",
                                "required": [
                                  "tldr",
                                  "themes",
                                  "ideas",
                                  "questions",
                                  "perQuestion"
                                ],
                                "properties": {
                                  "tldr": {
                                    "type": "string"
                                  },
                                  "themes": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "required": [
                                        "title",
                                        "summary"
                                      ],
                                      "properties": {
                                        "title": {
                                          "type": "string"
                                        },
                                        "summary": {
                                          "type": "string"
                                        }
                                      },
                                      "additionalProperties": true
                                    }
                                  },
                                  "ideas": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "questions": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "perQuestion": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "required": [
                                        "ordinal",
                                        "question",
                                        "discussed",
                                        "summary"
                                      ],
                                      "properties": {
                                        "ordinal": {
                                          "type": "integer"
                                        },
                                        "question": {
                                          "type": "string"
                                        },
                                        "discussed": {
                                          "type": "boolean"
                                        },
                                        "summary": {
                                          "type": "string"
                                        }
                                      },
                                      "additionalProperties": true
                                    }
                                  }
                                },
                                "additionalProperties": true
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "stats": {
                            "anyOf": [
                              {
                                "type": "object",
                                "required": [
                                  "totalWords",
                                  "totalTurns",
                                  "totalQuestions",
                                  "promptsCovered",
                                  "promptsTotal",
                                  "lifetimeSeconds",
                                  "headcount",
                                  "speakers",
                                  "rosterReconstructed"
                                ],
                                "properties": {
                                  "totalWords": {
                                    "type": "integer"
                                  },
                                  "totalTurns": {
                                    "type": "integer"
                                  },
                                  "totalQuestions": {
                                    "type": "integer"
                                  },
                                  "promptsCovered": {
                                    "type": "integer"
                                  },
                                  "promptsTotal": {
                                    "type": "integer"
                                  },
                                  "lifetimeSeconds": {
                                    "type": "integer"
                                  },
                                  "headcount": {
                                    "type": "integer"
                                  },
                                  "speakers": {
                                    "type": "integer"
                                  },
                                  "rosterReconstructed": {
                                    "type": "boolean"
                                  }
                                },
                                "additionalProperties": true
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "people": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "userId",
                                "name",
                                "words",
                                "turns",
                                "spanSeconds",
                                "questionsAsked",
                                "badges"
                              ],
                              "properties": {
                                "userId": {
                                  "type": "string"
                                },
                                "name": {
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "words": {
                                  "type": "integer"
                                },
                                "turns": {
                                  "type": "integer"
                                },
                                "spanSeconds": {
                                  "type": "integer"
                                },
                                "questionsAsked": {
                                  "type": "integer"
                                },
                                "badges": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "id",
                                      "name",
                                      "description",
                                      "tier",
                                      "icon"
                                    ],
                                    "properties": {
                                      "id": {
                                        "type": "string"
                                      },
                                      "name": {
                                        "type": "string"
                                      },
                                      "description": {
                                        "type": "string"
                                      },
                                      "tier": {
                                        "type": "integer"
                                      },
                                      "icon": {
                                        "type": "string"
                                      },
                                      "glyph": {
                                        "type": "string"
                                      }
                                    },
                                    "additionalProperties": true
                                  }
                                }
                              },
                              "additionalProperties": true
                            }
                          },
                          "tableBadges": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "id",
                                "name",
                                "description",
                                "tier",
                                "icon"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "description": {
                                  "type": "string"
                                },
                                "tier": {
                                  "type": "integer"
                                },
                                "icon": {
                                  "type": "string"
                                },
                                "glyph": {
                                  "type": "string"
                                }
                              },
                              "additionalProperties": true
                            }
                          },
                          "attributionWarning": {
                            "type": "boolean"
                          },
                          "engagement": {
                            "type": "object",
                            "required": [
                              "score",
                              "level",
                              "signals"
                            ],
                            "properties": {
                              "score": {
                                "type": "integer"
                              },
                              "level": {
                                "type": "string",
                                "description": "none | low | moderate | high"
                              },
                              "signals": {
                                "type": "object",
                                "required": [
                                  "pace",
                                  "participation",
                                  "balance",
                                  "coverage",
                                  "sustain"
                                ],
                                "properties": {
                                  "pace": {
                                    "anyOf": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "participation": {
                                    "anyOf": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "balance": {
                                    "anyOf": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "coverage": {
                                    "anyOf": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "sustain": {
                                    "anyOf": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "additionalProperties": true
                              }
                            },
                            "additionalProperties": true
                          },
                          "source": {
                            "type": "object",
                            "required": [
                              "cues",
                              "words",
                              "speakers"
                            ],
                            "properties": {
                              "cues": {
                                "type": "integer"
                              },
                              "words": {
                                "type": "integer"
                              },
                              "speakers": {
                                "type": "integer"
                              }
                            },
                            "additionalProperties": true
                          },
                          "generatedAt": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sharedAt": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "reachable": {
                            "type": "integer"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "rollup": {
                      "anyOf": [
                        {
                          "type": "object",
                          "required": [
                            "rollup",
                            "tablesCovered",
                            "tablesTotal",
                            "generatedAt",
                            "stale"
                          ],
                          "properties": {
                            "rollup": {
                              "type": "object",
                              "required": [
                                "tldr",
                                "consensus",
                                "divergence",
                                "standoutIdeas",
                                "openQuestions",
                                "perQuestion"
                              ],
                              "properties": {
                                "tldr": {
                                  "type": "string"
                                },
                                "consensus": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "divergence": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "point",
                                      "positions"
                                    ],
                                    "properties": {
                                      "point": {
                                        "type": "string"
                                      },
                                      "positions": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      }
                                    },
                                    "additionalProperties": true
                                  }
                                },
                                "standoutIdeas": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "idea",
                                      "tables"
                                    ],
                                    "properties": {
                                      "idea": {
                                        "type": "string"
                                      },
                                      "tables": {
                                        "type": "array",
                                        "items": {
                                          "type": "integer"
                                        }
                                      }
                                    },
                                    "additionalProperties": true
                                  }
                                },
                                "openQuestions": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "perQuestion": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "ordinal",
                                      "question",
                                      "synthesis"
                                    ],
                                    "properties": {
                                      "ordinal": {
                                        "type": "integer"
                                      },
                                      "question": {
                                        "type": "string"
                                      },
                                      "synthesis": {
                                        "type": "string"
                                      }
                                    },
                                    "additionalProperties": true
                                  }
                                }
                              },
                              "additionalProperties": true
                            },
                            "tablesCovered": {
                              "type": "integer"
                            },
                            "tablesTotal": {
                              "type": "integer"
                            },
                            "generatedAt": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          },
                          "additionalProperties": true
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Generate per-table notes",
        "tags": [
          "media"
        ],
        "description": "Host-only. Runs inline for a targeted re-run of a few tables; queues a Cloud Task for a whole event, so the request returns before the model calls do.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "maxItems": 200
                  },
                  "force": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "queued"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "queued": {
                      "type": "boolean"
                    },
                    "tables": {
                      "type": "integer"
                    },
                    "ran": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "thin": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "failed": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "deferred": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/tables/{roomId}/insights": {
      "get": {
        "summary": "One table’s conversation insights",
        "tags": [
          "media"
        ],
        "description": "Host-only. Talk-time distribution per participant, time spent on each discussion question, and an engagement band — all derived from the table’s live captions at read time, so a table with no AI notes (thin, or not written up yet) still reports honestly. Talk time is ESTIMATED from caption length: a breakout table is never recorded, so no measured duration exists.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "roomId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "table",
                    "engagement",
                    "talk",
                    "timeline",
                    "source",
                    "rosterReconstructed",
                    "approximateWindow"
                  ],
                  "properties": {
                    "table": {
                      "type": "object",
                      "required": [
                        "roomId",
                        "number",
                        "label",
                        "phaseOrdinal"
                      ],
                      "properties": {
                        "roomId": {
                          "type": "string"
                        },
                        "number": {
                          "type": "integer"
                        },
                        "label": {
                          "type": "string"
                        },
                        "phaseOrdinal": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    },
                    "engagement": {
                      "type": "object",
                      "required": [
                        "score",
                        "level",
                        "signals"
                      ],
                      "properties": {
                        "score": {
                          "type": "integer"
                        },
                        "level": {
                          "type": "string",
                          "description": "none | low | moderate | high"
                        },
                        "signals": {
                          "type": "object",
                          "required": [
                            "pace",
                            "participation",
                            "balance",
                            "coverage",
                            "sustain"
                          ],
                          "properties": {
                            "pace": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "participation": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "balance": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "coverage": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "sustain": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "additionalProperties": true
                        }
                      },
                      "additionalProperties": true
                    },
                    "talk": {
                      "type": "object",
                      "required": [
                        "people",
                        "unassignedSeconds",
                        "totalTalkSeconds",
                        "lifetimeSeconds",
                        "uncapturedSeconds"
                      ],
                      "properties": {
                        "people": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "userId",
                              "name",
                              "talkSeconds",
                              "share",
                              "words",
                              "turns",
                              "dwellSeconds",
                              "observer"
                            ],
                            "properties": {
                              "userId": {
                                "type": "string"
                              },
                              "name": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "talkSeconds": {
                                "type": "number"
                              },
                              "share": {
                                "type": "number"
                              },
                              "words": {
                                "type": "integer"
                              },
                              "turns": {
                                "type": "integer"
                              },
                              "dwellSeconds": {
                                "type": "number"
                              },
                              "observer": {
                                "type": "boolean"
                              }
                            },
                            "additionalProperties": true
                          }
                        },
                        "unassignedSeconds": {
                          "type": "number"
                        },
                        "totalTalkSeconds": {
                          "type": "number"
                        },
                        "lifetimeSeconds": {
                          "type": "number"
                        },
                        "uncapturedSeconds": {
                          "type": "number"
                        }
                      },
                      "additionalProperties": true
                    },
                    "timeline": {
                      "type": "object",
                      "required": [
                        "segments",
                        "accountedSeconds",
                        "lifetimeSeconds",
                        "questionsReached",
                        "questionsTotal"
                      ],
                      "properties": {
                        "segments": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "kind",
                              "promptId",
                              "ordinal",
                              "body",
                              "reached",
                              "startSeconds",
                              "seconds",
                              "share",
                              "cues",
                              "words",
                              "speakers"
                            ],
                            "properties": {
                              "kind": {
                                "type": "string",
                                "description": "question | before-questions | open-conversation"
                              },
                              "promptId": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "ordinal": {
                                "anyOf": [
                                  {
                                    "type": "integer"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "body": {
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "reached": {
                                "type": "boolean"
                              },
                              "startSeconds": {
                                "anyOf": [
                                  {
                                    "type": "number"
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "seconds": {
                                "type": "number"
                              },
                              "share": {
                                "type": "number"
                              },
                              "cues": {
                                "type": "integer"
                              },
                              "words": {
                                "type": "integer"
                              },
                              "speakers": {
                                "type": "integer"
                              }
                            },
                            "additionalProperties": true
                          }
                        },
                        "accountedSeconds": {
                          "type": "number"
                        },
                        "lifetimeSeconds": {
                          "type": "number"
                        },
                        "questionsReached": {
                          "type": "integer"
                        },
                        "questionsTotal": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    },
                    "source": {
                      "type": "object",
                      "required": [
                        "cues",
                        "words",
                        "speakers"
                      ],
                      "properties": {
                        "cues": {
                          "type": "integer"
                        },
                        "words": {
                          "type": "integer"
                        },
                        "speakers": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    },
                    "rosterReconstructed": {
                      "type": "boolean"
                    },
                    "approximateWindow": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/tables/{roomId}/transcript": {
      "get": {
        "summary": "One table’s full transcript",
        "tags": [
          "media"
        ],
        "description": "Host-only, and never shared with participants: the notes they receive are deliberately anonymous, because on-device captions frequently misattribute who spoke. This names people so a host can read what happened at a table they ran. Echo-deduped, and capped — `truncated` says when a table ran past the cap.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "in": "path",
            "name": "roomId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "table",
                    "lines",
                    "questions",
                    "total",
                    "truncated",
                    "echoesHidden",
                    "approximateWindow"
                  ],
                  "properties": {
                    "table": {
                      "type": "object",
                      "required": [
                        "roomId",
                        "number",
                        "label",
                        "phaseOrdinal"
                      ],
                      "properties": {
                        "roomId": {
                          "type": "string"
                        },
                        "number": {
                          "type": "integer"
                        },
                        "label": {
                          "type": "string"
                        },
                        "phaseOrdinal": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "atSeconds",
                          "speaker",
                          "userId",
                          "text",
                          "ordinal"
                        ],
                        "properties": {
                          "atSeconds": {
                            "type": "integer"
                          },
                          "speaker": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "userId": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "text": {
                            "type": "string"
                          },
                          "ordinal": {
                            "anyOf": [
                              {
                                "type": "integer"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "questions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "ordinal",
                          "body"
                        ],
                        "properties": {
                          "ordinal": {
                            "type": "integer"
                          },
                          "body": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "echoesHidden": {
                      "type": "integer"
                    },
                    "approximateWindow": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/table-summaries/rollup": {
      "post": {
        "summary": "Re-run the cross-table synthesis",
        "tags": [
          "media"
        ],
        "description": "Host-only. Refreshes the \"across all tables\" overview — the thing to call when a table has been re-summarised since it was written.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "force": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "queued"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "queued": {
                      "type": "boolean"
                    },
                    "tables": {
                      "type": "integer"
                    },
                    "ran": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "thin": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "failed": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "deferred": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/table-summaries/share": {
      "post": {
        "summary": "Email each table its own notes",
        "tags": [
          "media"
        ],
        "description": "Host-only. Emails every reachable participant a personal, revocable link to the notes for the table(s) they were at — never another table’s. Recipients are derived server-side; the caller cannot name them.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "maxItems": 200
                  },
                  "resend": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "sent",
                    "unreachable",
                    "tables"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "sent": {
                      "type": "integer"
                    },
                    "unreachable": {
                      "type": "integer"
                    },
                    "tables": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "roomId",
                          "number",
                          "sent"
                        ],
                        "properties": {
                          "roomId": {
                            "type": "string"
                          },
                          "number": {
                            "type": "integer"
                          },
                          "sent": {
                            "type": "integer"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "sampleUrl": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/table-summaries/revoke": {
      "post": {
        "summary": "Stop sharing table notes",
        "tags": [
          "media"
        ],
        "description": "Host-only. Clears `shared_at`, so every emailed link stops working immediately. Not retroactive: the emails themselves stay in inboxes, including the excerpt they quote.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "maxItems": 200
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "revoked"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "revoked": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/transcribe": {
      "post": {
        "summary": "Transcribe an event recording",
        "tags": [
          "transcripts"
        ],
        "description": "Post-event batch transcription of a GCS audio object via the TranscriptionPort. Stores editable cues and materialises the transcript asset + JSON/VTT derivatives at the documented paths.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sourceUri": {
                    "type": "string"
                  },
                  "roomId": {
                    "type": "string"
                  },
                  "force": {
                    "type": "boolean"
                  },
                  "sync": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false,
                "description": "Batch transcription request."
              }
            }
          },
          "description": "Batch transcription request."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Transcription result (cue count + asset coordinates).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Transcription result (cue count + asset coordinates)."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/transcript": {
      "get": {
        "summary": "Get an event transcript",
        "tags": [
          "transcripts"
        ],
        "description": "Fetch an event’s stored transcript cues, earliest first.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Stored transcript cues for an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "cues"
                  ],
                  "properties": {
                    "cues": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true,
                  "description": "Stored transcript cues for an event."
                }
              }
            }
          }
        }
      }
    },
    "/v1/transcript-cues/{id}": {
      "patch": {
        "summary": "Edit a transcript cue",
        "tags": [
          "transcripts"
        ],
        "description": "Admin correction of a stored cue’s text and/or speaker. Flips `edited` so re-transcription won’t clobber corrections.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "speaker": {
                    "type": "string"
                  }
                },
                "additionalProperties": false,
                "description": "Admin cue correction."
              }
            }
          },
          "description": "Admin cue correction."
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Transcript cue resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Transcript cue resource."
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/uploads": {
      "post": {
        "summary": "Request an image upload URL",
        "tags": [
          "assets"
        ],
        "description": "Mint a short-lived signed URL for uploading an image (stage design background/logo) straight to the assets bucket. PUT the file bytes to uploadUrl with requiredHeaders, then call confirm.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "contentType"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "contentType": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "image/png"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "image/jpeg"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "image/webp"
                        ]
                      }
                    ],
                    "description": "MIME type of the image being uploaded."
                  },
                  "purpose": {
                    "type": "string",
                    "maxLength": 60
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "assetId",
                    "uploadUrl",
                    "url",
                    "requiredHeaders"
                  ],
                  "properties": {
                    "assetId": {
                      "type": "string"
                    },
                    "uploadUrl": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "requiredHeaders": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/uploads/{assetId}/confirm": {
      "post": {
        "summary": "Confirm an image upload",
        "tags": [
          "assets"
        ],
        "description": "Verify the uploaded object and record it as a photo asset on the event. Idempotent for the same asset id.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "purpose": {
                    "type": "string",
                    "maxLength": 60
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$"
            },
            "in": "path",
            "name": "assetId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "assetId",
                    "url"
                  ],
                  "properties": {
                    "assetId": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/chat-uploads": {
      "post": {
        "summary": "Request a chat file-share upload URL",
        "tags": [
          "chat"
        ],
        "description": "Mint a short-lived signed URL for sharing a file in meeting chat, straight to the assets bucket. PUT the file bytes to uploadUrl with requiredHeaders, then call confirm.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "contentType"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "contentType": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "image/png"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "image/jpeg"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "image/webp"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "image/gif"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/pdf"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/msword"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/vnd.ms-excel"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/vnd.ms-powerpoint"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/vnd.openxmlformats-officedocument.presentationml.presentation"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "text/plain"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "text/csv"
                        ]
                      },
                      {
                        "type": "string",
                        "enum": [
                          "application/zip"
                        ]
                      }
                    ],
                    "description": "MIME type of the file being shared."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "attachmentId",
                    "uploadUrl",
                    "url",
                    "requiredHeaders"
                  ],
                  "properties": {
                    "attachmentId": {
                      "type": "string"
                    },
                    "uploadUrl": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "requiredHeaders": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/chat-uploads/{attachmentId}/confirm": {
      "post": {
        "summary": "Confirm a chat file-share upload",
        "tags": [
          "chat"
        ],
        "description": "Verify the uploaded object and return its metadata to post alongside a chat message. Idempotent for the same attachment id.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$"
            },
            "in": "path",
            "name": "attachmentId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "attachmentId",
                    "url",
                    "name",
                    "contentType",
                    "size"
                  ],
                  "properties": {
                    "attachmentId": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "contentType": {
                      "type": "string"
                    },
                    "size": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "summary": "Register a webhook endpoint",
        "tags": [
          "webhooks"
        ],
        "description": "Register an endpoint to receive HMAC-signed event deliveries. The signing secret is returned once, at creation time.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Endpoint to deliver signed events to."
                  },
                  "eventTypes": {
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "event.published"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "event.started"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "event.ended"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "participant.joined"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "participant.left"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "broadcast.live"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "broadcast.paused"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "recording.ready"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "transcript.ready"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "question.created"
                          ]
                        },
                        {
                          "type": "string",
                          "enum": [
                            "clip.ready"
                          ]
                        }
                      ],
                      "description": "A webhook-deliverable domain event type."
                    },
                    "description": "Event types this endpoint subscribes to (defaults to none)."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook endpoint resource.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": true,
                  "description": "Webhook endpoint resource."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List webhook endpoints",
        "tags": [
          "webhooks"
        ],
        "description": "List the workspace’s registered webhook endpoints (secrets omitted).",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "webhooks"
                  ],
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "summary": "Delete a webhook endpoint",
        "tags": [
          "webhooks"
        ],
        "description": "Remove a registered webhook endpoint.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://api.gathercloud.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ]
}
