# GENERADO POR motor/openapi/generar-openapi.py — NO SE EDITA A MANO.
#
# Las rutas salen del atributo [HttpTrigger] de cada Function y las
# descripciones del <summary> de XML doc que tienen al lado. Para
# cambiar lo que dice una ruta aqui, se cambia su comentario en el
# codigo y se vuelve a generar. Hay una guarda que falla si este
# fichero no coincide con lo que sale de generar de nuevo.
openapi: 3.0.3
info:
  title: Factuza API
  version: "1.0.0"
  description: >-
    Motor VERI*FACTU de OBTechnologies. Cada factura emitida por aqui nace
    con su registro de facturacion, entra en la cadena de huellas SHA-256
    de su emisor y se remite a la AEAT. La declaracion responsable del
    art. 13 del RD 1007/2023 la firma OBTechnologies.
  contact:
    name: OBTechnologies
    email: hola@factuza.com
    url: https://factuza.com/motor-api/
servers:
  - url: https://func-factuza-prod-obt1.azurewebsites.net/api
    description: Produccion
  - url: https://func-factuza-test-obt1.azurewebsites.net/api
    description: Pruebas (no cuenta ni remite a la AEAT)
components:
  securitySchemes:
    claveApi:
      type: apiKey
      in: header
      name: X-Api-Key
      description: La clave de una maquina. Se crea en el area de clientes.
    usuario:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: El token de una persona (lo que usan la web y la app).
security:
  - claveApi: []
  - usuario: []
