openapi: 3.0.0
info:
  title: Payment
  description: 'Este API es parte de **Transcend** y corresponde al módulo de procesamiento
    de pagos y facturación.


    Su principal misión es gestionar todos los aspectos relacionados con los pagos,
    suscripciones,

    facturación y planes de precios para los servicios de Transcend. Proporciona endpoints
    para:

    - Gestión de suscripciones y planes de precios

    - Procesamiento de pagos mediante Stripe

    - Facturación y gestión de facturas

    - Seguimiento de uso y métricas de consumo

    - Gestión de perfiles de usuario y clientes Stripe

    '
  version: 1.0.0
  contact:
    email: support@cargoffer.com
  license: Private API - Access by agreement only
servers:
- url: https://api.pro.cargoffer.com
  description: Producción
components:
  parameters:
    Module_Authorization:
      name: authorization
      in: header
      required: true
      schema:
        type: string
        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2M2Q3OTA3Y2JlNzY0MDNiMzVkYTYzZGYiLCJlbWFpbCI6ImNpYUB0ZXN0aW5nLmNvbSIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTc0MTI3NzU2OSwiZXhwIjoxNzQxMzYzOTY5fQ.9LtCdRFKVXB2oONyupGToxYz_wu4zH9dKhmw2beBNGI
      description: Token JWT de Autenticación; se consigue con IAM
    API_Key:
      name: x-api-key
      in: header
      required: true
      schema:
        type: string
        example: your-api-key-here
      description: API key para autenticación de servicios
    UserId:
      name: userId
      in: query
      description: Identificador único del usuario en el sistema
      required: false
      schema:
        type: string
        example: 63d7907cbe76403b35da63df
    UserId_Path:
      name: userId
      in: path
      description: Identificador único del usuario en el sistema
      required: true
      schema:
        type: string
        example: 63d7907cbe76403b35da63df
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Mensaje descriptivo del error
      example:
        error: userId is required
    SuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Indica si la operación fue exitosa
      example:
        success: true
    SubscriptionSummary:
      type: object
      properties:
        subscription:
          type: object
          properties:
            status:
              type: string
              description: Estado de la suscripción (active, canceled, etc.)
            currentPeriodStart:
              type: string
              format: date-time
              description: Inicio del período de facturación
            currentPeriodEnd:
              type: string
              format: date-time
              description: Fin del período de facturación
            cancelAt:
              type: string
              format: date-time
              description: Fecha de cancelación programada
            cancelReason:
              type: string
              description: Motivo de cancelación
            amount:
              type: number
              description: Monto del período
            currency:
              type: string
              description: 'Moneda, ejemplo: eur'
        pricingTier:
          type: object
          properties:
            code:
              type: string
              description: Código del plan
            name:
              type: string
              description: Nombre del plan
            type:
              type: string
              description: Tipo de plan
            basePrice:
              type: number
              description: Precio base
            includedRoutes:
              type: number
              description: Rutas incluidas en el plan
            excessRoutePrice:
              type: number
              description: Precio por ruta adicional
        totalRoutes:
          type: number
          description: Total de rutas utilizadas en el período
    PricingTier:
      type: object
      properties:
        _id:
          type: string
        code:
          type: string
          description: 'Código único del plan, ejemplo: basic o premium'
        name:
          type: string
          description: Nombre descriptivo del plan
        type:
          type: string
          description: Tipo de plan (subscription, pay-per-use, etc.)
        basePrice:
          type: number
          description: Precio base mensual/anual
        includedRoutes:
          type: number
          description: Cantidad de rutas incluidas en el precio base
        excessRoutePrice:
          type: number
          description: Costo por cada ruta adicional
        isActive:
          type: boolean
          description: Indica si el plan está disponible
    CheckoutSessionRequest:
      type: object
      required:
      - success_url
      - cancel_url
      - subscription
      properties:
        success_url:
          type: string
          format: uri
          description: URL a la que redirigir tras pago exitoso
          example: https://app.example.com/success
        cancel_url:
          type: string
          format: uri
          description: URL a la que redirigir si el usuario cancela
          example: https://app.example.com/cancel
        subscription:
          type: string
          description: Código del plan de suscripción a contratar
          example: premium
    PortalSessionRequest:
      type: object
      required:
      - return_url
      properties:
        return_url:
          type: string
          format: uri
          description: URL a la que redirigir al salir del portal de cliente
          example: https://app.example.com/account
    RouteUsageRecord:
      type: object
      required:
      - userId
      - quantity
      properties:
        userId:
          type: string
          description: ID del usuario que utiliza las rutas
        quantity:
          type: number
          minimum: 1
          description: Cantidad de rutas utilizadas
          default: 1
        timestamp:
          type: number
          description: Timestamp Unix del momento de uso (opcional, usa actual si
            no se proporciona)
    BillingModeUpdate:
      type: object
      required:
      - code
      properties:
        code:
          type: string
          description: Código del nuevo plan de precios a aplicar
          example: premium
    Invoice:
      type: object
      properties:
        id:
          type: string
          description: ID de la factura en Stripe
        number:
          type: string
          description: Número de factura
        amount_due:
          type: number
          description: Monto total de la factura
        currency:
          type: string
          description: Moneda
        status:
          type: string
          description: Estado de la factura (paid, draft, open, etc.)
        created:
          type: number
          description: Timestamp de creación
        due_date:
          type: number
          description: Timestamp de vencimiento
        hosted_invoice_url:
          type: string
          description: URL para ver la factura
  responses:
    BadRequest:
      description: Parámetros inválidos o faltantes
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Recurso no encontrado
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: Error del servidor
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: No autorizado
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
paths:
  /:
    get:
      tags:
      - System
      summary: Estado del sistema
      description: Endpoint de health check para verificar el estado del servicio
        y conexión a base de datos
      operationId: healthCheck
      responses:
        '200':
          description: Servicio funcionando correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  dbStatus:
                    type: string
                    example: connected
                  timestamp:
                    type: string
                    format: date-time
        '500':
          $ref: '#/components/responses/InternalServerError'
  /test:
    get:
      tags:
      - System
      summary: Test de conexión
      description: Endpoint alternativo para verificar estado del servicio
      operationId: testCheck
      responses:
        '200':
          description: Servicio funcionando correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  dbStatus:
                    type: string
                    example: connected
                  timestamp:
                    type: string
                    format: date-time
        '500':
          $ref: '#/components/responses/InternalServerError'
  /health:
    get:
      tags:
      - System
      summary: Health check
      description: Endpoint de monitoreo de salud del sistema
      operationId: healthCheckMonitor
      responses:
        '200':
          description: Servicio funcionando correctamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  dbStatus:
                    type: string
                    example: connected
                  timestamp:
                    type: string
                    format: date-time
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/summary:
    get:
      tags:
      - Account
      summary: Obtener resumen de suscripción
      description: Obtiene información completa sobre la suscripción actual del usuario,
        incluyendo estado, período de facturación, plan contratado y consumo de rutas
      operationId: getAccountSummary
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: Resumen de suscripción obtenido exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: No se encontró suscripción activa para el usuario
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/create-checkout-session:
    post:
      tags:
      - Account
      summary: Crear sesión de checkout
      description: Crea una sesión de pago en Stripe para que el usuario pueda suscribirse
        a un plan. Devuelve la URL del checkout de Stripe
      operationId: createCheckoutSession
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      - $ref: '#/components/parameters/UserId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutSessionRequest'
      responses:
        '200':
          description: Sesión de checkout creada exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    format: uri
                    description: URL del checkout de Stripe
                    example: https://checkout.stripe.com/pay/cs_test_a1B2c3D4e5F6...
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: Perfil de usuario no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/create-portal-session:
    post:
      tags:
      - Account
      summary: Crear sesión del portal de cliente
      description: Crea una sesión del portal de cliente de Stripe para que el usuario
        pueda gestionar su suscripción, métodos de pago y facturas
      operationId: createPortalSession
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      - $ref: '#/components/parameters/UserId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PortalSessionRequest'
      responses:
        '200':
          description: Sesión del portal creada exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    format: uri
                    description: URL del portal de cliente de Stripe
                    example: https://billing.stripe.com/session/bps_1a2B3c4D5e6F...
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: Cliente de Stripe no encontrado para el usuario
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/failed-payments:
    get:
      tags:
      - Account
      summary: Obtener pagos fallidos
      description: Recupera el listado de pagos fallidos para el cliente del usuario,
        útil para identificar problemas de facturación
      operationId: getFailedPayments
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: Lista de pagos fallidos obtenida exitosamente
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  description: Objeto de pago fallido de Stripe
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: Cliente de Stripe no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/pricing-plans:
    get:
      tags:
      - Account
      summary: Obtener planes de precios disponibles
      description: Devuelve el listado completo de planes de precios activos, sus
        características y costos
      operationId: getPricingPlans
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      responses:
        '200':
          description: Lista de planes de precios obtenida exitosamente
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PricingTier'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /account/invoices:
    get:
      tags:
      - Account
      summary: Obtener facturas del usuario
      description: Recupera el historial de facturas del usuario, incluyendo estados
        y URLs para acceso
      operationId: getUserInvoices
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: Lista de facturas obtenida exitosamente
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Invoice'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: Cliente de Stripe no encontrado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /billing/pricing:
    get:
      tags:
      - Billing
      summary: Obtener todas las tarifas
      description: Recupera todos los planes de precios activos del sistema (endpoint
        público para IAM y otros servicios)
      operationId: getAllPricingTiers
      responses:
        '200':
          description: Lista de planes de precios obtenida exitosamente
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/PricingTier'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /billing/users/{userId}/subscription:
    get:
      tags:
      - Billing
      summary: Obtener tipo de suscripción de usuario
      description: Obtiene información sobre el tipo de suscripción de un usuario
        específico. Si no existe el perfil, lo crea automáticamente
      operationId: getUserSubscriptionType
      parameters:
      - $ref: '#/components/parameters/UserId_Path'
      - name: email
        in: query
        description: Email del usuario (requerido si no existe el perfil)
        required: false
        schema:
          type: string
          format: email
          example: user@example.com
      responses:
        '200':
          description: Tipo de suscripción obtenida exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  userId:
                    type: string
                    description: ID del usuario
                  subscriptionType:
                    type: string
                    description: Código del plan de suscripción ('none' si no tiene)
                  subscriptionName:
                    type: string
                    description: Nombre del plan ('none' si no tiene)
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /billing/routes/usage:
    post:
      tags:
      - Billing
      summary: Registrar uso de rutas
      description: Registra el consumo de rutas de un usuario para facturación. Las
        operaciones se encolan para procesamiento batch
      operationId: recordRouteUsage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RouteUsageRecord'
      responses:
        '202':
          description: Uso registrado y encolado exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: queued
                  message:
                    type: string
                    example: Usage record queued for user 63d7907cbe76403b35da63df
                  queueSize:
                    type: number
                    description: Tamaño actual de la cola de procesamiento
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /billing/users/{userId}/check-stripe:
    get:
      tags:
      - Billing
      summary: Verificar si el usuario tiene cliente Stripe
      description: Verifica si el usuario tiene un cliente Stripe asociado. Si no
        existe el perfil, lo crea automáticamente
      operationId: checkUserHasStripe
      parameters:
      - $ref: '#/components/parameters/UserId_Path'
      - name: email
        in: query
        description: Email del usuario (requerido si no existe el perfil)
        required: false
        schema:
          type: string
          format: email
          example: user@example.com
      responses:
        '200':
          description: Verificación completada exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  hasStripe:
                    type: boolean
                    description: Indica si el usuario tiene cliente Stripe
                  customerId:
                    type: string
                    description: ID del cliente Stripe (si existe)
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          description: No se encontró cliente Stripe para el usuario
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /billing/mode:
    put:
      tags:
      - Billing
      summary: Actualizar modo de facturación
      description: Actualiza el plan de precios de un usuario existente (requiere
        autenticación del usuario)
      operationId: updateBillingMode
      security:
      - bearerAuth: []
      - apiKeyAuth: []
      parameters:
      - $ref: '#/components/parameters/Module_Authorization'
      - $ref: '#/components/parameters/API_Key'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillingModeUpdate'
      responses:
        '200':
          description: Modo de facturación actualizado exitosamente
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Billing mode updated
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
security:
- bearerAuth: []
- apiKeyAuth: []
