{
  "openapi": "3.1.0",
  "info": {
    "title": "Optiverse External API",
    "version": "1.1.0",
    "description": "Programmatic access to your meeting records, transcripts, summaries, topics, and full-text search.",
    "contact": {
      "email": "support@optiverse.ai"
    }
  },
  "servers": [
    {
      "url": "https://api.optiverse.ai/external-api",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key starting with `optiuser_v1_`"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string", "example": "AUTH001" },
              "message": { "type": "string", "example": "Missing authorization header" }
            },
            "required": ["code", "message"]
          }
        }
      },
      "Attendee": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "email": { "type": "string", "format": "email" }
        }
      },
      "MeetingRecord": {
        "type": "object",
        "properties": {
          "recordId": { "type": "string", "format": "uuid" },
          "role": { "type": "string" },
          "ownerEmail": { "type": "string", "format": "email" },
          "meetingTitle": { "type": "string", "nullable": true },
          "startDate": { "type": "string", "format": "date-time", "nullable": true },
          "endDate": { "type": "string", "format": "date-time", "nullable": true },
          "attendees": { "type": "array", "items": { "$ref": "#/components/schemas/Attendee" } },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "ProtocolTemplate": {
        "type": "object",
        "properties": {
          "protocolId": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "summaryType": { "type": "string", "enum": ["structured", "unstructured"] },
          "managedBy": { "type": "string", "enum": ["optiverse", "user"] },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "StructuredSection": {
        "type": "object",
        "properties": {
          "title": { "type": "string" },
          "question": { "type": "string" },
          "answerType": { "type": "string" },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "answer": { "type": "string" },
                "referenceIds": { "type": "array", "items": { "type": "integer" } }
              }
            }
          }
        }
      },
      "StructuredSummary": {
        "type": "object",
        "properties": {
          "recordId": { "type": "string", "format": "uuid" },
          "createdAt": { "type": "string", "format": "date-time" },
          "sections": { "type": "array", "items": { "$ref": "#/components/schemas/StructuredSection" } }
        }
      },
      "UnstructuredSummary": {
        "type": "object",
        "properties": {
          "recordId": { "type": "string", "format": "uuid" },
          "createdAt": { "type": "string", "format": "date-time" },
          "summary": { "type": "string", "description": "Markdown content" }
        }
      },
      "Topic": {
        "type": "object",
        "properties": {
          "topic": { "type": "string" },
          "description": { "type": "string", "nullable": true }
        }
      },
      "MeetingTopics": {
        "type": "object",
        "properties": {
          "recordId": { "type": "string", "format": "uuid" },
          "meetingTitle": { "type": "string", "nullable": true },
          "meetingDate": { "type": "string", "format": "date-time", "nullable": true },
          "attendees": { "type": "array", "items": { "$ref": "#/components/schemas/Attendee" } },
          "topics": { "type": "array", "items": { "$ref": "#/components/schemas/Topic" } }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "recordId": { "type": "string", "format": "uuid" },
          "speakerLabel": { "type": "string" },
          "sentence": { "type": "string" },
          "sentenceIndex": { "type": "integer" }
        }
      }
    }
  },
  "paths": {
    "/v1/list-records": {
      "get": {
        "summary": "List Meeting Records",
        "description": "Retrieve a paginated list of meeting records accessible to your API key.",
        "tags": ["Meetings"],
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } },
          { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date-time" } }
        ],
        "responses": {
          "200": {
            "description": "List of meeting records",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/MeetingRecord" } },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "total": { "type": "integer" },
                        "limit": { "type": "integer" },
                        "offset": { "type": "integer" },
                        "hasMore": { "type": "boolean" }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/transcript/{recordId}": {
      "get": {
        "summary": "Get Meeting Transcript",
        "description": "Retrieve the full transcript for a specific meeting record.",
        "tags": ["Meetings"],
        "parameters": [
          { "name": "recordId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "Meeting transcript",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": {
                      "type": "object",
                      "properties": {
                        "recordId": { "type": "string", "format": "uuid" },
                        "metadata": {
                          "type": "object",
                          "properties": {
                            "meetingTitle": { "type": "string", "nullable": true },
                            "startDate": { "type": "string", "format": "date-time", "nullable": true },
                            "endDate": { "type": "string", "format": "date-time", "nullable": true },
                            "attendees": { "type": "array", "items": { "$ref": "#/components/schemas/Attendee" } }
                          }
                        },
                        "transcript": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid UUID format", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "Not found or access denied", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/protocol-templates": {
      "get": {
        "summary": "List Protocol Templates",
        "description": "Retrieve all protocol templates on your account. Use `summaryType` to know which summaries endpoint to call.",
        "tags": ["Protocols & Summaries"],
        "responses": {
          "200": {
            "description": "List of protocol templates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/ProtocolTemplate" } }
                  }
                }
              }
            }
          },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/summaries/structured": {
      "get": {
        "summary": "Get Structured Summaries",
        "description": "Fetch JSON summaries (Q&A sections) generated by a structured protocol template.",
        "tags": ["Protocols & Summaries"],
        "parameters": [
          { "name": "protocolId", "in": "query", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "Protocol template ID (must have summaryType: structured)" },
          { "name": "recordId", "in": "query", "schema": { "type": "string", "format": "uuid" }, "description": "Filter to a specific meeting" },
          { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } }
        ],
        "responses": {
          "200": {
            "description": "Structured summaries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/StructuredSummary" } },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "total": { "type": "integer" },
                        "limit": { "type": "integer" },
                        "offset": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/summaries/unstructured": {
      "get": {
        "summary": "Get Unstructured Summaries",
        "description": "Fetch Markdown summaries generated by an unstructured protocol template.",
        "tags": ["Protocols & Summaries"],
        "parameters": [
          { "name": "protocolId", "in": "query", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "Protocol template ID (must have summaryType: unstructured)" },
          { "name": "recordId", "in": "query", "schema": { "type": "string", "format": "uuid" }, "description": "Filter to a specific meeting" },
          { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "minimum": 0, "default": 0 } }
        ],
        "responses": {
          "200": {
            "description": "Unstructured summaries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/UnstructuredSummary" } },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "total": { "type": "integer" },
                        "limit": { "type": "integer" },
                        "offset": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/topics": {
      "get": {
        "summary": "Get Topics",
        "description": "Retrieve topics discussed in meetings, grouped by meeting.",
        "tags": ["Analysis"],
        "parameters": [
          { "name": "recordId", "in": "query", "schema": { "type": "string", "format": "uuid" }, "description": "Filter to a specific meeting" },
          { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 300, "default": 300 }, "description": "Max number of meetings to return" }
        ],
        "responses": {
          "200": {
            "description": "Topics grouped by meeting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/MeetingTopics" } },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "totalMeetings": { "type": "integer" },
                        "totalTopics": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/search": {
      "get": {
        "summary": "Search Transcripts",
        "description": "Full-text keyword search (BM25) across all meeting transcripts you have access to.",
        "tags": ["Analysis"],
        "parameters": [
          { "name": "query", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1 }, "description": "Search keyword or phrase" },
          { "name": "dateFrom", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "dateTo", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/SearchResult" } },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "total": { "type": "integer" },
                        "limit": { "type": "integer" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/upload/request-url": {
      "post": {
        "summary": "Request upload URL",
        "description": "Get a presigned URL for direct single-file PUT upload. Supported formats: mp4, webm, mov, mp3, m4a, wav.",
        "operationId": "requestUploadUrl",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["fileName"],
                "properties": {
                  "fileName": { "type": "string", "description": "File name with extension", "example": "meeting.mp3" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "data": {
                      "type": "object",
                      "properties": {
                        "uploadUrl": { "type": "string", "format": "uri", "description": "Presigned PUT URL to upload the file" },
                        "uploadId": { "type": "string", "format": "uuid", "description": "Upload ID to use in the complete call" },
                        "requiredHeaders": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Headers to include in the PUT request" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/v1/upload/complete": {
      "post": {
        "summary": "Complete upload",
        "description": "Confirm the file has been uploaded and trigger transcription processing.",
        "operationId": "uploadComplete",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["uploadId"],
                "properties": {
                  "uploadId": { "type": "string", "format": "uuid", "description": "Upload ID from request-url response" },
                  "title": { "type": "string", "description": "Meeting title (defaults to 'Untitled Upload')" },
                  "protocolId": { "type": "string", "format": "uuid", "nullable": true, "description": "Protocol ID for summarization (defaults to user's default)" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Processing started",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "const": true },
                    "message": { "type": "string", "example": "Processing started" }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Authentication failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    }
  }
}
