openapi: 3.0.3
info:
  title: CRM Pro GECOERP API
  description: API REST oficial y versionada de integración para CRM Pro GECOERP. Permite la sincronización bidireccional de clientes, inventarios, cotizaciones, pedidos, facturación electrónica CFDI 4.0 con el SAT y pipeline de ventas.
  version: 1.0.0
  contact:
    name: Soporte Técnico e Integraciones GECOERP
    url: https://geco-crm.gecoerp.com/api-externa
    email: soporte@gecoerp.com
  license:
    name: Proprietary
    url: https://geco-crm.gecoerp.com/terms
x-api-versioning:
  strategy: URL Path (/api/v1/) and Header Parameter (X-API-Version)
  current_version: v1
  supported_versions:
    - v1
  version_header: X-API-Version
  deprecation_policy:
    policy_description: GECOERP implements a strict Semantic Versioning policy. Deprecated endpoints are announced at least 6 months before retirement and signal deprecation via standard HTTP Deprecation and Sunset (RFC 8594) response headers.
    deprecation_header: Deprecation
    sunset_header: Sunset
    documentation_url: https://geco-crm.gecoerp.com/docs/
servers:
  - url: https://geco-crm.gecoerp.com
    description: Servidor de Producción (v1)
tags:
  - name: Clientes
    description: Gestión de clientes, datos fiscales y saldos
  - name: Productos
    description: Catálogo de productos, servicios, precios y existencias
  - name: Cotizaciones
    description: Generación y seguimiento de cotizaciones comerciales
  - name: Pedidos
    description: Órdenes de venta y estatus de surtido
  - name: Facturas
    description: Emisión y timbrado de facturación CFDI 4.0 con SAT
  - name: Pipeline
    description: Embudo de ventas y oportunidades comerciales
  - name: Marketplace
    description: Feeds y aplets del ecosistema GECOERP
  - name: Autenticación
    description: Inicio de sesión y verificación de credenciales
