openapi: "3.1.0"
info:
  title: Telephony MiniApp — Solicitudes Salientes
  description: >
    Solicitudes salientes de nuestra aplicacion hacia la externa (Acloud → MiniApp).
    Se envian como solicitudes POST al endpoint_url configurado en la integracion.
    Authorization: Bearer {api_token}
  version: "1.0.0"

x-retry-policy:
  max_retries: 3
  strategy: exponential backoff
  delays_seconds: [1, 2, 4]

x-expected-response:
  success_codes: [200, 201, 202]
  description: >
    Cualquier respuesta 2xx se considera exitosa.
    Los errores 4xx no se reintentan. Los errores 5xx se reintentan segun la politica de reintentos.

webhooks:

  call.init:
    post:
      summary: Iniciar llamada saliente
      description: >
        Solicita a la aplicacion externa que inicie una llamada en nombre de un empleado.
        Se envia cuando el usuario hace clic en el boton de llamada en la interfaz de Acloud.
      x-headers:
        Content-Type: application/json
        Authorization: Bearer {api_token}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - method
                - payload
              properties:
                method:
                  type: string
                  enum:
                    - call.init
                payload:
                  $ref: '#/components/schemas/CallInitPayload'
            examples:
              call_init:
                summary: Iniciar llamada de empleado a cliente
                value:
                  method: call.init
                  payload:
                    to: "+79995556677"
                    from: "101"
      responses:
        "200":
          description: Solicitud de inicio de llamada aceptada

  call.list:
    post:
      summary: Obtener lista de llamadas
      description: >
        Solicita la lista de llamadas del periodo especificado.
        Se usa para sincronizar llamadas desde el sistema externo.
      x-headers:
        Content-Type: application/json
        Authorization: Bearer {api_token}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - method
                - payload
              properties:
                method:
                  type: string
                  enum:
                    - call.list
                payload:
                  $ref: '#/components/schemas/CallListPayload'
            examples:
              call_list_by_days:
                summary: Llamadas de los ultimos 7 dias
                value:
                  method: call.list
                  payload:
                    days_left: 7
              call_list_by_range:
                summary: Llamadas por rango de fechas
                value:
                  method: call.list
                  payload:
                    from_date: "2026-04-01"
                    to_date: "2026-04-09"
      responses:
        "200":
          description: Lista de llamadas
          content:
            application/json:
              schema:
                type: object
                properties:
                  calls:
                    type: array
                    items:
                      $ref: '#/components/schemas/CallItem'
              examples:
                call_list_response:
                  summary: Lista de llamadas
                  value:
                    calls:
                      - call_id: call_abc123
                        direction: in
                        from: "+79990001234"
                        to: "101"
                        timestamp: "2026-04-09T10:30:00Z"
                        call_duration: 295
                        status: terminated
                        has_record: true
                      - call_id: call_abc124
                        direction: out
                        from: "102"
                        to: "+79991112233"
                        timestamp: "2026-04-09T11:00:00Z"
                        call_duration: 0
                        status: missed
                        has_record: false

  call.get:
    post:
      summary: Obtener datos de una llamada
      description: >
        Solicita los datos de una llamada especifica por su identificador.
      x-headers:
        Content-Type: application/json
        Authorization: Bearer {api_token}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - method
                - payload
              properties:
                method:
                  type: string
                  enum:
                    - call.get
                payload:
                  $ref: '#/components/schemas/CallGetPayload'
            examples:
              call_get:
                summary: Obtener llamada por ID
                value:
                  method: call.get
                  payload:
                    call_id: call_abc123
      responses:
        "200":
          description: Datos de la llamada (null si no se encuentra)
          content:
            application/json:
              schema:
                type: object
                properties:
                  call:
                    oneOf:
                      - $ref: '#/components/schemas/CallItem'
                      - type: "null"
              examples:
                call_found:
                  summary: Llamada encontrada
                  value:
                    call:
                      call_id: call_abc123
                      direction: in
                      from: "+79990001234"
                      to: "101"
                      timestamp: "2026-04-09T10:30:00Z"
                      call_duration: 295
                      status: terminated
                      has_record: true
                call_not_found:
                  summary: Llamada no encontrada
                  value:
                    call: null

  sip.employees.list:
    post:
      summary: Obtener lista de empleados SIP
      description: >
        Solicita la lista de empleados configurados en el sistema telefonico externo.
        Se usa para mapear las extensiones de empleados a usuarios de Acloud.
      x-headers:
        Content-Type: application/json
        Authorization: Bearer {api_token}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - method
                - payload
              properties:
                method:
                  type: string
                  enum:
                    - sip.employees.list
                payload:
                  type: object
                  description: Payload vacio
            examples:
              sip_employees_list:
                summary: Solicitar lista de empleados
                value:
                  method: sip.employees.list
                  payload: {}
      responses:
        "200":
          description: Lista de empleados SIP
          content:
            application/json:
              schema:
                type: object
                properties:
                  employees:
                    type: array
                    items:
                      $ref: '#/components/schemas/SipEmployee'
              examples:
                employees_list:
                  summary: Lista de empleados
                  value:
                    employees:
                      - id: "emp_001"
                        name: Juan Garcia
                        email: juan@example.com
                        extension: "101"
                      - id: "emp_002"
                        name: Maria Garcia
                        email: maria@example.com
                        extension: "102"

  integration.status:
    post:
      summary: Obtener estado de la integracion
      description: >
        Verifica la disponibilidad y el estado de la integracion con la aplicacion externa.
        Se usa para health check y diagnostico.
      x-headers:
        Content-Type: application/json
        Authorization: Bearer {api_token}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - method
                - payload
              properties:
                method:
                  type: string
                  enum:
                    - integration.status
                payload:
                  type: object
                  description: Payload vacio
            examples:
              integration_status:
                summary: Solicitud de estado de integracion
                value:
                  method: integration.status
                  payload: {}
      responses:
        "200":
          description: Estado de la integracion
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationStatusResponse'
              examples:
                status_active:
                  summary: Integracion activa
                  value:
                    status: active
                    message: ""
                status_inactive:
                  summary: Integracion inactiva
                  value:
                    status: inactive
                    message: "API token is invalid"


