openapi: 3.0.3
info:
  title: Wipsy CRM API
  description: >
    ### 🚀 Prueba con Datos Reales

    Para que esta documentación devuelva datos de tu cuenta en lugar de ejemplos
    ficticios:

    1. Ve a tu panel de Wipsy y obtén tu **API Key**.

    2. En el panel derecho de "Try it", haz clic en el botón de
    **Authentication**.

    3. Pega tu clave en el campo **x-api-key**.

    4. Asegúrate de tener seleccionado el **Production server** en el selector
    de servidores.


    ### Características principales:

    - Mensajería multicanal (WhatsApp, Instagram, Facebook Messenger)

    - Gestión de Pipeline y embudos de venta

    - Sistema de etiquetas y campos personalizados

    - Soporte para mensajes citados y estados de entrega (enviado, entregado,
    leído)

    - Autenticación de agentes y permisos segmentados
  version: 1.1.0
  contact:
    name: Wipsy Support
    email: support@wipsy.com
  license:
    name: Proprietary
servers:
  - url: https://api.getwipsy.com/functions/v1
    description: Production server
tags:
  - name: Messages
    description: Send and manage messages across different channels
  - name: Chats
    description: Retrieve and manage chat conversations
  - name: Contacts
    description: Manage customer contacts
  - name: Agents
    description: Agent authentication and data access
  - name: Inventory
    description: Product inventory management
  - name: Pipeline
    description: Manage pipeline stages for contacts
  - name: Tags
    description: Manage tags for contacts and chats
  - name: CustomFields
    description: Manage custom fields for contacts
security:
  - ApiKeyAuth: []
  - BearerAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key for authentication (get from your Wipsy dashboard)
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Bearer token for agent authentication
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
      required:
        - error
    SuccessResponse:
      type: object
      properties:
        success:
          type: boolean
        data:
          type: object
    Message:
      type: object
      properties:
        id:
          type: string
          format: uuid
        chat_id:
          type: string
          format: uuid
        content:
          type: string
        sender_type:
          type: string
          enum:
            - customer
            - business
            - agent
            - system
        message_type:
          type: string
          enum:
            - text
            - image
            - video
            - audio
            - document
            - location
        created_at:
          type: string
          format: date-time
        is_read:
          type: boolean
        status:
          type: string
          enum:
            - sent
            - delivered
            - read
          description: Message delivery status (for business/agent sent messages)
          nullable: true
        whatsapp_message_id:
          type: string
          description: WhatsApp message ID (wamid.xxx format for Meta API)
          nullable: true
        metadata:
          type: object
          properties:
            quotedMessage:
              type: object
              description: Quoted message information
              properties:
                type:
                  type: string
                  enum:
                    - text
                    - image
                    - video
                    - audio
                    - document
                content:
                  type: string
                caption:
                  type: string
                  nullable: true
                url:
                  type: string
                  format: uri
                  nullable: true
            imageUrl:
              type: string
              format: uri
              nullable: true
            videoUrl:
              type: string
              format: uri
              nullable: true
            audioUrl:
              type: string
              format: uri
              nullable: true
            documentUrl:
              type: string
              format: uri
              nullable: true
            caption:
              type: string
              nullable: true
    Chat:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        customer_id:
          type: string
          format: uuid
        channel_type:
          type: string
          enum:
            - whatsapp
            - instagram
            - messenger
        status:
          type: string
          enum:
            - active
            - pending
            - completed
            - archived
        last_message_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        customer:
          $ref: '#/components/schemas/Contact'
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
    Contact:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        name:
          type: string
        last_name:
          type: string
          nullable: true
        phone:
          type: string
        whatsapp_id:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        profile_picture_url:
          type: string
          format: uri
          nullable: true
        pipeline_stage_id:
          type: string
          format: uuid
          description: Current pipeline stage ID for this contact
          nullable: true
        pipeline_stage:
          $ref: '#/components/schemas/PipelineStage'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
          nullable: true
        tags:
          type: array
          items:
            $ref: '#/components/schemas/Tag'
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/CustomFieldValue'
          description: Custom field values for this contact
    PipelineStage:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        name:
          type: string
          example: Nuevo Lead
        color:
          type: string
          example: '#3B82F6'
        stage_order:
          type: integer
          description: Order/position of this stage in the pipeline
        is_system:
          type: boolean
          description: Whether this is a system-created stage
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    Tag:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        name:
          type: string
          example: VIP
        color:
          type: string
          example: '#FF5733'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CustomField:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        field_name:
          type: string
          example: Company
        field_type:
          type: string
          enum:
            - text
            - email
            - phone
            - number
            - date
            - select
        field_options:
          type: array
          items:
            type: string
          description: Options for select type fields
          nullable: true
        is_required:
          type: boolean
        field_order:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CustomFieldValue:
      type: object
      properties:
        id:
          type: string
          format: uuid
        customer_id:
          type: string
          format: uuid
        field_id:
          type: string
          format: uuid
        field_value:
          type: string
          nullable: true
        field:
          $ref: '#/components/schemas/CustomField'
        updated_at:
          type: string
          format: date-time
    SendMessageRequest:
      type: object
      required:
        - to
        - message
      properties:
        to:
          type: string
          description: >
            Recipient identifier. Format depends on channel:

            - WhatsApp: Phone number (e.g., "+573188779043" or "573188779043")

            - Instagram: Instagram user ID (e.g., "828925823321473"). You can
            also use the prefix "ig_" (e.g., "ig_828925823321473").

            - Facebook Messenger: Facebook user ID (e.g., "123456789"). You can
            also use the prefix "fb_" (e.g., "fb_123456789").
          example: '+573188779043'
        message:
          type: string
          description: Message content
          example: Hello, how can I help you?
        channel:
          type: string
          enum:
            - whatsapp
            - instagram
            - facebook
            - messenger
          description: |
            Channel to send message through.
            - `whatsapp`: Default for phone numbers
            - `instagram`: For Instagram DMs
            - `facebook` or `messenger`: For Facebook Messenger
          example: whatsapp
        mediaUrl:
          type: string
          format: uri
          description: URL of media file (image, video, audio, document)
        mediaType:
          type: string
          enum:
            - image
            - video
            - audio
            - document
          description: Type of media if mediaUrl is provided
        from:
          type: string
          description: >-
            Phone number to send from (WhatsApp only, uses default if not
            specified)
        quotedMessageId:
          type: string
          description: >-
            WhatsApp message ID (wamid.xxx) of the message to quote/reply to
            (WhatsApp only)
          example: wamid.HBgMNTczMTg4Nzc5MDQzFQIAERgSOTg5ODFCMTQ5ODMzQTJCOTZGAA==
          nullable: true
        quotedMessageMetadata:
          type: object
          description: Metadata of the quoted message (optional, used for display)
          properties:
            type:
              type: string
              enum:
                - text
                - image
                - video
                - audio
                - document
            content:
              type: string
            caption:
              type: string
              nullable: true
            url:
              type: string
              format: uri
              nullable: true
          nullable: true
    SendMessageResponse:
      type: object
      properties:
        success:
          type: boolean
        messageId:
          type: string
          description: Message ID from the provider
        recipientId:
          type: string
          description: Recipient ID (for Instagram/Messenger)
        provider:
          type: string
          enum:
            - evolution
            - meta
            - instagram
            - messenger
          description: Provider used to send the message
        data:
          type: object
          description: Raw response from the messaging provider
    AgentSession:
      type: object
      required:
        - agent
        - session
      properties:
        agent:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            email:
              type: string
            role:
              type: string
            owner_user_id:
              type: string
            organization_id:
              type: string
              nullable: true
        permissions:
          type: object
          additionalProperties:
            type: boolean
        session:
          type: object
          properties:
            token:
              type: string
            expires_at:
              type: string
              format: date-time