paths:
  /api/v1/clients:
    get:
      tags: [Clientes]
      summary: Listar clientes (v1)
      description: Obtiene la lista paginada de clientes activos de la empresa.
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: search
          in: query
          description: Filtro por nombre, RFC, email o teléfono
          schema:
            type: string
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Lista de clientes obtenida exitosamente
          headers:
            X-API-Version:
              $ref: '#/components/headers/ApiVersionResponse'
            Vary:
              $ref: '#/components/headers/VaryHeader'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientListResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Clientes]
      summary: Crear cliente (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientInput'
      responses:
        '201':
          description: Cliente creado exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/clients/{id}:
    get:
      tags: [Clientes]
      summary: Obtener cliente por ID (v1)
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      responses:
        '200':
          description: Detalle del cliente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientDetailResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      tags: [Clientes]
      summary: Actualizar cliente (v1)
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientInput'
      responses:
        '200':
          description: Cliente actualizado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/products:
    get:
      tags: [Productos]
      summary: Listar productos (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: search
          in: query
          schema:
            type: string
        - name: category
          in: query
          schema:
            type: string
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Catálogo de productos
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Productos]
      summary: Crear producto (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductInput'
      responses:
        '201':
          description: Producto creado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/products/{id}:
    get:
      tags: [Productos]
      summary: Obtener producto por ID (v1)
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      responses:
        '200':
          description: Detalle del producto
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductDetailResponse'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      tags: [Productos]
      summary: Actualizar producto (v1)
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProductInput'
      responses:
        '200':
          description: Producto actualizado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/quotations:
    get:
      tags: [Cotizaciones]
      summary: Listar cotizaciones (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '200':
          description: Lista de cotizaciones
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuotationListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Cotizaciones]
      summary: Crear cotización (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuotationInput'
      responses:
        '201':
          description: Cotización creada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuotationDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/orders:
    get:
      tags: [Pedidos]
      summary: Listar pedidos (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '200':
          description: Lista de pedidos
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Pedidos]
      summary: Crear pedido (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '201':
          description: Pedido creado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/invoices:
    get:
      tags: [Facturas]
      summary: Listar facturas CFDI 4.0 (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '200':
          description: Lista de facturas emitidas
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Facturas]
      summary: Timbrar factura CFDI 4.0 con el SAT (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '201':
          description: Factura timbrada exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/pipeline:
    get:
      tags: [Pipeline]
      summary: Listar oportunidades comerciales (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '200':
          description: Oportunidades en el embudo
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PipelineListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags: [Pipeline]
      summary: Crear oportunidad en el pipeline (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '201':
          description: Oportunidad creada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PipelineDetailResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/pipeline/stages:
    get:
      tags: [Pipeline]
      summary: Listar etapas del pipeline (v1)
      security:
        - ApiKeyAuth: []
          Timestamp: []
          Nonce: []
          Signature: []
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      responses:
        '200':
          description: Etapas del pipeline
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StageListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /api/v1/auth/login:
    post:
      tags: [Autenticación]
      summary: Iniciar sesión (v1)
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  format: password
      responses:
        '200':
          description: Autenticación exitosa
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthLoginResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  parameters:
    ApiVersionHeader:
      name: X-API-Version
      in: header
      required: false
      description: Versión de la API solicitada. Por defecto v1.
      schema:
        type: string
        default: v1
        enum: [v1]
  headers:
    ApiVersionResponse:
      description: Versión activa de la API que procesó la solicitud.
      schema:
        type: string
        example: v1
    DeprecationHeader:
      description: Fecha o booleano que indica obsolescencia (RFC 8594).
      schema:
        type: string
        example: '@1735689600'
    SunsetHeader:
      description: Fecha límite tras la cual el endpoint dejará de responder (RFC 8594).
      schema:
        type: string
        example: Wed, 31 Dec 2026 23:59:59 GMT
    VaryHeader:
      description: Cabecera de negociación de caché HTTP.
      schema:
        type: string
        example: Accept, Accept-Encoding
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Clave de API pública emitida en el panel de desarrolladores.
    Timestamp:
      type: apiKey
      in: header
      name: x-timestamp
      description: Marca de tiempo Unix actual en milisegundos.
    Nonce:
      type: apiKey
      in: header
      name: x-nonce
      description: Cadena única y aleatoria por solicitud.
    Signature:
      type: apiKey
      in: header
      name: x-signature
      description: Firma HMAC-SHA256 del payload y encabezados calculada con el API Secret.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Token JWT para sesiones interactivas de usuario.
  schemas:
    ProblemDetails:
      type: object
      description: Modelo formal de error tipado conforme a RFC 9457.
      required: [type, title, status, detail, code]
      properties:
        type:
          type: string
          format: uri
          example: https://geco-crm.gecoerp.com/docs/errors/bad-request
        title:
          type: string
          example: Petición Inválida
        status:
          type: integer
          example: 400
        detail:
          type: string
          example: El campo 'name' es requerido.
        instance:
          type: string
          example: /api/v1/clients
        code:
          type: string
          example: MISSING_REQUIRED_FIELD
        invalid_params:
          type: array
          items:
            type: object
            required: [name, reason]
            properties:
              name:
                type: string
                example: rfc
              reason:
                type: string
                example: Formato de RFC inválido ante el SAT
    Client:
      type: object
      required: [id, name]
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Comercializadora del Norte S.A. de C.V.
        rfc:
          type: string
          example: CNO180425ABC
        email:
          type: string
          format: email
          example: contacto@comercializadora.mx
        phone:
          type: string
          example: +52 55 1234 5678
        creditLimit:
          type: number
          example: 50000
        balance:
          type: number
          example: 12450
        createdAt:
          type: string
          format: date-time
    ClientInput:
      type: object
      required: [name]
      properties:
        name:
          type: string
        rfc:
          type: string
        email:
          type: string
          format: email
        phone:
          type: string
        address:
          type: string
        postal_code:
          type: string
        regimen_fiscal:
          type: string
          example: '601'
        uso_cfdi:
          type: string
          example: G03
    ClientListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Client'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ClientDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Client'
    Product:
      type: object
      required: [id, name, price]
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Laptop Dell 15 pulgadas
        sku:
          type: string
          example: DELL-LAP-001
        barcode:
          type: string
          example: '7501234567890'
        price:
          type: number
          example: 15999
        cost:
          type: number
          example: 12000
        stock:
          type: number
          example: 10
        sat_code:
          type: string
          example: '43211503'
    ProductInput:
      type: object
      required: [name, price]
      properties:
        name:
          type: string
        sku:
          type: string
        barcode:
          type: string
        price:
          type: number
        cost:
          type: number
        description:
          type: string
        category:
          type: string
        sat_code:
          type: string
    ProductListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Product'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    ProductDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Product'
    Quotation:
      type: object
      required: [id, client_id, total, status]
      properties:
        id:
          type: string
          format: uuid
        folio:
          type: string
          example: COT-2026-001
        client_id:
          type: string
          format: uuid
        total:
          type: number
          example: 25000
        currency:
          type: string
          example: MXN
        status:
          type: string
          enum: [draft, sent, approved, rejected, converted]
        createdAt:
          type: string
          format: date-time
    QuotationInput:
      type: object
      required: [client_id, items]
      properties:
        client_id:
          type: string
          format: uuid
        currency:
          type: string
          default: MXN
        items:
          type: array
          items:
            type: object
            required: [product_id, quantity, unit_price]
            properties:
              product_id:
                type: string
              quantity:
                type: number
              unit_price:
                type: number
              discount_percent:
                type: number
                default: 0
    QuotationListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Quotation'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    QuotationDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Quotation'
    Order:
      type: object
      required: [id, folio, total, status]
      properties:
        id:
          type: string
          format: uuid
        folio:
          type: string
          example: PED-2026-089
        client_id:
          type: string
          format: uuid
        total:
          type: number
          example: 25000
        status:
          type: string
          enum: [pending, in_process, shipped, delivered, invoiced]
        createdAt:
          type: string
          format: date-time
    OrderListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Order'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    OrderDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Order'
    Invoice:
      type: object
      required: [id, uuid_sat, total, status]
      properties:
        id:
          type: string
          format: uuid
        uuid_sat:
          type: string
          example: 4a5c89d2-3e21-4f12-9c34-7a1b89c0d123
        serie:
          type: string
          example: F
        folio:
          type: integer
          example: 1042
        rfc_emisor:
          type: string
          example: GEC150320XYZ
        rfc_receptor:
          type: string
          example: CNO180425ABC
        total:
          type: number
          example: 29000
        currency:
          type: string
          example: MXN
        status:
          type: string
          enum: [stamped, cancelled]
        xml_url:
          type: string
          format: uri
        pdf_url:
          type: string
          format: uri
        stampedAt:
          type: string
          format: date-time
    InvoiceListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Invoice'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    InvoiceDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Invoice'
    Opportunity:
      type: object
      required: [id, title, value, stage]
      properties:
        id:
          type: string
          format: uuid
        title:
          type: string
          example: Implementación ERP 50 usuarios
        value:
          type: number
          example: 120000
        currency:
          type: string
          example: MXN
        stage:
          type: string
          example: negotiation
        probability:
          type: integer
          example: 75
    PipelineListResponse:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Opportunity'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    PipelineDetailResponse:
      type: object
      required: [success, data]
      properties:
        success:
          type: boolean
          example: true
        data:
          $ref: '#/components/schemas/Opportunity'
    Stage:
      type: object
      required: [id, name, probability, order]
      properties:
        id:
          type: string
          example: prospecting
        name:
          type: string
          example: Prospección Inicial
        probability:
          type: integer
          example: 20
        order:
          type: integer
          example: 1
    StageListResponse:
      type: object
      required: [data]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Stage'
    AuthLoginResponse:
      type: object
      required: [token, user]
      properties:
        token:
          type: string
        user:
          type: object
          required: [id, email, name, role]
          properties:
            id:
              type: string
            email:
              type: string
              format: email
            name:
              type: string
            role:
              type: string
    PaginationMeta:
      type: object
      required: [total, page, limit, pages]
      properties:
        total:
          type: integer
          example: 120
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 50
        pages:
          type: integer
          example: 3
  responses:
    BadRequest:
      description: Petición inválida o parámetros faltantes (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Unauthorized:
      description: Firma inválida o credenciales no proporcionadas (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Forbidden:
      description: Acceso denegado al endpoint para el plan contratado (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    NotFound:
      description: Recurso no encontrado (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    UnprocessableEntity:
      description: Error semántico de validación en la entidad enviada (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    TooManyRequests:
      description: Límite de tasa de peticiones excedido (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    InternalServerError:
      description: Error interno del servidor (RFC 9457 Problem Details)
      headers:
        X-API-Version:
          $ref: '#/components/headers/ApiVersionResponse'
        Vary:
          $ref: '#/components/headers/VaryHeader'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
        application/json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
