openapi: 3.1.0
info:
  title: Profiles
  description: "Este API es parte de **Transcend** y corresponde al módulo de gestión\
    \ de perfiles.\n\nSu principal función es proporcionar una interfaz para buscar\
    \ y navegar por la jerarquía completa\nde códigos HS, que incluye:\n- Secciones\n\
    - Capítulos\n- Partidas\n- Subpartidas\n\nLa API permite tanto obtener la estructura\
    \ completa como realizar búsquedas específicas\npor términos en cualquier nivel\
    \ de la jerarquía.\n\n**Nota**: \n- La API requiere autenticación mediante un\
    \ token JWT.\n- Los endpoints están protegidos y requieren autenticación.\n"
  version: 1.0.0
  contact:
    email: support@cargoffer.com
  license:
    name: Private API - Access by agreement only
servers:
- url: https://api.pro.cargoffer.com
  description: Producción
components:
  schemas:
    SubheadingResult:
      type: object
      description: "Representa una subpartida del código HS (Sistema Armonizado),\
        \ que es el nivel más granular\nde la clasificación. Cada subpartida pertenece\
        \ a una partida específica.\n\nEjemplo:\n```json\n{\n  \"_id\": \"6501a2b3c4d5e6f7a8b9c0d1\"\
        ,\n  \"title\": \"Algodón sin cardar ni peinar\"\n}\n```\n"
      properties:
        _id:
          type: string
          description: 'Identificador único MongoDB de la subpartida.

            Formato: ObjectId como string hexadecimal (24 caracteres)

            '
          example: 6501a2b3c4d5e6f7a8b9c0d1
        title:
          type: string
          description: 'Nombre descriptivo completo de la subpartida según la nomenclatura
            HS.

            Este campo está disponible en múltiples idiomas según la configuración
            del sistema.

            '
          example: Algodón sin cardar ni peinar
      required:
      - _id
    HeadingResult:
      type: object
      description: "Representa una partida del código HS, que agrupa subpartidas relacionadas.\n\
        Cada partida pertenece a un capítulo específico.\n\nEjemplo:\n```json\n{\n\
        \  \"_id\": \"6501a2b3c4d5e6f7a8b9c0d2\",\n  \"title\": \"Algodón\",\n  \"\
        subheadings\": [\n    {\n      \"_id\": \"6501a2b3c4d5e6f7a8b9c0d1\",\n  \
        \    \"title\": \"Algodón sin cardar ni peinar\"\n    }\n  ]\n}\n```\n"
      properties:
        _id:
          type: string
          description: Identificador único MongoDB de la partida
          example: 6501a2b3c4d5e6f7a8b9c0d2
        title:
          type: string
          description: Nombre descriptivo de la partida según la nomenclatura HS
          example: Algodón
        subheadings:
          type: array
          description: 'Lista de subpartidas asociadas a esta partida.

            Puede estar vacía si no hay subpartidas definidas.

            '
          items:
            $ref: '#/components/schemas/SubheadingResult'
      required:
      - _id
      - subheadings
    ChapterResult:
      type: object
      description: "Representa un capítulo del código HS, que agrupa partidas relacionadas.\n\
        Cada capítulo pertenece a una sección específica.\n\nEjemplo:\n```json\n{\n\
        \  \"_id\": \"6501a2b3c4d5e6f7a8b9c0d3\",\n  \"title\": \"Capítulo 52 - Algodón\"\
        ,\n  \"headings\": [\n    {\n      \"_id\": \"6501a2b3c4d5e6f7a8b9c0d2\",\n\
        \      \"title\": \"Algodón\",\n      \"subheadings\": [...]\n    }\n  ]\n\
        }\n```\n"
      properties:
        _id:
          type: string
          description: Identificador único MongoDB del capítulo
          example: 6501a2b3c4d5e6f7a8b9c0d3
        title:
          type: string
          description: 'Título completo del capítulo incluyendo número y descripción.

            Formato: "Capítulo XX - Descripción"

            '
          example: Capítulo 52 - Algodón
        headings:
          type: array
          description: 'Lista de partidas asociadas a este capítulo.

            Puede estar vacía si no hay partidas definidas.

            '
          items:
            $ref: '#/components/schemas/HeadingResult'
      required:
      - _id
      - headings
    SearchResult:
      type: object
      description: "Representa una sección del código HS, que es el nivel más alto\
        \ de la jerarquía.\nCada sección contiene uno o más capítulos.\n\nEjemplo:\n\
        ```json\n{\n  \"_id\": \"6501a2b3c4d5e6f7a8b9c0d4\",\n  \"title\": \"Sección\
        \ XI - Textiles\",\n  \"chapters\": [\n    {\n      \"_id\": \"6501a2b3c4d5e6f7a8b9c0d3\"\
        ,\n      \"title\": \"Capítulo 52 - Algodón\",\n      \"headings\": [...]\n\
        \    }\n  ]\n}\n```\n"
      properties:
        _id:
          type: string
          description: Identificador único MongoDB de la sección
          example: 6501a2b3c4d5e6f7a8b9c0d4
        title:
          type: string
          description: 'Título completo de la sección incluyendo número romano y descripción.

            Formato: "Sección XX - Descripción"

            '
          example: Sección XI - Textiles
        chapters:
          type: array
          description: 'Lista de capítulos asociados a esta sección.

            Siempre contiene al menos un capítulo.

            '
          items:
            $ref: '#/components/schemas/ChapterResult'
      required:
      - _id
      - chapters
    Error:
      type: object
      properties:
        message:
          type: string
          description: Mensaje descriptivo del error
    securitySchemes:
      bearerAuth:
        type: http
        scheme: bearer
        bearerFormat: JWT
        description: "Autenticación mediante JWT. \nEl token debe ser obtenido del\
          \ servicio de autenticación de Transcend.\nFormato del header:\n```\nAuthorization:\
          \ Bearer {token}\n```\nEjemplo:\n```\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\n\
          ```\n"
  parameters:
    authorization:
      name: authorization
      in: header
      required: true
      schema:
        type: string
        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2M2Q3OTA3Y2JlNzY0MDNiMzVkYTYzZGYiLCJlbWFpbCI6ImNpYUB0ZXN0aW5nLmNvbSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc0MTI3NzU2OSwiZXhwIjoxNzQxMzYzOTY5fQ.9LtCdRFKVXB2oONyupGToxYz_wu4zH9dKhmw2beBNGI
        default: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2M2Q3OTA3Y2JlNzY0MDNiMzVkYTYzZGYiLCJlbWFpbCI6ImNpYUB0ZXN0aW5nLmNvbSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc0MTI3NzU2OSwiZXhwIjoxNzQxMzYzOTY5fQ.9LtCdRFKVXB2oONyupGToxYz_wu4zH9dKhmw2beBNGI
      description: Token JWT de Autenfiticación; se consigue con IAM