paths:
  /aceptaciones:
    post:
      operationId: Aceptar
      summary: "El contrato de encargo de tratamiento, aceptado desde el área."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /borradores:
    get:
      operationId: ListarBorradores
      summary: "Facturas escritas SIN COBERTURA, pendientes de emitir."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /borradores/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    put:
      operationId: GuardarBorrador
      summary: "Sube un borrador."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: DescartarBorrador
      summary: "Facturas escritas SIN COBERTURA, pendientes de emitir."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /borradores/{id}/emitir:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    post:
      operationId: EmitirBorrador
      summary: "Aquí es donde el borrador se vuelve factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /cartera/panel:
    get:
      operationId: PanelCartera
      summary: "El panel de la gestoría: GET /cartera/panel."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /claves-api:
    get:
      operationId: ListarClavesApi
      summary: "Las claves de API de la cuenta (plan Motor API, pieza A1 del 22-ago-2026)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearClaveApi
      summary: "Las claves de API de la cuenta (plan Motor API, pieza A1 del 22-ago-2026)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /claves-api/consumo:
    get:
      operationId: ConsumoApi
      summary: "Lo consumido en el mes en curso, emisor a emisor."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /claves-api/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    delete:
      operationId: RevocarClaveApi
      summary: "Las claves de API de la cuenta (plan Motor API, pieza A1 del 22-ago-2026)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /clientes:
    post:
      operationId: AltaCliente
      summary: "Registro de clientes (tenants) de Factuza con el servicio común de licencias."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /clientes/licencia:
    get:
      operationId: EstadoLicenciaCliente
      summary: "Registro de clientes (tenants) de Factuza con el servicio común de licencias."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /cobros:
    post:
      operationId: RegistrarCobro
      summary: "Registro de cobros (auditoría A4): marcar cobros, aging de pendientes y evaluación de crédito incobrable (art. 80.Cuatro)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /cobros/aging:
    get:
      operationId: AgingCobros
      summary: "Registro de cobros (auditoría A4): marcar cobros, aging de pendientes y evaluación de crédito incobrable (art. 80.Cuatro)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /email/pixel/{trackingId}:
    parameters:
      - name: trackingId
        in: path
        required: true
        schema: { type: string }
    get:
      operationId: PixelEmail
      summary: "Píxel de apertura: registra la apertura y devuelve un PNG 1x1."
      security: []   # abierta a proposito
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /emisor/configuracion:
    get:
      operationId: LeerConfiguracionEmisor
      summary: "Lo que hay guardado ahora mismo."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    put:
      operationId: GuardarConfiguracionEmisor
      summary: "Sección \"Mi negocio\": retención IRPF por defecto, criterio de caja, logo, color, IBAN y textos."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /emisor/logo:
    get:
      operationId: LeerLogoEmisor
      summary: "El logo, en binario."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /emisor/plantillas/{n}/muestra:
    parameters:
      - name: n
        in: path
        required: true
        schema: { type: integer }
    get:
      operationId: MuestraDePlantilla
      summary: "Una factura de muestra con una plantilla concreta, para verla antes de elegirla."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /emisores:
    get:
      operationId: ListarEmisores
      summary: "La cartera de emisores de un cliente."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: AnadirEmisor
      summary: "La cartera de emisores de un cliente."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /exportar/gestoria:
    get:
      operationId: ExportarGestoria
      summary: "El envío al asesor: un ZIP con el trimestre entero dentro."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /exportar/registros:
    get:
      operationId: ExportarRegistros
      summary: "LA EXPORTACIÓN DE LOS REGISTROS DE FACTURACIÓN (art. 10 del RD 1007/2023)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas:
    get:
      operationId: ListarFacturas
      summary: "El histórico: «enséñame mis facturas»."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: EmitirFactura
      summary: "Emisión (semana 2 del plan de obra): recibe los datos de la factura, construye el registro con su huella encadenada y lo deja listo para la remisión."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/detallada:
    post:
      operationId: EmitirFacturaDetallada
      summary: "Emisión (semana 2 del plan de obra): recibe los datos de la factura, construye el registro con su huella encadenada y lo deja listo para la remisión."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/email:
    post:
      operationId: EnviarFacturaEmail
      summary: "Envío de facturas por email (ACS) y píxel de seguimiento de apertura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    get:
      operationId: VerFactura
      summary: "El histórico: «enséñame mis facturas»."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/{id}/anular:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: AnularFactura
      summary: "Deshacer una factura mal emitida."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/{id}/email:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: EnviarFacturaPorCorreo
      summary: "El papel de la factura: descargarlo y mandarlo."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/{id}/pdf:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    get:
      operationId: PdfDeLaFactura
      summary: "El papel de la factura: descargarlo y mandarlo."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /facturas/{id}/rectificar:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: RectificarFactura
      summary: "Emite una rectificativa que corrige a la factura indicada."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /gastos:
    get:
      operationId: ListarGastos
      summary: "Gastos deducibles: la idea principal del producto."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearGasto
      summary: "Gastos deducibles: la idea principal del producto."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /gastos/{id}/descartar:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: DescartarGasto
      summary: "Gastos deducibles: la idea principal del producto."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /gastos/{id}/validar:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: ValidarGasto
      summary: "Gastos deducibles: la idea principal del producto."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /maestras/destinatarios:
    get:
      operationId: ListarDestinatarios
      summary: "Tablas maestras del emisor: destinatarios y servicios."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearDestinatario
      summary: "Tablas maestras del emisor: destinatarios y servicios."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /maestras/destinatarios/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    put:
      operationId: ActualizarDestinatario
      summary: "Tablas maestras del emisor: destinatarios y servicios."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /maestras/servicios:
    get:
      operationId: ListarServicios
      summary: "Tablas maestras del emisor: destinatarios y servicios."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearServicio
      summary: "Tablas maestras del emisor: destinatarios y servicios."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /maestras/servicios/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    put:
      operationId: ActualizarServicio
      summary: "Cambiar un servicio del catalogo."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: RetirarServicio
      summary: "Retirar un servicio."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /mi-cuenta:
    get:
      operationId: MiCuenta
      summary: "«¿Quién soy y qué puedo ver?» — la pieza que faltaba entre el login y los datos."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /mi-gestoria:
    get:
      operationId: MiGestoria
      summary: "La relación con la asesoría, vista por el DUEÑO del emisor (022)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /mi-gestoria/{relacionId}:
    parameters:
      - name: relacionId
        in: path
        required: true
        schema: { type: integer }
    put:
      operationId: CambiarRolGestoria
      summary: "La relación con la asesoría, vista por el DUEÑO del emisor (022)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: DejarGestoria
      summary: "La relación con la asesoría, vista por el DUEÑO del emisor (022)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /modelos/{modelo}:
    parameters:
      - name: modelo
        in: path
        required: true
        schema: { type: string }
    get:
      operationId: BorradorModelo
      summary: "Borradores de modelos fiscales (ADR-001): SOLO descarga, nunca presentación."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /newsletter:
    post:
      operationId: ApuntarseAlBoletin
      summary: "Apuntarse."
      security: []   # abierta a proposito
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /newsletter/baja:
    get:
      operationId: BajaBoletin
      summary: "Darse de baja."
      security: []   # abierta a proposito
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /newsletter/confirmar:
    get:
      operationId: ConfirmarBoletin
      summary: "Confirmar, desde el enlace del correo."
      security: []   # abierta a proposito
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /ocr/analizar:
    post:
      operationId: AnalizarDocumento
      summary: "OCR con el Document Intelligence ya desplegado por OBT (ADR-002)."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /pagos/checkout:
    post:
      operationId: CrearCheckout
      summary: "Pagos con la cuenta Stripe que OBT ya usa para el chatbot."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /pagos/confirmar:
    post:
      operationId: ConfirmarPago
      summary: "EL ESLABÓN QUE CONVIERTE UN PAGO EN UNA CUENTA. POST /api/pagos/confirmar { \"session\": \"cs_…\" } Hasta el 20-ago-2026 este eslabón NO EXISTÍA: Stripe cobraba y devolvía al comprador a /alta/ok, que era un 404, y ninguna pieza —ni webhook, ni lectura de sesión— creaba nada."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /pioneros:
    get:
      operationId: CupoPioneros
      summary: "Lo que quedan, para la portada."
      security: []   # abierta a proposito
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: ApuntarCupoPioneros
      summary: "El recuento que manda el flujo de Power Automate."
      security: []   # secreto compartido en cabecera, no token
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas:
    get:
      operationId: ListarProformas
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    get:
      operationId: VerProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    put:
      operationId: ActualizarProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: BorrarProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas/{id}/convertir:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: ConvertirProforma
      summary: "Aquí es donde la oferta se vuelve real."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas/{id}/email:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: EnviarProformaPorCorreo
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas/{id}/estado:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    post:
      operationId: CambiarEstadoProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /proformas/{id}/pdf:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    get:
      operationId: PdfDeLaProforma
      summary: "Presupuestos y proformas: el paso ANTES de la factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /recurrentes:
    get:
      operationId: ListarRecurrentes
      summary: "Facturas que se repiten: la cuota mensual, el mantenimiento trimestral."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearRecurrente
      summary: "Facturas que se repiten: la cuota mensual, el mantenimiento trimestral."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /recurrentes/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    put:
      operationId: ActualizarRecurrente
      summary: "Facturas que se repiten: la cuota mensual, el mantenimiento trimestral."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: DesactivarRecurrente
      summary: "Facturas que se repiten: la cuota mensual, el mantenimiento trimestral."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /recurrentes/{id}/emitir:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    post:
      operationId: EmitirRecurrente
      summary: "Emite de verdad el periodo indicado."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /recurrentes/{id}/pendientes:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: string }
    get:
      operationId: PendientesRecurrente
      summary: "Qué periodos tocaban y todavía no han salido, con su atraso."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /resumen:
    get:
      operationId: ResumenNegocio
      summary: "Panel de inicio (mini dashboard): GET /api/resumen Facturado del año, comparación honesta con el mismo periodo del año anterior, trimestre en curso, pendiente de cobro y barras mensuales."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /series:
    get:
      operationId: ListarSeries
      summary: "Series de facturación: de dónde sale el número de cada factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    post:
      operationId: CrearSerie
      summary: "Series de facturación: de dónde sale el número de cada factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /series/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    put:
      operationId: ActualizarSerie
      summary: "Series de facturación: de dónde sale el número de cada factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: DesactivarSerie
      summary: "Series de facturación: de dónde sale el número de cada factura."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /soporte/mis-tickets:
    get:
      operationId: MisTickets
      summary: "«Mis tickets de soporte», para el área de clientes."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /usuarios:
    get:
      operationId: ListarUsuarios
      summary: "Quién tiene acceso a la cuenta."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /usuarios/invitaciones:
    post:
      operationId: InvitarUsuario
      summary: "Quién tiene acceso a la cuenta."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /usuarios/invitaciones/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    delete:
      operationId: RevocarInvitacion
      summary: "Quién tiene acceso a la cuenta."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /usuarios/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema: { type: integer }
    patch:
      operationId: CambiarUsuario
      summary: "Quién tiene acceso a la cuenta."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
  /webhook:
    get:
      operationId: VerWebhook
      summary: "EL WEBHOOK DE ESTADO AEAT: donde avisar cuando la AEAT conteste."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    put:
      operationId: GuardarWebhook
      summary: "EL WEBHOOK DE ESTADO AEAT: donde avisar cuando la AEAT conteste."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
    delete:
      operationId: BorrarWebhook
      summary: "EL WEBHOOK DE ESTADO AEAT: donde avisar cuando la AEAT conteste."
      responses:
        "200": { description: Correcto }
        "401": { description: Sin credencial valida }
        "403": { description: La credencial no alcanza para esto }