paths:
  /api-send-message:
    post:
      tags:
        - Messages
      summary: Send a message
      operationId: sendMessage
      description: |
        Send a message via WhatsApp, Instagram, or Facebook Messenger.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendMessageRequest'
            examples:
              whatsappText:
                summary: WhatsApp text message
                value:
                  to: '+573188779043'
                  message: Hello, how can I help you?
              whatsappMedia:
                summary: WhatsApp with media
                value:
                  to: '+573188779043'
                  message: Check out this image!
                  mediaUrl: https://example.com/image.jpg
                  mediaType: image
              whatsappQuoted:
                summary: WhatsApp reply to message
                value:
                  to: '+573188779043'
                  message: This is a reply to your previous message
                  quotedMessageId: >-
                    wamid.HBgMNTczMTg4Nzc5MDQzFQIAERgSOTg5ODFCMTQ5ODMzQTJCOTZGAA==
                  quotedMessageMetadata:
                    type: text
                    content: Hello, how can I help you?
              instagramText:
                summary: Instagram DM text
                value:
                  to: '828925823321473'
                  message: Thanks for reaching out!
                  channel: instagram
              facebookText:
                summary: Facebook Messenger text
                value:
                  to: '123456789'
                  message: Hello from Messenger!
                  channel: facebook
              instagramMedia:
                summary: Instagram DM with image
                value:
                  to: '828925823321473'
                  message: Check out this image!
                  mediaUrl: https://example.com/image.jpg
                  mediaType: image
                  channel: instagram
              facebookMedia:
                summary: Facebook Messenger with video
                value:
                  to: '123456789'
                  message: Check out this video
                  mediaUrl: https://example.com/video.mp4
                  mediaType: video
                  channel: facebook
      responses:
        '200':
          description: Message sent successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendMessageResponse'
        '400':
          description: Bad request - missing required fields
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: WhatsApp credentials not found for specified number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api-get-chats:
    get:
      tags:
        - Chats
      summary: Get chats
      operationId: getChats
      description: |
        Retrieve chat conversations. Can get all chats or a specific chat by ID.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: chatId
          in: query
          description: Specific chat ID to retrieve (optional)
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          description: Maximum number of chats to return
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 100
      responses:
        '200':
          description: Chats retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    oneOf:
                      - $ref: '#/components/schemas/Chat'
                      - type: array
                        items:
                          $ref: '#/components/schemas/Chat'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Chat not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api-get-contacts:
    get:
      tags:
        - Contacts
      summary: Get contacts
      operationId: getContacts
      description: >
        Retrieve customer contacts. Can get all contacts or a specific contact
        by ID.

        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      parameters:
        - name: contactId
          in: query
          description: Specific contact ID to retrieve (optional)
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          description: Maximum number of contacts to return
          schema:
            type: integer
            default: 100
            minimum: 1
            maximum: 500
      responses:
        '200':
          description: Contacts retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    oneOf:
                      - $ref: '#/components/schemas/Contact'
                      - type: array
                        items:
                          $ref: '#/components/schemas/Contact'
        '401':
          description: Unauthorized - invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Contact not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /agent-get-chats:
    post:
      tags:
        - Agents
      summary: Get chats for agent
      operationId: agentGetChats
      description: |
        Retrieve chat conversations for an authenticated agent.
        Requires agent session authentication.
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agentSession
              properties:
                agentSession:
                  $ref: '#/components/schemas/AgentSession'
                status:
                  type: string
                  enum:
                    - all
                    - active
                    - pending
                    - completed
                  default: all
      responses:
        '200':
          description: Chats retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  chats:
                    type: array
                    items:
                      $ref: '#/components/schemas/Chat'
        '401':
          description: Unauthorized - invalid or expired agent session
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /agent-get-messages:
    post:
      tags:
        - Agents
      summary: Get messages for a chat (agent)
      operationId: agentGetMessages
      description: |
        Retrieve messages for a specific chat conversation.
        Requires agent session authentication.
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agentSession
                - chatId
              properties:
                agentSession:
                  $ref: '#/components/schemas/AgentSession'
                chatId:
                  type: string
                  format: uuid
                limit:
                  type: integer
                  default: 50
                  minimum: 1
                  maximum: 100
      responses:
        '200':
          description: Messages retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    type: array
                    items:
                      $ref: '#/components/schemas/Message'
        '401':
          description: Unauthorized - invalid or expired agent session
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - agent doesn't have access to this chat
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Chat not found or access denied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /inventory-api:
    get:
      tags:
        - Inventory
      summary: Get product inventory
      operationId: getInventory
      description: |
        Retrieve product inventory for a user.
        Can be accessed via userId or userHash parameter.
      parameters:
        - name: userId
          in: query
          description: User ID
          schema:
            type: string
            format: uuid
        - name: userHash
          in: query
          description: User hash (alternative to userId)
          schema:
            type: string
      responses:
        '200':
          description: Inventory retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  products:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        price:
                          type: number
                        stock:
                          type: integer
                        variants:
                          type: array
        '400':
          description: Bad request - userId or userHash required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api-update-contact:
    post:
      tags:
        - Contacts
      summary: Update a contact
      operationId: updateContact
      description: >
        Update contact information including name, email, phone, pipeline stage,
        and custom fields.

        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - contactId
              properties:
                contactId:
                  type: string
                  format: uuid
                name:
                  type: string
                last_name:
                  type: string
                  nullable: true
                email:
                  type: string
                  nullable: true
                phone:
                  type: string
                pipeline_stage_id:
                  type: string
                  format: uuid
                  description: Pipeline stage ID to assign to this contact
                  nullable: true
                custom_fields:
                  type: object
                  additionalProperties:
                    type: string
                  description: 'Custom field values (field_id: value pairs)'
      responses:
        '200':
          description: Contact updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Contact'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '404':
          description: Contact not found
        '500':
          description: Internal server error
  /api-get-pipeline-stages:
    get:
      tags:
        - Pipeline
      summary: Get pipeline stages
      operationId: getPipelineStages
      description: |
        Retrieve all pipeline stages for the authenticated user.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Pipeline stages retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PipelineStage'
        '401':
          description: Unauthorized
        '500':
          description: Internal server error
  /api-get-tags:
    get:
      tags:
        - Tags
      summary: Get tags
      operationId: getTags
      description: |
        Retrieve all tags for the authenticated user.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Tags retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Tag'
        '401':
          description: Unauthorized
        '500':
          description: Internal server error
  /api-assign-tag:
    post:
      tags:
        - Tags
      summary: Assign tag to contact
      operationId: assignTag
      description: |
        Assign a tag to a contact.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - contactId
                - tagId
              properties:
                contactId:
                  type: string
                  format: uuid
                tagId:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Tag assigned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '404':
          description: Contact or tag not found
        '500':
          description: Internal server error
  /api-remove-tag:
    post:
      tags:
        - Tags
      summary: Remove tag from contact
      operationId: removeTag
      description: |
        Remove a tag from a contact.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - contactId
                - tagId
              properties:
                contactId:
                  type: string
                  format: uuid
                tagId:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Tag removed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '404':
          description: Contact or tag not found
        '500':
          description: Internal server error
  /api-get-custom-fields:
    get:
      tags:
        - CustomFields
      summary: Get custom fields
      operationId: getCustomFields
      description: |
        Retrieve all custom fields for the authenticated user.
        Requires API key authentication.
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Custom fields retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CustomField'
        '401':
          description: Unauthorized
        '500':
          description: Internal server error
