{
  "openapi": "3.1.0",
  "info": {
    "title": "VideoApuntes Agent API",
    "version": "1.0.0",
    "description": "Acceso delegado mediante tokens va_. Crea un token en https://videoapuntes.vercel.app/agents. Nunca lo pongas en una URL. Cuota y documentos pertenecen a la cuenta Google que lo autoriza. Todas las operaciones requieren POST y Authorization: Bearer TOKEN. No necesitas apikey de Supabase ni claves propias de Gemini/Groq."
  },
  "servers": [
    {
      "url": "https://qygwonulqiwklqfqvioh.supabase.co/functions/v1/va"
    }
  ],
  "paths": {
    "/status": {
      "post": {
        "operationId": "getStatus",
        "summary": "Identidad, permisos y cuota compartida de la cuenta",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/generate": {
      "post": {
        "operationId": "generateNotes",
        "summary": "Genera apuntes JSON a partir de una transcripcion (permiso process)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transcript": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200000
                  },
                  "duration_sec": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 18000
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "modo": {
                    "type": "string",
                    "enum": [
                      "clase",
                      "reunion",
                      "tutorial",
                      "conferencia",
                      "resumen"
                    ]
                  }
                },
                "required": [
                  "transcript",
                  "duration_sec"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        },
        "description": "Consume una clase y la duracion declarada. No guarda el resultado. No es idempotente: un reintento puede consumir cuota otra vez. En fallos de IA puede haberse consumido la cuota."
      }
    },
    "/begin": {
      "post": {
        "operationId": "beginClass",
        "summary": "Inicia una clase para el flujo de audio de varios pasos (process)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "dur": {
                    "type": "number"
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/consume": {
      "post": {
        "operationId": "consumeTranscriptQuota",
        "summary": "Registra segundos de una transcripcion en el flujo de varios pasos (process)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "dur": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "dur"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/transcribe": {
      "post": {
        "operationId": "transcribeAudio",
        "summary": "Transcribe un fragmento de audio de hasta 20000000 bytes (process)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "segments, duration y quota"
          },
          "401": {
            "description": "Acceso invalido"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "413": {
            "description": "Fragmento demasiado grande"
          },
          "429": {
            "description": "Sin cupo"
          }
        }
      }
    },
    "/summarize": {
      "post": {
        "operationId": "summarizeContent",
        "summary": "Resume contenido Gemini del flujo de varios pasos (process)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contents": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                },
                "required": [
                  "contents"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        },
        "description": "Requiere consumo previo de segundos en la cuenta; para transcripciones usa preferentemente /generate."
      }
    },
    "/docs-list": {
      "post": {
        "operationId": "listDocuments",
        "summary": "Lista los apuntes de la cuenta (documents:read)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "offset": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 100
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/docs-get": {
      "post": {
        "operationId": "getDocument",
        "summary": "Obtiene metadata y payload JSON de un apunte propio (documents:read)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/docs-save": {
      "post": {
        "operationId": "saveDocument",
        "summary": "Guarda un apunte en la cuenta (documents:write)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payload": {
                    "$ref": "#/components/schemas/DocumentPayload"
                  },
                  "duration_sec": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "materia": {
                    "type": "string",
                    "maxLength": 100
                  }
                },
                "required": [
                  "payload"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Documento creado; devuelve document con id y storage_path"
          },
          "400": {
            "description": "Payload invalido"
          },
          "401": {
            "description": "Acceso invalido"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "413": {
            "description": "Maximo 12 MiB por solicitud"
          }
        }
      }
    },
    "/docs-delete": {
      "post": {
        "operationId": "deleteDocument",
        "summary": "Borra un apunte propio y su archivo (documents:write)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/docs-materia": {
      "post": {
        "operationId": "assignSubject",
        "summary": "Asigna materia a apuntes propios (documents:write)",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "materia": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100
                  }
                },
                "required": [
                  "ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/tokens-list": {
      "post": {
        "operationId": "listTokens",
        "summary": "Solo sesion Google: lista metadata sin secretos",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    },
    "/tokens-create": {
      "post": {
        "operationId": "createToken",
        "summary": "Solo sesion Google: crea un token y lo muestra una vez",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "default": 30
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "process",
                        "documents:read",
                        "documents:write"
                      ]
                    },
                    "minItems": 1,
                    "uniqueItems": true
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "token (secreto de una sola visualizacion), id, name, scopes y expires_at"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Sesion invalida"
          },
          "403": {
            "description": "Un agente no puede crear credenciales"
          }
        }
      }
    },
    "/tokens-revoke": {
      "post": {
        "operationId": "revokeToken",
        "summary": "Solo sesion Google: revoca un token propio",
        "security": [
          {
            "AgentToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado JSON"
          },
          "400": {
            "description": "Entrada invalida"
          },
          "401": {
            "description": "Credencial invalida, caducada o revocada"
          },
          "403": {
            "description": "Permiso insuficiente"
          },
          "429": {
            "description": "Cuota agotada"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "AgentToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "va_<64 hex>",
        "description": "Token delegado; los endpoints tokens-* requieren en su lugar el access_token de una sesion Google valida."
      }
    },
    "schemas": {
      "DocumentPayload": {
        "type": "object",
        "properties": {
          "v": {
            "type": "integer",
            "const": 1
          },
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "modo": {
            "type": "string",
            "enum": [
              "clase",
              "reunion",
              "tutorial",
              "conferencia",
              "resumen"
            ]
          },
          "theme": {
            "type": "string",
            "enum": [
              "dark",
              "light"
            ]
          },
          "data": {
            "type": "object",
            "description": "Apuntes estructurados: tldr, resumen_html, temas, glosario, pendientes, quiz, captions y _segments."
          },
          "frames": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "n": {
                  "type": "integer"
                },
                "t": {
                  "type": "number"
                },
                "b64": {
                  "type": "string"
                }
              },
              "required": []
            }
          }
        },
        "required": [
          "data"
        ]
      }
    }
  }
}