components:
  schemas:

    OutgoingEvent:
      type: object
      required:
        - method
        - payload
      properties:
        method:
          type: string
          enum:
            - call.init
            - call.list
            - call.get
            - sip.employees.list
            - integration.status
          description: Tipo de solicitud
        payload:
          oneOf:
            - $ref: '#/components/schemas/CallInitPayload'
            - $ref: '#/components/schemas/CallListPayload'
            - $ref: '#/components/schemas/CallGetPayload'
          discriminator:
            propertyName: method

    # ─── call.init ────────────────────────────────────────────────────────────

    CallInitPayload:
      type: object
      description: Parametros para iniciar una llamada saliente
      required:
        - to
        - from
      properties:
        to:
          type: string
          description: Numero de telefono al que llamar
          example: "+79995556677"
        from:
          type: string
          description: Extension del empleado (numero interno) en cuyo nombre se realiza la llamada
          example: "101"

    # ─── call.list ────────────────────────────────────────────────────────────

    CallListPayload:
      type: object
      description: >
        Parametros de filtrado para la lista de llamadas. Todos los campos son opcionales.
        Si no se especifican — se devuelven todas las llamadas disponibles.
      properties:
        days_left:
          type: ["integer", "null"]
          description: Numero de dias hacia atras desde la fecha actual para la seleccion de llamadas
          example: 7
        from_date:
          type: ["string", "null"]
          description: Fecha de inicio del periodo de seleccion (formato YYYY-MM-DD)
          example: "2026-04-01"
        to_date:
          type: ["string", "null"]
          description: Fecha de fin del periodo de seleccion (formato YYYY-MM-DD)
          example: "2026-04-09"

    # ─── call.get ─────────────────────────────────────────────────────────────

    CallGetPayload:
      type: object
      description: Parametros para obtener los datos de una llamada especifica
      required:
        - call_id
      properties:
        call_id:
          type: string
          description: Identificador unico de la llamada en el sistema externo
          example: call_abc123

    # ─── Shared types ─────────────────────────────────────────────────────────

    CallItem:
      type: object
      description: Datos de una llamada del sistema externo
      required:
        - call_id
        - direction
        - from
        - to
        - timestamp
        - call_duration
        - status
        - has_record
      properties:
        call_id:
          type: string
          description: Identificador unico de la llamada
          example: call_abc123
        direction:
          type: string
          enum:
            - in
            - out
          description: Direccion de la llamada
        from:
          type: string
          description: Origen de la llamada (numero de telefono o extension)
          example: "+79990001234"
        to:
          type: string
          description: Destinatario de la llamada (numero de telefono o extension)
          example: "101"
        timestamp:
          type: string
          description: Fecha y hora de la llamada en formato ISO 8601
          example: "2026-04-09T10:30:00Z"
        call_duration:
          type: integer
          description: Duracion de la conversacion en segundos
          example: 295
        status:
          type: string
          enum:
            - active
            - terminated
            - missed
          description: Estado de la llamada
        has_record:
          type: boolean
          description: Indicador de si existe grabacion de la llamada
          example: true
        record_url:
          type: string
          description: Enlace de descarga de la grabacion de la llamada
          example: https://dominio/call_id
          nullable: true

    SipEmployee:
      type: object
      description: Datos del empleado en el sistema SIP de la aplicacion externa
      required:
        - id
        - name
        - email
        - extension
      properties:
        id:
          type: string
          description: Identificador unico del empleado en el sistema externo
          example: "emp_001"
        name:
          type: string
          description: Nombre visible del empleado
          example: Juan Garcia
        email:
          type: string
          description: Email del empleado
          example: juan@example.com
        extension:
          type: string
          description: Numero SIP interno del empleado
          example: "101"

    IntegrationStatusResponse:
      type: object
      description: Respuesta a la solicitud de estado de integracion
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - active
            - inactive
          description: >
            Estado actual de la integracion.
            `active` — la integracion funciona normalmente;
            `inactive` — la integracion no esta disponible o esta desactivada.
        message:
          type: string
          description: Mensaje adicional de estado (p.ej., motivo de inactividad)
          example: ""