paths:
  /:
    get:
      tags:
      - HS Code Structure
      summary: Obtener toda la estructura jerárquica del HS Code
      description: "Obtiene la estructura completa del sistema armonizado, incluyendo\
        \ todas las secciones,\ncapítulos, partidas y subpartidas organizadas jerárquicamente.\n\
        \nLa respuesta incluye todos los niveles anidados en un solo request:\n- Secciones\
        \ (nivel más alto)\n- Capítulos (dentro de secciones)\n- Partidas (dentro\
        \ de capítulos) \n- Subpartidas (dentro de partidas)\n\nRequiere autenticación\
        \ mediante JWT en el header Authorization.\n"
      operationId: getAll
      security:
      - bearerAuth: []
      responses:
        '200':
          description: 'Estructura completa recuperada exitosamente.

            Devuelve un array de secciones, cada una con sus capítulos anidados,

            que a su vez contienen partidas y subpartidas.

            '
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SearchResult'
              example:
              - _id: 6501a2b3c4d5e6f7a8b9c0d4
                title: Sección XI - Textiles
                chapters:
                - _id: 6501a2b3c4d5e6f7a8b9c0d3
                  title: Capítulo 52 - Algodón
                  headings:
                  - _id: 6501a2b3c4d5e6f7a8b9c0d2
                    title: Algodón
                    subheadings:
                    - _id: 6501a2b3c4d5e6f7a8b9c0d1
                      title: Algodón sin cardar ni peinar
        '401':
          description: "No autorizado. Ocurre cuando:\n- No se proporciona el header\
            \ Authorization\n- El token JWT es inválido o ha expirado\n- El formato\
            \ del token es incorrecto\n\nEjemplo de respuesta:\n```json\n{\n  \"message\"\
            : \"Invalid or expired token\"\n}\n```\n"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingToken:
                  value:
                    message: Authentication token is required
                invalidToken:
                  value:
                    message: Invalid or expired token
        '500':
          description: 'Error interno del servidor.

            Puede ocurrir si hay problemas al acceder a la base de datos.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      parameters:
      - $ref: '#/components/parameters/authorization'
  /search:
    get:
      tags:
      - HS Code Structure
      summary: Buscar en toda la estructura del HS Code
      description: 'Realiza una búsqueda textual en todos los niveles de la jerarquía
        HS:

        - Secciones

        - Capítulos

        - Partidas

        - Subpartidas


        Devuelve solo los elementos que coincidan con el término de búsqueda,

        manteniendo la estructura jerárquica entre ellos.


        La búsqueda no distingue mayúsculas/minúsculas y busca coincidencias parciales.


        Requiere autenticación mediante JWT en el header Authorization.

        '
      operationId: search
      security:
      - bearerAuth: []
      parameters:
      - name: search
        in: query
        description: 'Término de búsqueda para filtrar resultados.

          Mínimo 3 caracteres. Puede buscar por:

          - Números de capítulo/partida (ej. "52")

          - Descripciones (ej. "algodón")

          - Combinaciones (ej. "52 algodón")

          '
        required: true
        schema:
          type: string
          minLength: 3
        example: algodón
      - $ref: '#/components/parameters/authorization'
      responses:
        '200':
          description: 'Búsqueda realizada exitosamente.

            Devuelve un array de secciones que contienen al menos un elemento

            que coincide con el término de búsqueda, con la estructura jerárquica

            completa desde la sección hasta el elemento coincidente.

            '
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SearchResult'
              example:
              - _id: 6501a2b3c4d5e6f7a8b9c0d4
                title: Sección XI - Textiles
                chapters:
                - _id: 6501a2b3c4d5e6f7a8b9c0d3
                  title: Capítulo 52 - Algodón
                  headings: []
        '400':
          description: 'Parámetros de búsqueda inválidos.

            Ocurre cuando:

            - No se proporciona el parámetro ''search''

            - El término de búsqueda tiene menos de 3 caracteres

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: Search query is required and must be at least 3 characters
        '401':
          description: "No autorizado. Ocurre cuando:\n- No se proporciona el header\
            \ Authorization\n- El token JWT es inválido o ha expirado\n- El formato\
            \ del token es incorrecto\n\nEjemplo de respuesta:\n```json\n{\n  \"message\"\
            : \"Invalid or expired token\"\n}\n```\n"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingToken:
                  value:
                    message: Authentication token is required
                invalidToken:
                  value:
                    message: Invalid or expired token
        '500':
          description: 'Error interno del servidor.

            Puede ocurrir si hay problemas al acceder a la base de datos.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
