openapi: "3.0.3"
info:
  version: 1.0.0
  title: HealviChat Client API
servers:
  - url: "https://{tenant_domain}/third-party/v1"
    variables:
      tenant_domain:
        default: your-tenant.onhealvi.com
        description: Your tenant domain
security:
  - bearerAuth: [ ]
paths:
  /support/openapi:
    get:
      summary: Return this document.
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            text/yaml:
              schema:
                type: string

  /support/channels:
    get:
      summary: Get info about channels and channel capabilities.
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          $ref: "#/components/schemas/Channel"
                        label:
                          description: Readable label of channel.
                          type: string
                          example: System
                        gdpr_approved:
                          description: Flag to indicate if the channel can be used to send sensitive information.
                          type: boolean
                        conversation_capabilities:
                          type: array
                          items:
                            anyOf:
                              - $ref: "#/components/schemas/ConversationCapability"
                        message_type:
                          type: array
                          items:
                            anyOf:
                              - $ref: "#/components/schemas/MessageType"
                        session_hours:
                          description: |
                            Number of hours a conversation session is valid.
                            After that time, a reply to a conversation will probably not be possible.
                            Implementation differs by channel.
                          type: integer

  /support/activity-types:
    get:
      summary: Get info about activity types (used in profile activity)
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: privacy_message
                        label:
                          deprecated: true
                          description: |
                            Readable label of activity type.
                            Deprecated, translate locally instead.
                          type: string
                          example: Datenschutzhinweis gesendet


  /support/allowed-mime-types:
    get:
      summary: Get info about allowed mime types per message type.
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      image:
                        type: array
                        items:
                          type: string
                      video:
                        type: array
                        items:
                          type: string
                      audio:
                        type: array
                        items:
                          type: string
                      document:
                        type: array
                        items:
                          type: string

  /support/media-size-limits:
    get:
      summary: Get info about allowed media file sizes in megabytes.
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      regular_mb:
                        description: Limits imposed by external services (e.g. WhatsApp).
                        type: object
                        properties:
                          image:
                            type: integer
                          video:
                            type: integer
                          audio:
                            type: integer
                          document:
                            type: integer
                      temporary_upload_mb:
                        description: |
                          Slightly higher limits when using the temporary file upload endpoint.
                          Images and videos will be compressed to comply with regular limits.
                        type: object
                        properties:
                          image:
                            type: integer
                          video:
                            type: integer
                          audio:
                            type: integer
                          document:
                            type: integer

  /support/whatsapp-pricing:
    get:
      summary: Get info about the current WhatsApp cost of sending messages. Any surcharge is already included.
      description: |
        Pricing, markets and calling codes are based on WhatsApp official rate card: https://developers.facebook.com/docs/whatsapp/pricing
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pricing:
                        type: array
                        items:
                          type: object
                          properties:
                            market:
                              type: string
                              example: Germany
                            currency:
                              type: string
                              example: €
                            marketing:
                              description: Price in currency of marketing message.
                              type: number
                              nullable: true
                              example: 0.1131
                            utility:
                              description: Price in currency of utility message.
                              type: number
                              nullable: true
                              example: 0.0456
                            authentication:
                              description: Price in currency of authentication message.
                              type: number
                              nullable: true
                              example: 0.0456
                            authentication_international:
                              description: Price in currency of authentication message.
                              type: number
                              nullable: true
                            service:
                              description: Price in currency of service message.
                              type: number
                              nullable: true
                      calling_codes:
                        description: |
                          Mapping of country/region to calling code. See market of pricing array for matching values.
                        type: array
                        items:
                          type: object
                          properties:
                            country:
                              type: string
                              example: Germany
                            region:
                              type: string
                              nullable: true
                              example: null
                            calling_code:
                              type: string
                              example: 49

  /support/whatsapp-template-languages:
    get:
      summary: |
        List of supported languages and their codes when creating a WhatsApp template.
      tags:
        - support
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        language:
                          type: string
                          example: English
                        code:
                          type: string
                          example: en

  /me:
    get:
      summary: |
        Returns the current user ID and name from the token.
      tags:
        - me
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        description: User ID.
                        type: integer
                      name:
                        description: User name.
                        type: string
                      email:
                        description: User email.
                        type: string
                      roles:
                        type: array
                        items:
                          type: string
                      permissions:
                        type: array
                        items:
                          type: string
                      uses_personal_access_token:
                        type: boolean

  /me/notifications:
    get:
      summary: |
        Returns the current user's notifications.
      tags:
        - me-notifications
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/UserNotification"

  /me/notifications/read:
    post:
      summary: |
        Mark all notifications as read.
      tags:
        - me-notifications
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/UserNotification"

  /me/notifications/{uuid}/read:
    post:
      summary: |
        Mark a notification as read.
      tags:
        - me-notifications
      parameters:
        - in: path
          name: uuid
          schema:
            type: string
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/UserNotification"

  /users:
    get:
      summary: List available users.
      tags:
        - users
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/User"
    post:
      summary: Add a new user.
      tags:
        - users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  description: Must be unique across users.
                  type: string
                is_admin:
                  type: boolean
                external_id:
                  type: string
                  nullable: true
                external_group:
                  type: string
                  nullable: true
                pin:
                  description: Optional user switch pin. Must be 6 digits.
                  type: number
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"

  /users/{id}:
    get:
      summary: Show user by ID.
      tags:
        - users
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/User"
    patch:
      summary: Update user by ID.
      tags:
        - users
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  description: Must be unique across users.
                external_id:
                  type: string
                  nullable: true
                external_group:
                  type: string
                  nullable: true
                pin:
                  description: Optional user switch pin. Must be 6 digits.
                  type: number
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/User"
    delete:
      summary: Delete user by ID. You cannot delete last admin user.
      tags:
        - users
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /user/{id}/verify-pin:
    post:
      summary: Check if the given PIN is correct for the user.
      description: |
        Can be used to implement a user account switcher.
        Requests are rate limited on fail.
      tags:
        - users
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pin:
                  type: integer
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      valid:
                        type: boolean

  /settings/general:
    get:
      summary: Get currently active general settings.
      tags:
        - settings
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/GeneralSettings"
    patch:
      summary: Update general settings.
      tags:
        - settings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GeneralSettings"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/GeneralSettings"

  /settings/third-party:
    get:
      summary: Get currently active third party settings.
      tags:
        - settings
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/ThirdPartySettings"
    patch:
      summary: Update third party settings.
      tags:
        - settings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ThirdPartySettings"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/ThirdPartySettings"

  /settings/crm:
    get:
      summary: Get currently active CRM settings.
      tags:
        - settings
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CrmSettings"
    patch:
      summary: Update CRM settings.
      tags:
        - settings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CrmSettings"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/CrmSettings"

  /agents:
    get:
      summary: List available agents.
      tags:
        - agents
      parameters:
        - in: query
          name: channel
          description: Optional channel filter.
          schema:
            $ref: "#/components/schemas/Channel"
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Agent"

  /agents/{id}:
    get:
      summary: Show agent by ID.
      tags:
        - agents
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Agent"
    patch:
      summary: Update agent by ID.
      tags:
        - agents
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                bot_id:
                  type: integer
                  description: Default bot that should handle new conversations.
                  nullable: true
                proxy_email:
                  type: string
                  description: See agent proxy_email field.
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Agent"

  /customers:
    get:
      summary: List available customers.
      tags:
        - customers
      parameters:
        - in: query
          name: channel
          description: Optional channel filter.
          schema:
            $ref: "#/components/schemas/Channel"
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Customer"
    post:
      summary: Add a new customer. Also creates a new profile.
      description: |
        Currently only possible for channel WhatsApp.
      tags:
        - customers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                channel:
                  type: string
                  enum:
                    - whatsapp
                display_id:
                  description: |
                    For WhatsApp: phone number in international format without leading "+", special characters and spaces.
                    Must be unique among channel "whatsapp".
                    Will be saved as phone number in profile.
                  type: string
                  example: 491521234567
                name:
                  description: Name of customer and profile.
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Customer"

  /customers/{id}:
    get:
      summary: Show customer by ID.
      tags:
        - customers
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Customer"
    delete:
      summary: Delete customer by ID. Attached profile and all customer data (messages, activities, etc) will be deleted.
      description: |
        Deletion will be logged. See deletion log.
      tags:
        - customers
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /customers/{id}/users:
    get:
      summary: List users attached to a customer
      description: |
        Used to show / hide customers for certain users.
        Users with role admin can always see and interact with all customers.
        User without that role must be explicitly added via this endpoint to be able so see
        and interact with the customer and conversation.
        The get route will not show admin users.
      tags:
        - customers
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/User"
    post:
      summary: Sync users with a customer.
      tags:
        - customers
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                user_ids:
                  description: |
                    Array of user IDs. It will automatically determine which IDs to attach or detach.
                  type: array
                  items:
                    type: integer
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/User"

  /customers/bulk-import:
    post:
      summary: Add new customers in bulk. Also creates new profile if a customer does not exist yet.
      description: |
        Currently only possible for channel WhatsApp.
      tags:
        - customers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                duplicates:
                  description: How to handle display IDs that already exist in the customer database.
                  type: string
                  enum:
                    - override
                    - skip
                customers:
                  type: array
                  items:
                    type: object
                    properties:
                      channel:
                        type: string
                        enum:
                          - whatsapp
                      display_id:
                        description: |
                          For WhatsApp: phone number in international format without leading "+", special characters and spaces.
                          Will be saved as phone number in profile.
                        type: string
                        example: 491521234567
                      name:
                        description: Name of customer and profile.
                        type: string
                      profile:
                        type: object
                        properties:
                          email:
                            description: Must be valid email address. Skipped otherwise.
                            type: string
                            nullable: true
                          date_of_birth:
                            description: |
                              Must be valid date. Skipped otherwise.
                              Supports YYYY-MM-DD and DD.MM.YYYY format.
                            type: string
                            nullable: true
                          address:
                            type: string
                            nullable: true
                          custom_1:
                            type: string
                            nullable: true
                          custom_2:
                            type: string
                            nullable: true
                          custom_3:
                            type: string
                            nullable: true
                          custom_4:
                            type: string
                            nullable: true
                          custom_5:
                            type: string
                            nullable: true
                          marketing_opt_in:
                            description: Flag to indicate of customer has given consent to receive marketing messages.
                            type: integer
                            example: 1
                            nullable: true
                          tags:
                            description: Comma separated list of tags. New tags will be created on the fly.
                            type: string
                            nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created_count:
                        type: integer
                        description: Number of customers created.
                      updated_count:
                        type: integer
                        description: Number of existing customers updated.
                      skipped_count:
                        type: integer
                        description: Number of existing customers skipped.

  /customers/bulk-delete:
    post:
      summary: |
        Bulk deletion of customers by ID. Same logic from singular customer deletion applies.
      tags:
        - customers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  description: IDs of customers to delete.
                  type: array
                  items:
                    type: integer
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /profiles:
    get:
      summary: List available profiles.
      tags:
        - profiles
      parameters:
        - in: query
          name: per_page
          description: Optional number of profiles per page.
          schema:
            type: integer
          required: false
        - in: query
          name: search
          description: Optional search filter.
          schema:
            type: string
          required: false
        - in: query
          name: channel
          description: Optional channel filter.
          schema:
            type: string
          required: false
        - in: query
          name: order_by
          description: Optional order by. List of comma separated fields.
          example: name:asc,email:desc
          schema:
            type: string
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Profile"

  /profiles/{id}:
    get:
      summary: Show profile by ID.
      tags:
        - profiles
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Profile"
    patch:
      summary: Update profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Profile"

      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Profile"

  /profiles/{id}/marketing-opt-in:
    get:
      summary: |
        Get info about current opt in / out status.
      tags:
        - profiles
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                        description: ID of profile.
                      is_opted_in:
                        type: boolean
                      latest_opt_in_at:
                        type: string
                        format: date-time
                        nullable: true
                        example: '2023-01-01T12:00:00Z'
                      latest_opt_out_at:
                        type: string
                        format: date-time
                        nullable: true
                        example: '2023-01-01T12:00:00Z'
    post:
      summary: Update the current marketing opt in or opt out for a profile. This will generate an activity.
      description: |
        The current opt in or opt out status can be determined by looking at activities or using the GET request
        on this endpoint.
        If there is an activity of type "marketing_opt_in" and no "marketing_opt_out" after that, the profile
        is opted in.
      tags:
        - profiles
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                opt_in:
                  description: |
                    If a profile is not currently opted in and this field is true, the profile will be opted in.
                    If a profile is already opted in and this field is true, nothing will change.
                    Same applies to setting this field to false and therefore opting out.
                  type: boolean
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Profile"

  /profiles/{profileId}/activities:
    get:
      summary: List activities performed by a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Activity"

  /profiles/{profileId}/activities/{activityId}:
    get:
      summary: Show activity by ID performed by a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
        - in: path
          name: activityId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Activity"

  /profiles/{profileId}/tags:
    get:
      summary: List tags attached to a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"
    post:
      summary: Sync tags with a profile. Tags without ID will be created on the fly.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tags:
                  description: |
                    Array of tag objects. It will automatically determine which IDs to attach or detach.
                    An object should contain either an ID or a title. If an ID is supplied, the existing tag
                    will be attached to the profile. If the ID is missing or null, a tag with that title
                    will be created and attached.
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                        nullable: true
                      title:
                        type: string
                        nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"

  /profiles/{profileId}/tags/{tagId}:
    delete:
      summary: Detach a tag from a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
        - in: path
          name: tagId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"

  /profiles/{profileId}/groups:
    get:
      summary: List groups attached to a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Group"
    post:
      summary: Sync groups with a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                groups:
                  description: |
                    Array of groups objects. It will automatically determine which IDs to attach or detach.
                    An object should contain an ID.
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Group"

  /profiles/{profileId}/groups/{groupId}:
    delete:
      summary: Detach a group from a profile.
      tags:
        - profiles
      parameters:
        - in: path
          name: profileId
          schema:
            type: integer
          required: true
        - in: path
          name: groupId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Group"

  /tags:
    get:
      summary: List available tags. Sorted by title (ASC).
      tags:
        - tags
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"
    post:
      summary: Add a new tag.
      tags:
        - tags
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Tag"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Tag"

  /tags/{id}:
    get:
      summary: Show tag by ID.
      tags:
        - tags
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Tag"
    patch:
      summary: Update a tag.
      tags:
        - tags
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Tag"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Tag"
    delete:
      summary: Delete tag by ID.
      tags:
        - tags
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /groups:
    get:
      summary: List available groups.
      tags:
        - groups
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Group"
    post:
      summary: Add a new group.
      tags:
        - groups
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Group"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Group"

  /groups/{id}:
    get:
      summary: Show group by ID.
      tags:
        - groups
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Group"
    patch:
      summary: Update a group.
      tags:
        - groups
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Group"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Group"
    delete:
      summary: Delete group by ID.
      tags:
        - groups
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /groups/{groupId}/profiles:
    get:
      summary: List profiles attached to a group.
      tags:
        - groups
      parameters:
        - in: path
          name: groupId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Profile"

  /files/temporary-upload:
    post:
      summary: Upload an image, video, audio or document. You can use the return object directly when creating a new message.
      description: |
        An internal UUID will be generated. This UUID will be used instead of providing a public URL to a file.
        When you set public to true, you can use the URL field, which is reachable from public, for use in Whatsapp templates.
        Depending on the given type, mime type validation will take place.
        File will be stored for a maximum of 90 days.
        Special: images will be downsized to 1500px (each side, respecting aspect ratio) to maintain file size limits
        when sending to external services (e.g. WhatsApp limits images to 5MB).
        Special: videos of type video/quicktime (usually from iOS) will be converted to mp4.
      tags:
        - files
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - image
                    - video
                    - audio
                    - document
                public:
                  description: |
                    Optional flag to indicate if the file should be publicly accessible permanently.
                    Use it for WhatsApp campaigns or template sending.
                    Does not work when using the messages endpoint.
                    Only use for files that are not sensitive as anyone with the URL can access the file.
                  type: integer
                  example: 1
                file:
                  type: string
                  format: binary
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  internal_uuid:
                    description: Internal identifier which will be used when creating a new message.
                    type: string
                  public:
                    type: boolean
                    description: |
                      When public, returned URL is valid as long file exists.
                      When not public, URL will be temporary signed URL.
                  url:
                    description: Public reachable URL.
                    type: string
                  name:
                    description: Name of uploaded file.
                    type: string
                  type:
                    description: Type of uploaded file (specified on upload).
                    type: string
                  mime_type:
                    description: Mime type of uploaded file.
                    type: string
                  size:
                    description: Size in bytes of uploaded file.
                    type: integer

  /files/{uuid}:
    get:
      summary: Download file by uuid. This is meant as a fallback for direct API access from backend to backend.
      description: |
        Please use the temporary URL endpoint instead to get a public link.
        This endpoint does not support streaming / seeking.
      tags:
        - files
      parameters:
        - in: path
          name: uuid
          schema:
            type: string
          required: true
      responses:
        "200":
          description: Success
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary

  /files/{uuid}/temporary-url:
    get:
      summary: Generate a valid temporary URL for a private file based on the given UUID.
      description: |
        URL is valid for 7 days.
      tags:
        - files
      parameters:
        - in: path
          name: uuid
          schema:
            type: string
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string

  /media:
    get:
      summary: List available media.
      tags:
        - media
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Media"
    post:
      summary: Add new media.
      tags:
        - media
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - image
                    - video
                    - audio
                    - document
                internal_uuid:
                  description: |
                    UUID of uploaded file.
                    You need to use the temporary upload endpoint to upload a file first.
                  type: string
                title:
                  description: Human readable title of media.
                  type: string
                  nullable: true
                description:
                  description: Human readable description of media.
                  type: string
                  nullable: true
                filename:
                  description: Technical name of the file.
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Media"

  /media/{id}:
    get:
      summary: Show media by ID.
      tags:
        - media
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Media"
    patch:
      summary: Update media.
      tags:
        - media
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  description: Human readable title of media.
                  type: string
                  nullable: true
                description:
                  description: Human readable description of media.
                  type: string
                  nullable: true
                filename:
                  description: Technical name of the file.
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Media"
    delete:
      summary: Delete media by ID.
      tags:
        - media
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /media/{mediaId}/tags:
    get:
      summary: List tags attached to media.
      tags:
        - media
      parameters:
        - in: path
          name: mediaId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"
    post:
      summary: Sync tags with media. Tags without ID will be created on the fly.
      tags:
        - media
      parameters:
        - in: path
          name: mediaId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tags:
                  description: |
                    Array of tag objects. It will automatically determine which IDs to attach or detach.
                    An object should contain either an ID or a title. If an ID is supplied, the existing tag
                    will be attached to the media. If the ID is missing or null, a tag with that title
                    will be created and attached.
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                        nullable: true
                      title:
                        type: string
                        nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"

  /media/{mediaId}/tags/{tagId}:
    delete:
      summary: Detach a tag from media.
      tags:
        - media
      parameters:
        - in: path
          name: mediaId
          schema:
            type: integer
          required: true
        - in: path
          name: tagId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"

  /templates:
    get:
      summary: List available templates.
      tags:
        - templates
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Template"
    post:
      summary: Add a new template.
      tags:
        - templates
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Template"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Template"

  /templates/{id}:
    get:
      summary: Show template by ID.
      tags:
        - templates
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Template"
    patch:
      summary: Update a template.
      tags:
        - templates
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Template"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Template"
    delete:
      summary: Delete template by ID.
      tags:
        - templates
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /marketing/whatsapp-qr-code:
    get:
      summary: Generate WhatsApp link as qr code.
      tags:
        - marketing
      parameters:
        - in: query
          name: agent_id
          description: Optional ID of target agent. If none given, the first WhatsApp agent will be used.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            image/png:
              schema:
                type: string
                format: binary

  /ratings:
    get:
      summary: List all ratings across conversations. Sorted by latest.
      tags:
        - ratings
      parameters:
        - in: query
          name: only_rated
          description: Optional flag to only fetch ratings which the user has completed.
          schema:
            type: integer
            example: 1
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Rating"

  /ratings/{id}:
    get:
      summary: Show rating by ID.
      tags:
        - ratings
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Rating"
    delete:
      summary: Delete rating by ID.
      tags:
        - ratings
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /conversations:
    get:
      summary: List available conversations.
      tags:
        - conversations
      parameters:
        - in: query
          name: name
          description: Optional name of customer. Searches customer and profile in name, username and phone number.
          schema:
            type: string
            nullable: true
          required: false
        - in: query
          name: status
          description: Optional status of conversations.
          schema:
            $ref: "#/components/schemas/ConversationStatus"
          required: false
        - in: query
          name: channel
          description: Optional channel of conversations.
          schema:
            $ref: "#/components/schemas/Channel"
          required: false
        - in: query
          name: user_id
          description: |
            Optional ID of assigned user. Setting to empty will return conversations without assigned user.
            When parameter is not set, conversations with or without assigned user will be returned.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: agent_id
          description: Optional ID of agent.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: customer_id
          description: Optional ID of customer.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: folder_id
          description: |
            Optional ID of assigned folder. Setting to empty will return conversations without assigned folder.
            When parameter is not set, conversations with or without assigned folder will be returned.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: bot_id
          description: |
            Optional ID of running bot. Setting to empty will return conversations without running bot.
            When parameter is not set, conversations with or without running bot will be returned.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: tag_ids
          description: |
            Optional IDs of tags assigned to the customer profile. Matches any of the given IDs.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: group_ids
          description: |
            Optional IDs of groups assigned to the customer profile. Matches any of the given IDs.
          schema:
            type: integer
            nullable: true
          required: false
        - in: query
          name: hide_empty
          description: Optional flag to hide conversations which have no messages.
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: hide_archived
          description: Optional flag to hide conversations that are archived. Default on!
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: hide_read
          description: Optional flag to hide all conversations that are already in "read" state.
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: expires_soon
          description: Optional flag to only show conversations that expire in the next 3 hours.
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: order_by_pinned
          description: Optional flag to order conversations by their pinned status (pinned first).
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: order_by_unread
          description: |
            Deprecated: not supported anymore. Use the filter "hide_read" instead.
            Optional flag to order conversations by their unread customer message status (desc).
          schema:
            type: integer
            example: 1
          required: false
          deprecated: true
        - in: query
          name: order_by_latest_message
          description: |
            Optional flag to order conversations by their latest message sent_at field (desc).
            If not enabled, conversations will be ordered by their created_at field (desc).
          schema:
            type: integer
            example: 1
          required: false
        - in: query
          name: pagination_mode
          description: |
            Optional alternate mode of pagination. Default is offset (page by page).
            You can set to "cursor" to use cursor based pagination. This is useful to
            reproduce an endless scroll experience with updating conversations.
            Caution, when using cursor mode, the paginated result model changes slightly.
          schema:
            type: string
            enum:
              - offset
              - cursor
            nullable: true
            default: offset
          required: false
        - in: query
          name: per_page
          description: Optional number of conversations per page.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - $ref: "#/components/schemas/CursorPaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Conversation"

  /conversations/{id}:
    get:
      summary: Show conversation by ID.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"
    patch:
      summary: Update a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  $ref: "#/components/schemas/ConversationStatus"
                pinned:
                  type: boolean
                archived:
                  type: boolean
                user_id:
                  description: Optional ID of user which should be associated with this conversation.
                  type: integer
                  nullable: true
                folder_id:
                  description: Optional ID of folder which should be associated with this conversation.
                  type: integer
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Conversation"
    delete:
      summary: Delete conversation by ID.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /conversations/{id}/mark-read:
    post:
      summary: Mark all messages in a conversation as read.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                mark_external:
                  description: |
                    Optional flag to decide if the external service behind a message should also be instructed to
                    mark the message as read. If not defined, the value from general settings will be used which
                    will be true by default.
                  type: boolean
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"

  /conversations/{id}/mark-unread:
    post:
      summary: Mark latest customer message in a conversation as unread (delivered).
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"

  /conversations/{id}/mark-typing:
    post:
      summary: |
        Mark the conversation as typing. Customer will see indicator in app.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"

  /conversations/{id}/status:
    patch:
      summary: Update status of conversation.
      description: |
        DEPRECATED: use regular conversation update endpoint.
      deprecated: true
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  $ref: "#/components/schemas/ConversationStatus"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"

  /conversations/{id}/snooze:
    post:
      summary: Snooze a conversation for a given amount of minutes and seconds.
      description: |
        When time is over, status will change to "to-do" and a webhook of type "conversation-snoozed" will be sent.
        Use null or 0 to remove.
        Caution: scheduler will check every minute.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                minutes:
                  type: integer
                  nullable: true
                seconds:
                  type: integer
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Conversation"

  /conversations/{id}/invite-rating:
    post:
      summary: Generate a message containing an invite link for the user to leave a rating.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      text:
                        description: The message which should be sent to the user.
                        type: string
                      link:
                        description: The URL to the rating page (already contained within text if placeholder is used).
                        type: string
                      rating:
                        $ref: "#/components/schemas/Rating"

  /conversations/{id}/restart:
    post:
      summary: If this is a WhatsApp conversation it is possible to restart the conversation by calling this endpoint.
      description: |
        A WhatsApp template message will be sent asking the customer if they want to continue the conversation.
        The template is a marketing message and will cost about 11 cents. This opens up a new 24 hours window for chatting
        as soon as the customer replies with anything (even "No").
        See the "Important" hint in the description of the reply_until field in this document!
        The conversation must have expired before.
      tags:
        - conversations
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"

  /conversations/{conversationId}/messages:
    get:
      summary: List latest (ordered desc) messages of conversation.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: query
          name: from
          description: Optional from filter.
          schema:
            $ref: "#/components/schemas/MessageFrom"
          required: false
        - in: query
          name: status
          description: Optional status filter.
          schema:
            $ref: "#/components/schemas/MessageStatus"
          required: false
        - in: query
          name: per_page
          description: Optional number of messages per page.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Message"
    post:
      summary: Add a message from the agent to a conversation.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                reference_id:
                  description: ID of message within the same conversation this message is referring to.
                  type: integer
                  nullable: true
                from_automation:
                  description: Indicates if the message was sent by an automation. A "new-agent-message" webhook will be triggered if set to true.
                  type: boolean
                  nullable: true
                  default: false
                text:
                  type: object
                  properties:
                    content:
                      type: string
                image:
                  type: object
                  properties:
                    caption:
                      type: string
                      nullable: true
                video:
                  type: object
                  properties:
                    caption:
                      type: string
                      nullable: true
                audio:
                  type: object
                  properties:
                    voice:
                      type: boolean
                document:
                  type: object
                  properties:
                    filename:
                      type: string
                      nullable: true
                    caption:
                      type: string
                      nullable: true
                location:
                  type: object
                  properties:
                    latitude:
                      type: string
                    longitude:
                      type: string
                    remaining_fields:
                      type: string
                      example: See location schema.
                contact:
                  type: object
                  properties:
                    name:
                      type: object
                      properties:
                        formatted_name:
                          type: string
                    remaining_fields:
                      type: string
                      example: See contact schema.
                file:
                  description: |
                    Used when type is image / video / audio / document.
                    See allowed-mime-types endpoint for valid file mime types.
                  type: object
                  properties:
                    url:
                      description: |
                        URL of file to download and re-upload to target messenger service.
                        URL must be available from public. If you do not want to host the file yourself,
                        use the temporary upload endpoint for files.
                        Mime type and size will be determined from response.
                      type: string
                    internal_uuid:
                      description: |
                        See the temporary upload endpoint for files.
                        URL field will be ignored when UUID is given.
                      type: string
                      nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"

  /conversations/{conversationId}/messages/{messageId}:
    get:
      summary: Show message by ID.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"
    delete:
      summary: Delete message by ID. This will not delete messages on external services.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /conversations/{conversationId}/messages/{messageId}/set-reaction:
    post:
      summary: Set agent reaction to message.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                reaction:
                  description: String containing s single emoji. Set null to remove reaction.
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"

  /conversations/{conversationId}/messages/{messageId}/duplicate:
    post:
      summary: Duplicate an existing message. Message must be from agent. Can be used to retry a failed message.
      description: |
        New message will be sent immediately. When message was based on a WhatsApp template,
        the template itself will not be used. Instead, the compiled message will be sent
        as a regular (e.g. text) message.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"

  /conversations/{conversationId}/messages/{messageId}/errors:
    get:
      summary: List message errors.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/MessageError"

  /conversations/{conversationId}/messages/{messageId}/errors/{errorId}:
    get:
      summary: Show message error by ID.
      tags:
        - messages
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: messageId
          schema:
            type: integer
          required: true
        - in: path
          name: errorId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/MessageError"

  /conversation/{conversationId}/notes:
    get:
      summary: List available notes within a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/PaginatedResult"
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: "#/components/schemas/Note"
    post:
      summary: Add a new note to a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Note"

  /conversation/{conversationId}/notes/{noteId}:
    get:
      summary: Show note by ID within a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: noteId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Note"
    patch:
      summary: Update a note within a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: noteId
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Note"
    delete:
      summary: Delete note by ID within a conversation.
      tags:
        - conversations
      parameters:
        - in: path
          name: conversationId
          schema:
            type: integer
          required: true
        - in: path
          name: noteId
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /search/messages:
    post:
      summary: Search for messages. Up to 50 results will be returned. Bot messages will not be included.
      tags:
        - search
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  description: The search term to look for. Uses fuzzy search.
                  type: string
                conversation_id:
                  description: If given, only search for messages in that conversation.
                  type: integer
                  nullable: true
                not_older_than_days:
                  description: Max age of messages. Lower to increase search performance.
                  type: integer
                  default: 30
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          $ref: "#/components/schemas/Channel"
                        message_id:
                          type: integer
                        conversation_id:
                          type: integer
                        customer_id:
                          type: integer
                        profile_id:
                          type: integer
                        profile_name:
                          type: string
                        preview:
                          description: Content of the message which passed the query.
                          type: string
                        score:
                          description: |
                            0 indicates perfect match. 1 means complete mismatch.
                            Only matches with score lower than 0.3 will be returned.
                          type: number

  /search/tags:
    post:
      summary: Search for tags. Up to 100 results will be returned.
      tags:
        - search
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  description: The search term to look for. Case insensitive.
                  type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Tag"

  /search/conversations/by-customers:
    post:
      summary: Find conversations by customer attributes
      description: |
        Returns up to 1000 conversations updated most recently that match the given customer filters.
        At least one of `channels`, `display_ids`, or `profile_ids` must be provided.

        Notes:
        - Filter fields accept comma-separated lists.
        - Results are limited to 1000 and ordered by `updated_at` descending.
      tags:
        - search
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                channels:
                  type: string
                  maxLength: 15000
                  description: |
                    Comma-separated list of channel identifiers (values of the `Channel` enum).
                  example: "whatsapp,facebook"
                display_ids:
                  type: string
                  maxLength: 15000
                  description: |
                    Comma-separated list of customer `display_id` values.
                    For WhatsApp, this can be the phone number in international format WITHOUT the leading `+`.
                    (Only works if WhatsApp customer has shared the phone number.)
                  example: "491711234567,4915777654321"
                profile_ids:
                  type: string
                  maxLength: 15000
                  description: Comma-separated list of `profile_id` values (IDs of related profiles).
                  example: "101,202,303"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Conversation"

  /folders:
    get:
      summary: List available folders. Sorted by title (ASC).
      tags:
        - folders
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Folder"
    post:
      summary: Add a new folder.
      tags:
        - folders
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Folder"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Folder"

  /folders/{id}:
    get:
      summary: Show folder by ID.
      tags:
        - folders
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Folder"
    patch:
      summary: Update a folder.
      tags:
        - folders
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Folder"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Folder"
    delete:
      summary: Delete folder by ID.
      tags:
        - folders
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
        - in: query
          name: delete_conversations
          description: |
            When true (1), conversations in the folder will be deleted instead of
            being moved back into the inbox.
          schema:
            type: boolean
            default: false
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /whatsapp/agent-usage:
    get:
      summary: Get current limit and usage (business initiated conversations) for WhatsApp agent.
      tags:
        - whatsapp
      parameters:
        - in: query
          name: agent_id
          description: Optional ID of target agent. If none given, the first WhatsApp agent will be used.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappAgentUsage"

  /whatsapp/templates:
    get:
      summary: Get list of existing WhatsApp templates.
      tags:
        - whatsapp
      parameters:
        - in: query
          name: group
          description: Optional group filter for templates.
          schema:
            type: string
          required: false
        - in: query
          name: category
          description: Optional category filter.
          schema:
            $ref: "#/components/schemas/WhatsappTemplateCategory"
          required: false
        - in: query
          name: status
          description: Optional status filter.
          schema:
            $ref: "#/components/schemas/WhatsappTemplateStatus"
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappTemplate"
    post:
      summary: "Submit a WhatsApp template for approval. Note: it is not possible to update existing templates via API."
      description: |
        You can manually update templates by visiting the Meta WhatsApp manager.
      tags:
        - whatsapp
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  description: Name of template. Must be lowercase, allowed characters are a-z, 0-9 and underscores.
                  type: string
                language:
                  description: Language of template.
                  example: de
                friendly_name:
                  description: |
                    Optional name for template without the technical naming rules of the regular name. Used for display.
                  type: string
                  nullable: true
                group:
                  description: |
                    Optional group for filtering later.
                    Reserved group names are: system, restart
                  type: string
                  nullable: true
                category:
                  $ref: "#/components/schemas/WhatsappTemplateCategory"
                components:
                  $ref: "#/components/schemas/WhatsappTemplateComponents"
                agent_id:
                  description: Optional ID of WhatsApp agent to use for creating the template. Defaults to first available agent.
                  type: integer
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappTemplate"

  /whatsapp/templates/{id}:
    get:
      summary: Show WhatsApp template by ID.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappTemplate"
    delete:
      summary: Delete WhatsApp template by ID. All languages will be deleted.
      description: |
        Actual deletion will take 4 weeks. You cannot submit a new template
        with a name which is currently in deletion.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /whatsapp/send-template:
    post:
      summary: Send an approved WhatsApp template to a number. Customer and conversation will be created if not
      description: |
        already existing.
      tags:
        - whatsapp
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phone_number:
                  description: |
                    Number of WhatsApp user to send template to. Must be in E.164 format.
                    Only required when not using the customer_id field.
                  type: string
                  example: +4915224367929
                  nullable: true
                customer_name:
                  description: Name of WhatsApp user. Customer will be created with that name if not already exists.
                  type: string
                customer_id:
                  description: |
                    If you already have a customer ID, you can directly use it here instead of providing a phone number.
                    This is useful when dealing with WhatsApp customers that have not shared a phone number yet.
                    When you do not have the phone number, you would not be able to send a template to that customer.
                    When customer ID is given, the phone number field is ignored.
                  type: integer
                  nullable: true
                agent_id:
                  description: ID of WhatsApp agent to use for sending the message.
                  type: integer
                template_name:
                  description: Name of template to send.
                template_language:
                  description: Language of template to send.
                  example: de
                template_components:
                  description: |
                    Array of objects describing how to fill variables within the specified template.
                    If there are no variables, set this to an empty array.
                    Format is defined by WhatsApp. See `components` under https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates
                  type: array
                  items:
                    type: object
                placeholders:
                  type: object
                  description: |
                    Optional key-value object with the values for placeholders when used to fill variables from components.
                    Used as is, no delimiters are added.
                    Example: when you call this endpoint and one of your components contains a custom placeholder like `$my_custom_placeholder$`,
                    you can then fill this object with `{"$my_custom_placeholder$": "my value"}`.
                  nullable: true
                from_automation:
                  description: Indicates if the message was sent by an automation. A "new-agent-message" webhook will be triggered if set to true.
                  type: boolean
                  nullable: true
                  default: false
                assign_bot_id:
                  description: |
                    Optional ID of bot which will be assigned to the conversation.
                    Existing running bot will be stopped and a new one will be started.
                  type: integer
                  nullable: true
                assign_user_id:
                  description: |
                    Optional ID of user the conversation will be assigned to.
                  type: integer
                  nullable: true
                assign_folder_id:
                  description: |
                    Optional ID of folder the conversation will be assigned to.
                  type: integer
                  nullable: true
                assign_tag_id:
                  description: |
                    Optional ID of tag the profile will be assigned to.
                  type: integer
                  nullable: true
                assign_group_id:
                  description: |
                    Optional ID of tag the profile will be assigned to.
                  type: integer
                  nullable: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Message"

  /whatsapp/flows:
    get:
      summary: Get list of existing WhatsApp flows.
      tags:
        - whatsapp
      parameters:
        - in: query
          name: group
          description: Optional group filter for flows.
          schema:
            type: string
          required: false
        - in: query
          name: category
          description: Optional category filter.
          schema:
            type: string
          required: false
        - in: query
          name: status
          description: Optional status filter.
          schema:
            type: string
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappFlow"

  /whatsapp/flows/{id}:
    get:
      summary: Show WhatsApp flow by ID.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappFlow"

  /whatsapp/campaigns:
    get:
      summary: Get list of existing WhatsApp campaigns.
      tags:
        - whatsapp
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"
    post:
      summary: |
        Create a new WhatsApp campaign. To start a campaign, call the start endpoint.
      tags:
        - whatsapp
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpsertWhatsappCampaign"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"

  /whatsapp/campaigns/{id}:
    get:
      summary: Show WhatsApp campaign by ID.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"
    put:
      summary: Update a campaign by ID. Only campaigns with status "draft" can be updated.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpsertWhatsappCampaign"
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"
    delete:
      summary: |
        Delete WhatsApp campaign by ID. Only campaigns that are not "in_progress" can be deleted.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

  /whatsapp/campaigns/{id}/start:
    post:
      summary: Start a campaign by ID. Only campaigns with status "draft" can be started.
      description: |
        There is also a check for template approval status.
        Actual work on campaign will happen when start_at is reached.
        When the daily messaging limit is reached, the campaign will stay in "in_progress"
        together with a datetime in "resume_at".
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"

  /whatsapp/campaigns/{id}/pause:
    post:
      summary: |
        Pause a campaign by ID. Only campaigns with status "in_progress" can be paused.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"

  /whatsapp/campaigns/{id}/resume:
    post:
      summary: Resume a campaign by ID. Only campaigns with status "paused" can be resumed.
      description: |
        Resuming will reset the message limit check.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"

  /whatsapp/campaigns/{id}/cancel:
    post:
      summary: Cancel a campaign by ID. Only campaigns with status "paused" can be canceled.
      description: |
        Canceled campaigns cannot be resumed and are practically read-only.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/WhatsappCampaign"

  /whatsapp/campaigns/{id}/recipients:
    get:
      summary: |
        Get the list of recipients for a campaign by ID.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
        - in: query
          name: per_page
          description: Optional number of recipients per page. Returns full list when omitted.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappCampaignRecipient"
    post:
      summary: Append a batch of recipients to a campaign by ID.
      description: |
        Only campaigns with status "draft" can be modified.
        Meant for recipient lists that are too large for a single request:
        call this repeatedly and set "is_last" on the final batch.
        Send "reset" with the first batch to replace the existing list.
        Phone numbers are normalized, duplicates inside the batch and numbers
        already stored for the campaign are skipped. A batch can therefore be
        sent again after a timeout without creating duplicates.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AppendWhatsappCampaignRecipients"
      responses:
        "200":
          description: |
            Success. Intermediate batches return the result of the batch.
            The final batch ("is_last" = true) returns the campaign itself
            with the batch result in "meta".
          content:
            application/json:
              schema:
                oneOf:
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/WhatsappCampaignRecipientsBatchResult"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/WhatsappCampaign"
                      meta:
                        $ref: "#/components/schemas/WhatsappCampaignRecipientsBatchResult"
    delete:
      summary: Delete all recipients of a campaign by ID.
      description: |
        Only campaigns with status "draft" can be modified.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                        description: Number of deleted recipients.
                        example: 4200
                      total:
                        type: integer
                        description: Recipients left on the campaign, always 0.
                        example: 0

  /whatsapp/campaigns/{id}/statistics:
    get:
      summary: |
        Get the list of statistics for a campaign by ID.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappCampaignStatistics"

  /whatsapp/campaigns/{id}/recipients/export/excel:
    get:
      summary: |
        Get an Excel export of the campaign recipients. Useful for tracking progress and errors.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Excel file download
          content:
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary

  /whatsapp/campaigns/{id}/logs:
    get:
      summary: Get the list of debugging logs for a campaign.
      description: |
        Each event of a campaign is logged.
        Events include start, pause, resume, cancel, hitting messaging limit etc.
        Should not be visible to user since its technical data.
      tags:
        - whatsapp
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        content:
                          type: string
                        created_at:
                          type: string
                          format: date-time
                          example: '2023-01-01T12:00:00Z'

  /metrics/{year}/{month}:
    get:
      summary: Metric by month. Metrics are retained for 180 days.
      tags:
        - metrics
      parameters:
        - in: path
          name: year
          schema:
            type: integer
          required: true
        - in: path
          name: month
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/MetricByDate"

  /deletion-logs/export-csv:
    get:
      summary: Returns a csv file containing all stored deletion logs of the last 3 years.
      tags:
        - deletion logs
      responses:
        "200":
          description: Success
          content:
            text/csv:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeletionLogCsvRow"

  /external-automations/hubspot/auth/redirect:
    get:
      summary: Fetch the redirect URL for the HubSpot OAuth flow.
      tags:
        - external-automations-hubspot
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                        description: |
                          The URL for the HubSpot OAuth flow.
                          Redirect the user to this URL to initiate the OAuth flow.

  /external-automations/hubspot:
    get:
      summary: Get current HubSpot integration status.
      tags:
        - external-automations-hubspot
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/HubspotAutomation"
    patch:
      summary: Update current HubSpot integration.
      tags:
        - external-automations-hubspot
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/HubspotAutomation"

  /external-automations/hubspot/profiles/{id}/contact:
    get:
      summary: Get linked HubSpot contact for a given profile.
      tags:
        - external-automations-hubspot
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/HubspotContact"
    post:
      summary: Create or update HubSpot contact for a given profile.
      tags:
        - external-automations-hubspot
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/HubspotContact"
    delete:
      summary: Unlink HubSpot contact for a given profile. Optionally archive contact on HubSpot as well.
      tags:
        - external-automations-hubspot
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
        - in: query
          name: archive_on_hubspot
          description: Optional boolean flag to archive contact on HubSpot after unlinking.
          schema:
            type: integer
          required: false
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: { }
                    maxItems: 0

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

  schemas:
    PaginatedResult:
      type: object
      properties:
        data:
          description: |
            Default count: 100
          type: array
          items: { }
        links:
          type: object
          properties:
            first:
              type: string
            last:
              type: string
            prev:
              type: string
              nullable: true
            next:
              type: string
              nullable: true
        meta:
          type: object
          properties:
            current_page:
              type: integer
            from:
              type: integer
            to:
              type: integer
            last_page:
              type: integer
            per_page:
              type: integer
            total:
              type: integer
            path:
              type: string
            links:
              type: array
              items: { }
    CursorPaginatedResult:
      type: object
      properties:
        data:
          description: |
            Default count: 100
          type: array
          items: { }
        links:
          type: object
          properties:
            first:
              type: string
            last:
              type: string
            prev:
              type: string
              nullable: true
            next:
              type: string
              nullable: true
        meta:
          type: object
          properties:
            per_page:
              type: integer
            path:
              type: string
            next_cursor:
              type: string
            prev_cursor:
              type: string

    GeneralSettings:
      description: General configuration settings.
      type: object
      properties:
        timezone:
          description: Must be a valid timezone like Europe/Berlin.
          type: string
          default: Europe/Berlin
        default_language:
          type: string
        opening_hours:
          description: |
            Array of opening hours for the configured timezone. 7 entries for each weekday. Starting at monday.
            Each day is an array of periods with start and end time.
          type: array
          minItems: 7
          maxItems: 7
          items:
            type: array
            items:
              type: array
              minItems: 2
              maxItems: 2
              items:
                type: string
            example: [ [ "06:00", "12:00" ], [ "13:00", "20:00" ] ]
        force_close:
          description: |
            Set true to ignore evaluating opening hours and always appear closed.
          type: boolean
          default: false
        send_welcome_message:
          type: boolean
          deprecated: true
          description: Do not use anymore. Create or update a bot instead.
        welcome_message_open:
          description: Do not use anymore. Create or update a bot instead.
          deprecated: true
          type: string
        welcome_message_closed:
          description: Do not use anymore. Create or update a bot instead.
          deprecated: true
          type: string
        custom_tenant_name:
          description: If set, overrides the name used while creating the tenant. Will be displayed for rating.
          type: string
          nullable: true
        custom_notifications_email:
          description: |
            If set, overrides the address used for sending notification emails.
            Default is address used when creating the tenant.
          type: string
          nullable: true
        logo_url:
          description: |
            Link to external logo image. File will be downloaded and field will be replaced with new public reachable URL.
            Image must have mime type of jpeg or png. Dimensions must match (quadratic) and be at least 1024x1024.
            White background preferred.
          type: string
          nullable: true
        primary_color:
          description: Optional hex color for theme. Will be used for rating.
          type: string
          nullable: true
          example: ff00ff
        send_privacy_message:
          type: boolean
          deprecated: true
          description: Do not use anymore. Create or update a bot instead.
        privacy_link:
          description: |
            Optional link to custom privacy policy. If value is set to null, a default privacy
            page URL will be generated from the tenants info. Can be used as $privacy_link$ placeholder in automations.
          type: string
          nullable: true
        privacy_message:
          description: Do not use anymore. Create or update a bot instead.
          deprecated: true
          type: string
        privacy_message_unsafe:
          description: Do not use anymore. Create or update a bot instead.
          deprecated: true
          type: string
        notify_on_message:
          description: |
            Send email notification when a new message arrives and is not read within given amount of minutes.
          type: boolean
        notify_after_minutes:
          description: Number of minutes before the notification will be sent.
          type: integer
        rating_invite_message:
          description: Message template used to generate rating invite. Should contain $link$ placeholder!
          type: string
        rating_external_link:
          description: Link to Google reviews if user gave 4 or 5 stars.
          type: string
          nullable: true
        mark_external_messages_as_read:
          description: |
            If enabled and the mark read endpoint is called,
            the external service will also be instructed to mark their message as read.
            (E.g. for WhatsApp, the customer will get the blue check marks.)
          type: boolean
          default: true
        delete_messages_after_days:
          description: Number of days after a message will be deleted.
          type: integer
          default: 90

    ThirdPartySettings:
      description: Third party configuration settings.
      type: object
      properties:
        webhooks_enabled:
          type: boolean
        webhook_url:
          description: URL for webhook. Must be https.
          type: string
          nullable: true
        webhook_secret:
          description: Secret to sign webhook calls.
          type: string
          nullable: true
        email_landing_url:
          description: URL used in email notifications to direct user to specific page.
          type: string
          nullable: true

    CrmSettings:
      description: CRM configuration settings.
      type: object
      properties:
        custom_field_name_1:
          description: One of five custom field names. See profiles.
          type: string
          nullable: true
        custom_field_name_2:
          type: string
          nullable: true
        custom_field_name_3:
          type: string
          nullable: true
        custom_field_name_4:
          type: string
          nullable: true
        custom_field_name_5:
          type: string
          nullable: true

    Channel:
      description: Type of messenger service.
      type: string
      enum:
        - bridge
        - whatsapp
        - facebook
        - widget

    ConversationStatus:
      description: Status of a conversation.
      type: string
      enum:
        - to-do
        - in-progress
        - done

    ConversationCapability:
      description: Capability of a channel in a conversation.
      type: string
      enum:
        - message_initiate_any
        - message_initiate_template
        - message_receive_any
        - message_reply_any

    Agent:
      description: |
        Represents an agent belonging to a messenger service.
        A business phone number registered on WhatsApp is an agent.
      type: object
      properties:
        id:
          type: integer
          description: Internal ID.
        channel:
          $ref: "#/components/schemas/Channel"
        display_id:
          type: string
          description: An unique identifier within a channel.
          example: 4915223567929
        name:
          type: string
          description: Name received from channel.
          example: John Doe
        in_sync:
          type: boolean
          description: |
            Indicates whether the agent is actually a connected agent (e.g. a WhatsApp number).
            In case of disconnecting a tenants service, this flag will turn false to keep conversations.
            You should not use this agent anymore to send messages as you will receive errors.
        healthy:
          type: boolean
          description: Whether the agent is healthy and can send/receive messages.
          example: true
        unread_conversations_count:
          type: integer
          description: Number of conversation with at least one unread customer message.
        bot_id:
          type: integer
          description: Default bot that should handle new conversations.
          nullable: true
        proxy_email:
          type: string
          description: |
            If given, messages will be sent to this email address.
            When a reply to that email is received, the message will be forwarded to the customer.
          nullable: true
        whatsapp:
          description: Field only available if this agent has channel "whatsapp".
          type: object
          properties:
            is_on_biz_app:
              type: boolean
              description: Whether the agent is connected to a BizApp.
              example: false
            is_missing_funds:
              type: boolean
              description: |
                Whether the agent (360dialog number) needs to pay in order to send billable messages.
                (e.g. WhatsApp marketing template messages)
              example: false

    Profile:
      description: |
        Profile data of a customer. A profile can have many customers. A customer belongs to one profile.
        Can be used to connect a real person with multiple messengers (aka customers) to one profile.
      type: object
      properties:
        id:
          type: integer
        salutation:
          type: string
          enum:
            - formal_male
            - formal_female
            - informal
        name:
          type: string
          example: John Doe
        gender:
          type: string
          enum:
            - undisclosed
            - male
            - female
            - diverse
        blocked:
          type: boolean
          description: If a profile is blocked, receiving messages will be disabled.
        date_of_birth:
          type: string
          format: date
          nullable: true
          example: '1970-01-01'
        phone_number:
          description: Phone number in international format.
          type: string
          nullable: true
          example: '+4915224367929'
        email:
          type: string
          format: email
          nullable: true
        address:
          type: string
          nullable: true
        custom_1:
          description: One of five custom fields. Names of custom fields can be configured via settings.
          type: string
          nullable: true
        custom_2:
          type: string
          nullable: true
        custom_3:
          type: string
          nullable: true
        custom_4:
          type: string
          nullable: true
        custom_5:
          type: string
          nullable: true
        created_at:
          description: Datetime when profile was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when profile was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        customers:
          type: array
          items:
            $ref: "#/components/schemas/Customer"

    ProfileSummary:
      description: |
        Profile data of a customer, without the nested list of other customers on the same profile.
        Used when embedding a profile inside a customer, to avoid re-embedding the customer itself.
      type: object
      properties:
        id:
          type: integer
        salutation:
          type: string
          enum:
            - formal_male
            - formal_female
            - informal
        name:
          type: string
          example: John Doe
        gender:
          type: string
          enum:
            - undisclosed
            - male
            - female
            - diverse
        blocked:
          type: boolean
          description: If a profile is blocked, receiving messages will be disabled.
        date_of_birth:
          type: string
          format: date
          nullable: true
          example: '1970-01-01'
        phone_number:
          description: Phone number in international format.
          type: string
          nullable: true
          example: '+4915224367929'
        email:
          type: string
          format: email
          nullable: true
        address:
          type: string
          nullable: true
        custom_1:
          description: One of five custom fields. Names of custom fields can be configured via settings.
          type: string
          nullable: true
        custom_2:
          type: string
          nullable: true
        custom_3:
          type: string
          nullable: true
        custom_4:
          type: string
          nullable: true
        custom_5:
          type: string
          nullable: true
        created_at:
          description: Datetime when profile was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when profile was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Activity:
      description: |
        Describes an activity performed by a profile. For example, when a customer messages the business for the first
        time, a "privacy message" informing the customer will be sent. This will be persisted as an activity of
        type "privacy_message".
      type: object
      properties:
        id:
          type: integer
        type:
          $ref: "#/components/schemas/ActivityType"
        value:
          description: Optional data for given activity type.
          type: object
          nullable: true
        created_at:
          description: Datetime when activity was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when activity was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    ActivityType:
      description: Type of activity.
      type: string
      enum:
        - customer_initiated_conversation
        - privacy_message
        - welcome_message
        - marketing_opt_in
        - marketing_opt_out
        - rating

    Tag:
      description: |
        Used to further categorize profiles.
      type: object
      properties:
        id:
          type: integer
        title:
          description: Title of tag.
          type: string
        color_hex:
          description: Optional color of tag. Null value should be displayed with a default color.
          type: string
          nullable: true
        created_at:
          description: Datetime when tag was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when tag was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Group:
      description: |
        Used to group profiles.
      type: object
      properties:
        id:
          type: integer
        title:
          description: Title of group.
          type: string
        description:
          description: Description of group.
          type: string
          nullable: true
        created_at:
          description: Datetime when group was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when group was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Customer:
      description: |
        Represents a customer using a messenger service.
        A person with a phone number registered on WhatsApp is a customer.
      type: object
      properties:
        id:
          type: integer
        channel:
          $ref: "#/components/schemas/Channel"
        display_id:
          type: string
          description: An unique identifier within a channel.
          example: 4915223567929
        canonical_id:
          type: string
          nullable: true
          description: |
            Additional ID that identifies the customer. Currently used for WhatsApp.
            In WhatsApp, the display_id is either the phone number or the username.
            The canonical_id is always the BSUID (see WhatsApp usernames documentation).
            For other channels, the canonical_id is not used.
          example: DE.abc123
        name:
          type: string
          description: Name received from channel.
          example: John Doe
        username:
          type: string
          nullable: true
          description: Self given username. See WhatsApp usernames.
          example: john_doe
        profile:
          $ref: "#/components/schemas/ProfileSummary"
        conversations:
          description: Not always included.
          type: array
          items:
            type: object
            properties:
              id:
                type: integer

    Conversation:
      description: |
        A conversation between an agent and a customer.
        Assignable to a user to mark who is actively managing the conversation.
        Assignable to an folder to mark which folder the conversation belongs to.
      type: object
      properties:
        id:
          type: integer
          description: Internal ID.
        folder_id:
          type: integer
          description: |
            Internal ID of folder this conversation belongs to.
            When null, the conversation is not assigned to an folder.
          nullable: true
        created_at:
          description: Datetime when conversation was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        channel:
          $ref: "#/components/schemas/Channel"
        status:
          $ref: "#/components/schemas/ConversationStatus"
        pinned:
          type: boolean
        archived:
          type: boolean
        snooze_until:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        agent:
          $ref: "#/components/schemas/Agent"
        customer:
          $ref: "#/components/schemas/Customer"
        user:
          $ref: "#/components/schemas/User"
        latest_message:
          allOf:
            - $ref: "#/components/schemas/Message"
          nullable: true
        latest_customer_message:
          description: Contains the latest message from the customer, if available.
          allOf:
            - $ref: "#/components/schemas/Message"
          nullable: true
        last_reply_from:
          description: |
            Date and time of the last message received from either customer or agent. This value remains even if
            you delete the last message.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        last_customer_reply_from:
          description: |
            Date and time of the last message received from the customer. This value remains even if
            you delete the last customer message.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        latest_note:
          description: Contains the latest note written from business.
          allOf:
            - $ref: "#/components/schemas/Note"
          nullable: true
        unread_customer_messages_count:
          description: Number of messages from customer which do not have status "read".
          type: integer
        reply_until:
          description: |
            Indicates until when it's possible to send a (free form) reply to this conversation. If a datetime
            in the future is given,
            it should be possible to send a reply without errors (exception: WhatsApp, see below).
            If this field is null, a reply can only be sent if the user
            initiates a new conversation. The timing differs per channel. WhatsApp has the
            most complex rules on sending messages. Currently it's only possible to initiate business messages
            by using pre approved templates. Note: even when this field indicates that no reply is possible,
            you can still call the API to send a reply. You will then receive a message status update from the channel
            if the message could not be delivered.
            Important (WhatsApp): there is the special case when the business initiates a conversation (e.g. using the restart method).
            As soon as the message is sent, a reply_until value will be given from WhatsApp. The business will only be able to
            send more messages if the user replies something within the 24 hour window. So even though this field indicates
            that a reply would be possible, an error will be received when the business tries to send another message without
            user interaction. See the fields "reply_possible" and "customer_interaction_required".
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        reply_possible:
          description: |
            Flag to indicate if a (free form) reply to this conversation is possible. If true, all requirements
            should be met that a message without error can be sent. Use this flag to enable/disable your chat input field.
            The "reply_until" field can be used to show how much time is left until conversation expires.
          type: boolean
        customer_interaction_required:
          description: |
            Flag to indicate if a message from the customer is required. Typical used in combination with the "restart"
            endpoint. After restarting a conversation, the "reply_possible" flag will turn true as soon as the customer
            sends any message.
          type: boolean

    Folder:
      description: |
        Folders are used to group conversations.
        A conversation can be assigned to an folder.
      type: object
      properties:
        id:
          type: integer
          description: Internal ID.
        title:
          description: Title of the folder.
          type: string
        unread_conversations_count:
          type: integer
          description: Number of conversation with at least one unread customer message.

    MessageType:
      description: Type of message content.
      type: string
      enum:
        - text
        - image
        - video
        - audio
        - document
        - location
        - contact

    MessageFrom:
      description: Who wrote the message.
      type: string
      enum:
        - system
        - agent
        - customer

    MessageSource:
      description: What triggered the message.
      type: string
      enum:
        - user
        - bot
        - whatsapp-campaign
        - proxy-mail

    MessageStatus:
      description: Status of message. Created messages have not been sent yet via external API.
      type: string
      enum:
        - created
        - sent
        - delivered
        - read
        - error

    MessageError:
      description: Error description when something went wrong sending/receiving a message.
      type: object
      properties:
        id:
          type: integer
          description: Internal ID.
        message_id:
          type: integer
          description: Foreign ID of related message.
        type:
          type: string
          enum:
            - status-update
            - other
        original_message:
          description: Error message from bridge or messenger service.
          type: string
        user_friendly_message:
          description: If given, contains error message that can be shown to the user.
          type: string
          nullable: true
        created_at:
          description: Datetime when error was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'


    TextMessageContent:
      description: Simple message content containing text.
      type: object
      properties:
        type:
          type: string
          enum:
            - text
        content:
          description: The content of the text message.
          type: string

    FileMessageContent:
      description: Base object for message content having a file.
      type: object
      properties:
        has_file:
          type: boolean
          enum:
            - true
        uuid:
          description: Unique UUID of file. Used to retrieve file data from server.
          type: string
        name:
          description: Name of file.
          nullable: true
        mime_type:
          description: Type of file.
          type: string
          example: audio/ogg
        size:
          description: Size of file in bytes.
          type: integer
        download_url:
          deprecated: true
          description: |
            URL to directly download the file. URL is our API endpoint. Token still needed.
            Please use the public_download_url field instead to get CDN access directly.
          type: string
        public_download_url:
          description: |
            URL to directly download the file without a token.
            WARNING: Temporary valid for 7 days!
          type: string

    ImageMessageContent:
      description: Message content containing an image.
      allOf:
        - $ref: "#/components/schemas/FileMessageContent"
        - type: object
          properties:
            type:
              type: string
              enum:
                - image
            caption:
              description: Caption of image.
              type: string
              nullable: true

    VideoMessageContent:
      description: Message content containing a video.
      allOf:
        - $ref: "#/components/schemas/FileMessageContent"
        - type: object
          properties:
            type:
              type: string
              enum:
                - video
            caption:
              description: Caption of video.
              type: string
              nullable: true

    AudioMessageContent:
      description: Message content containing an audio recording.
      allOf:
        - $ref: "#/components/schemas/FileMessageContent"
        - type: object
          properties:
            type:
              type: string
              enum:
                - audio
            voice:
              description: True if audio is a voice recording.
              type: boolean

    DocumentMessageContent:
      description: Message content containing a document.
      allOf:
        - $ref: "#/components/schemas/FileMessageContent"
        - type: object
          properties:
            type:
              type: string
              enum:
                - document
            filename:
              description: Name of document.
              type: string
              nullable: true
            caption:
              description: Caption of document.
              type: string
              nullable: true

    LocationMessageContent:
      description: Message content containing a GPS location.
      type: object
      properties:
        type:
          type: string
          enum:
            - location
        latitude:
          type: string
        longitude:
          type: string
        address:
          type: string
          nullable: true
        name:
          description: Name of the place.
          type: string
          nullable: true
        url:
          type: string
          nullable: true

    ContactMessageContent:
      description: Message content containing a contact.
      type: object
      required:
        - name
      properties:
        type:
          type: string
          enum:
            - contact
        name:
          type: object
          required:
            - formatted_name
            - first_name
          properties:
            formatted_name:
              type: string
            first_name:
              type: string
              nullable: true
            middle_name:
              type: string
              nullable: true
            last_name:
              type: string
              nullable: true
            prefix:
              type: string
              nullable: true
            suffix:
              type: string
              nullable: true
        birthday:
          type: string
          format: date
          nullable: true
          example: 1970-01-01
        phones:
          type: array
          items:
            type: object
            properties:
              phone:
                type: string
              type:
                type: string
                description: Type of phone number. For example, cell, mobile, main, iPhone, home, work, etc.
        emails:
          type: array
          items:
            type: object
            properties:
              email:
                type: string
              type:
                type: string
                description: Type of email, such as personal or work.
        addresses:
          type: array
          items:
            type: object
            properties:
              street:
                type: string
              city:
                type: string
              state:
                type: string
              zip:
                type: string
              country:
                type: string
              country_code:
                type: string
              type:
                type: string
        org:
          type: object
          properties:
            company:
              type: string
            department:
              type: string
            title:
              type: string

    InteractiveMessageContent:
      description: |
        See all interactive types:
        https://developers.facebook.com/documentation/business-messaging/whatsapp/messages/interactive-cta-url-messages
        Except media carousel. Header supports only text.
      type: object
      properties:
        type:
          type: string
          enum:
            - interactive
        interactive_type:
          type: string
          enum: [ url, button, list, whatsapp_flow, whatsapp_catalog_message, whatsapp_request_contact_info ]
        header_text:
          type: string
          nullable: true
        body_text:
          type: string
        footer_text:
          type: string
          nullable: true
        url_action:
          nullable: true
          type: object
          properties:
            url:
              type: string
              format: uri
            title:
              type: string
        button_action:
          nullable: true
          type: object
          properties:
            buttons:
              type: array
              items:
                type: object
                properties:
                  title:
                    type: string
                  id:
                    type: string
                    nullable: true
        list_action:
          nullable: true
          type: object
          properties:
            title:
              type: string
            sections:
              type: array
              items:
                type: object
                properties:
                  title:
                    type: string
                  rows:
                    type: array
                    items:
                      type: object
                      properties:
                        title:
                          type: string
                        description:
                          type: string
                          nullable: true
                        id:
                          type: string
                          nullable: true
        whatsapp_flow_action:
          nullable: true
          type: object
          properties:
            cta:
              type: string
              description: Text on the button that opens the flow.
            flow_id:
              type: string
            flow_token:
              type: string
              nullable: true
              description: Optional custom value that will be posted back and stored in the meta field of the message.
            screen:
              type: string
              nullable: true
              description: Optional alternate start screen.
            data:
              type: object
              nullable: true
              description: Optional start data for the first screen.
        whatsapp_catalog_action:
          nullable: true
          type: object
          properties:
            thumbnail_product_retailer_id:
              type: string
              nullable: true

    Message:
      description: A message within a conversation.
      type: object
      properties:
        id:
          type: integer
          description: Internal ID.
        conversation_id:
          type: integer
          description: Foreign ID of related conversation.
        from:
          $ref: "#/components/schemas/MessageFrom"
        source:
          $ref: "#/components/schemas/MessageSource"
        user_id:
          description: Id of user who created this message.
          type: integer
          nullable: true
        contents:
          description: |
            A message can contain multiple contents when receiving.
            Usually it is just one item. For example when sending multiple
            contacts with WhatsApp, it will generate one message with multiple
            contacts within the contents array. When sending, only one item in the
            array is allowed.
          type: array
          items:
            anyOf:
              - $ref: "#/components/schemas/TextMessageContent"
              - $ref: "#/components/schemas/ImageMessageContent"
              - $ref: "#/components/schemas/VideoMessageContent"
              - $ref: "#/components/schemas/AudioMessageContent"
              - $ref: "#/components/schemas/DocumentMessageContent"
              - $ref: "#/components/schemas/LocationMessageContent"
              - $ref: "#/components/schemas/ContactMessageContent"
              - $ref: "#/components/schemas/InteractiveMessageContent"
            minLength: 1
        status:
          $ref: "#/components/schemas/MessageStatus"
        agent_reaction:
          description: String containing a single emoji.
          type: string
          nullable: true
        customer_reaction:
          description: String containing a single emoji.
          type: string
          nullable: true
        sent_at:
          description: Datetime when message was sent.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        reference:
          description: Reference to a message within the same conversation.
          type: object
          nullable: true
        latest_error:
          description: Contains the latest error if something went wrong.
          allOf:
            - $ref: "#/components/schemas/MessageError"
          nullable: true
        wa_template_id:
          description: If "source" is "whatsapp-campaign" then this will be the ID of the WhatsApp template used.
          type: integer
          nullable: true
        wa_flow_id:
          description: ID of WhatsApp flow that has been used.
          type: integer
          nullable: true

    Template:
      description: Template to store text with placeholders.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        category:
          description: Category or directory to organize templates one level deep.
          type: string
          nullable: true
        name:
          description: Name of template.
          type: string
        text:
          description: Template text with placeholders.
          type: string
          example: Name of profile is $name$.
        created_at:
          description: Datetime when template was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when template was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Media:
      description: Media used to quickly send files without having to upload them first every time.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        type:
          type: string
          enum:
            - image
            - video
            - audio
            - document
        uuid:
          description: |
            Internal file system UUID.
            Use this UUID when sending messages.
          type: string
        public_download_url:
          description: |
            URL to directly download the file without a token.
            WARNING: Temporary valid for 7 days!
        title:
          description: Human readable title of media.
          type: string
          nullable: true
        description:
          description: Human readable description of media.
          type: string
          nullable: true
        filename:
          description: Technical name of the file.
          type: string
        mime_type:
          description: Mime type of the file.
          type: string
        size:
          description: Size in bytes.
          type: integer
        user_id:
          description: Optional ID of user which uploaded the media.
          type: integer
          nullable: true
        created_at:
          description: Datetime when template was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: Datetime when template was last updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Note:
      description: Note within a conversation. Only visible to business.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        conversation_id:
          type: integer
        text:
          description: Note content.
          type: string
        created_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    Rating:
      description: |
        User fillable rating of a conversation. Users have 2 days to fill out the form.
        If 4 or 5 stars are given, the user will be redirected to a given URL (Google) to
        create a public review if configured.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        code:
          description: Unique ID for URL generation.
          type: string
        stars:
          description: Actual rating. Null if not yet rated.
          type: integer
          nullable: true
        comment:
          description: Optional comment.
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    User:
      description: |
        User from business which operates this app.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        name:
          type: string
        email:
          type: integer
          nullable: true
        roles:
          description: List of roles. "admin" has all permissions implicitly.
          type: array
          items:
            type: string
        permissions:
          description: List of permissions.
          type: array
          items:
            type: string
        has_password:
          type: boolean
        has_pin:
          type: boolean
        created_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    UserNotification:
      type: object
      properties:
        id:
          description: Internal UUID.
          type: string
        created_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        read_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        type:
          type: string
        important:
          type: boolean
        title:
          type: string
        summary:
          type: string
        context:
          type: object

    UpsertWhatsappCampaign:
      type: object
      properties:
        name:
          type: string
        agent_id:
          description: ID of WhatsApp agent to use for creating the campaign.
          type: integer
          nullable: true
        template_name:
          description: Name of template to send.
        template_language:
          description: Language of template to send.
          example: de
        template_components:
          description: |
            Array of objects describing how to fill variables within the specified template.
            If there are no variables, set this to an empty array.
            Format is defined by WhatsApp. See `components` under https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates
          type: array
          items:
            type: object
        recipients:
          type: array
          items:
            type: object
            properties:
              profile_id:
                description: Optional ID of profile. Only used to have a reference. No data is copied from the profile.
                type: integer
                nullable: true
              name:
                description: Optional name of recipient. Phone number is used if not set.
                type: string
                nullable: true
              phone_number:
                description: Required phone number of recipient. Must be in international format. See example.
                type: string
                example: +4915212345678
              placeholders:
                type: object
                description: |
                  Key-value object with the values for placeholders when used to fill variables.
                  Used as is, no delimiters are added.
        start_at:
          description: |
            When to start the campaign in UTC. Only relevant when status is "in_progress".
            When messaging limit is hit for agent, campaign will pause automatically and resume
            the next day at the same time.
          type: string
          format: date-time
          example: '2023-01-01T12:00:00Z'
        send_from:
          description: |
            Together with send_until: time window to send the campaign. Can be used such that customers do not receive
            messages in the middle of the night.
          type: string
          example: '00:00:00'
        send_until:
          description: See send_from.
          type: string
          example: '23:59:59'
        assign_bot_id:
          description: |
            Optional ID of bot which will be assigned to the conversation.
            Existing running bot will be stopped and a new one will be started.
          type: integer
          nullable: true
        assign_user_id:
          description: |
            Optional ID of user the conversation will be assigned to.
          type: integer
          nullable: true
        assign_folder_id:
          description: |
            Optional ID of folder the conversation will be assigned to.
          type: integer
          nullable: true

    WhatsappCampaign:
      description: WhatsApp campaign (marketing).
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        name:
          description: Name of campaign.
          type: string
        agent_id:
          description: ID of connected WhatsApp agent.
          type: string
        wa_template_id:
          description: ID of connected WhatsApp template.
          type: string
        status:
          description: Status of campaign.
          type: string
          enum:
            - ready
            - in_progress
            - paused
            - done
            - canceled
        components:
          description: |
            Array of objects describing how to fill variables within the specified template.
            If there are no variables, set this to an empty array.
            Format is defined by WhatsApp. See `components` under https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates
          type: array
          items:
            type: object
        start_at:
          description: |
            Datetime when to start sending the campaign. Field is only relevant if status is "in_progress".
            Field is also used when messaging limit is reached for the day. Campaign will wait till next day
            same time and continue sending.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        send_from:
          description: |
            Together with send_until: time window to send the campaign. Can be used such that customers do not receive
            messages in the middle of the night.
          type: string
          example: '00:00:00'
        send_until:
          description: See send_from.
          type: string
          example: '23:59:59'
        assign_bot_id:
          description: |
            Optional ID of bot which will be assigned to the conversation.
            Existing running bot will be stopped and a new one will be started.
          type: integer
          nullable: true
        assign_user_id:
          description: |
            Optional ID of user the conversation will be assigned to.
          type: integer
          nullable: true
        assign_folder_id:
          description: |
            Optional ID of folder the conversation will be assigned to.
          type: integer
          nullable: true
        assign_tag_id:
          description: |
            Optional ID of tag the profile will be assigned to.
          type: integer
          nullable: true
        assign_group_id:
          description: |
            Optional ID of tag the profile will be assigned to.
          type: integer
          nullable: true
        resume_at:
          description: |
            When messaging limit is reached for the day, this field will be set to the datetime when the
            campaign will resume.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        finished_at:
          description: |
            Filled when campaign is finished.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        created_at:
          description: |
            When the campaign was created.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        updated_at:
          description: |
            When the campaign was updated.
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'
        recipients_count:
          description: Total number of attached recipients.
          type: integer
        latest_statistics:
          nullable: true
          allOf:
            - $ref: "#/components/schemas/WhatsappCampaignStatistics"

    AppendWhatsappCampaignRecipients:
      type: object
      required:
        - recipients
      properties:
        recipients:
          type: array
          maxItems: 5000
          items:
            $ref: "#/components/schemas/UpsertWhatsappCampaignRecipient"
        reset:
          type: boolean
          default: false
          description: |
            Delete all recipients currently stored on the campaign before
            inserting this batch. Send it with the first batch to restart
            an upload from scratch.
        is_last:
          type: boolean
          default: false
          description: |
            Marks the final batch of an upload. Finalizes the upload, writes a
            campaign log entry and returns the campaign instead of the batch result.

    WhatsappCampaignRecipientsBatchResult:
      type: object
      properties:
        received:
          type: integer
          description: Number of recipients in the request.
          example: 1000
        inserted:
          type: integer
          description: Number of recipients actually stored.
          example: 987
        skipped:
          type: integer
          description: |
            Recipients dropped as duplicates, either within the batch itself or
            because the phone number is already stored on the campaign.
          example: 13
        total:
          type: integer
          description: Total number of recipients on the campaign after this batch.
          example: 4187
        finalized:
          type: boolean
          description: Whether this batch was sent with "is_last".
          example: false

    UpsertWhatsappCampaignRecipient:
      type: object
      required:
        - phone_number
        - placeholders
      properties:
        profile_id:
          type: integer
          nullable: true
          description: ID of an existing profile the recipient belongs to.
        name:
          type: string
          nullable: true
          example: Jane Doe
        phone_number:
          type: string
          maxLength: 128
          description: |
            Formatting characters ("+()-_", space) and a leading "00" are
            stripped, the number is stored as "+<digits>".
          example: "+49123456789"
        placeholders:
          type: object
          additionalProperties:
            type: string
          description: |
            Values for the placeholders of the campaign template, keyed by
            placeholder name. Send an empty object when the template has none.
          example:
            first_name: Jane
            order_id: "12345"

    WhatsappCampaignStatistics:
      description: Statistics of a WhatsApp campaign. Fetched hourly.
      type: object
      properties:
        id:
          type: integer
        campaign_id:
          type: integer
        datetime:
          type: string
          format: date-time
          example: '2023-01-01T12:00:00Z'
        recipients_count:
          type: integer
        to_send_count:
          type: integer
        to_send_percent:
          type: number
        sent_count:
          type: integer
        sent_percent:
          type: number
        delivered_count:
          type: integer
        delivered_percent:
          type: number
        read_count:
          type: integer
        read_percent:
          type: number
        error_count:
          type: integer
        error_percent:
          type: number

    WhatsappCampaignRecipient:
      type: object
      properties:
        id:
          type: integer
        campaign_id:
          type: integer
        profile_id:
          type: integer
          nullable: true
        conversation_id:
          type: integer
          nullable: true
        message_id:
          type: integer
          nullable: true
        name:
          type: string
          nullable: true
        phone_number:
          type: string
        placeholders:
          type: object
          description: |
            Key-value object with the values for placeholders when used to fill variables.
            Used as is, no delimiters are added.
        sent_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    WhatsappTemplateCategory:
      description: Category of template. Determines cost of sending message with this template.
      type: string
      enum:
        - AUTHENTICATION
        - MARKETING
        - UTILITY

    WhatsappTemplateStatus:
      description: |
        Status of template. WhatsApp decides if template is good or if it will be rejected.
        Only "approved" templates can be used to send messages.
        See https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/reference/message_template_status_update
      type: string
      enum:
        - created
        - submitted
        - approved
        - in_appeal
        - pending
        - rejected
        - pending_deletion
        - deleted
        - disabled
        - limit_exceeded
        - archived
        - unarchived
        - flagged
        - locked
        - paused
        - reinstated

    WhatsappTemplateComponents:
      description: |
        Parts of the template (header, body, footer, buttons) with their content.
        Variables like {{1}} can be used per part to make template dynamic.
        Format is defined by WhatsApp. See examples on https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates
      type: array
      items:
        type: object

    WhatsappTemplate:
      description: Template submitted to WhatsApp for approval. Necessary to create business initiated conversations.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        agent_ids:
          description: |
            Array of agent IDs which are capable to send this template.
          type: array
          items:
            type: integer
        group:
          description: Custom group name. Can be null or any value. Useful for filtering when fetching all templates.
          type: string
          nullable: true
        template_id:
          description: WhatsApp internal ID.
          type: string
        namespace:
          description: WhatsApp internal namespace.
          type: string
        name:
          description: Name of template (technical, use friendly name if available for display).
          type: string
        friendly_name:
          description: Name of template in a friendly, readable way.
          type: string
          nullable: true
        language:
          description: Language of template.
          type: string
        category:
          $ref: "#/components/schemas/WhatsappTemplateCategory"
        status:
          $ref: "#/components/schemas/WhatsappTemplateStatus"
        components:
          $ref: "#/components/schemas/WhatsappTemplateComponents"

    WhatsappFlow:
      description: Flow submitted to WhatsApp for approval.
      type: object
      properties:
        id:
          description: Internal ID.
          type: integer
        agent_ids:
          description: |
            Array of agent IDs which are capable to send this flow.
          type: array
          items:
            type: integer
        group:
          description: Custom group name. Can be null or any value. Useful for filtering when fetching all templates.
          type: string
          nullable: true
        flow_id:
          description: WhatsApp internal ID.
          type: string
        namespace:
          description: WhatsApp internal namespace.
          type: string
        name:
          description: Name of flow.
          type: string
        categories:
          type: array
          items:
            type: string
            example: LEAD_GENERATION
        status:
          type: string
          example: PUBLISHED
        json:
          type: string
          description: Actual JSON config of the flow.
        preview_url:
          type: string
          description: Public URL to display or embed the flow preview.
        preview_expires_at:
          type: string
          format: date-time
          nullable: true
          example: '2023-01-01T12:00:00Z'

    WhatsappAgentUsage:
      description: Template submitted to WhatsApp for approval. Necessary to create business initiated conversations.
      type: object
      properties:
        business_initiated:
          type: object
          properties:
            current_usage:
              description: Number of business initiated conversations in the last 24 hour rolling window.
              type: integer
            current_limit:
              description: Max number of conversations this agent can initiate in the given time window (see above).
              type: integer
            limit_exhausted:
              type: boolean

    MetricByDate:
      description: Collected metrics on a monthly basis.
      type: object
      properties:
        year:
          type: integer
        month:
          type: integer
        customer_messages_count:
          description: Number of messages received by customers.
          type: integer
        new_customers_count:
          description: Number of new customers sending a message in this month.
          type: integer
        existing_customers_count:
          description: Number of already existing customers sending a message in this month.
          type: integer
        fresh_conversations_count:
          description: Number of fresh conversations. Fresh = conversation has not been used for more than 24 hours.
          type: integer
        agent_messages_count:
          description: Number of messages sent by agents.
          type: integer
        average_agent_response_time_minutes:
          description: Average time between customer and agent message in minutes.
          type: number
          format: float
        marketing_opt_in_profiles_count:
          description: Number of customers who opted in for marketing this month.
          type: integer
        marketing_opt_out_profiles_count:
          description: Number of customers who opted out for marketing this month.
          type: integer

    DeletionLogCsvRow:
      description: |
        Protocol about data that has been deleted.
      type: object
      properties:
        who:
          type: string
        what:
          type: string
        when:
          type: string
        how:
          type: string

    HubspotAutomation:
      type: object
      properties:
        enabled:
          type: boolean
        hub_id:
          type: string
          nullable: true
        scopes:
          type: array
          nullable: true
          items:
            type: string

    HubspotContact:
      type: object
      properties:
        id:
          type: string
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
        phone_number:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        hubspot_url:
          type: string

    ### Webhooks

    NewMessageWebhook:
      description: Payload of webhook on new customer message.
      type: object
      properties:
        type:
          type: string
          example: 'new-message'
        channel:
          $ref: "#/components/schemas/Channel"
        from:
          type: string
          example: 'customer'
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"
        agent_id:
          type: string
        customer_id:
          type: string
        message_id:
          type: string
        bot_execution_id:
          description: If given, this message was handled by a bot.
          type: string
          nullable: true
        is_new_conversation:
          description: True if completely new customer.
          type: boolean
        is_fresh_conversation:
          description: True if conversation has not been used for more than 24 hours.
          type: boolean

    NewAgentMessageWebhook:
      description: |
        Payload of webhook on new agent message.
        Triggered by echo messages (WhatsApp coexistance), when an automation triggers an action that sends a message,
        or for messages sent by WhatsApp campaigns.
      type: object
      properties:
        type:
          type: string
          example: 'new-agent-message'
        channel:
          $ref: "#/components/schemas/Channel"
        from:
          type: string
          example: 'agent'
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"
        agent_id:
          type: string
        customer_id:
          type: string
        message_id:
          type: string

    StatusUpdateWebhook:
      description: Payload of webhook on status update (message was delivered / read / etc).
      type: object
      properties:
        type:
          type: string
          example: 'status-update'
        channel:
          $ref: "#/components/schemas/Channel"
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"
        agent_id:
          type: string
        customer_id:
          type: string
        message_id:
          type: string
        status:
          $ref: "#/components/schemas/MessageStatus"

    ReactionWebhook:
      description: Payload of webhook on reaction (message emoji added or removed).
      type: object
      properties:
        type:
          type: string
          example: 'reaction'
        channel:
          $ref: "#/components/schemas/Channel"
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"
        agent_id:
          type: string
        customer_id:
          type: string
        message_id:
          type: string
        customer_reaction:
          description: The current customer reaction emoji.
          type: string
          nullable: true
        agent_reaction:
          description: The current agent reaction emoji.
          type: string
          nullable: true

    ConversationSnoozedWebhook:
      description: Payload of webhook when conversation snooze time is over.
      type: object
      properties:
        type:
          type: string
          example: 'conversation-snoozed'
        channel:
          $ref: "#/components/schemas/Channel"
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"

    NewRatingWebhook:
      description: Payload of webhook when a user completed a rating.
      type: object
      properties:
        type:
          type: string
          example: 'new-rating'
        channel:
          $ref: "#/components/schemas/Channel"
        conversation_id:
          type: string
        conversation_status:
          $ref: "#/components/schemas/ConversationStatus"
        rating_id:
          type: string
        customer_id:
          type: string

    AgentsUpdateWebhook:
      description: Payload of webhook when any agent updated (e.g. new agent or name change).
      type: object
      properties:
        type:
          type: string
          example: 'agents-update'

    WhatsappTemplatesUpdateWebhook:
      description: Payload of webhook when any WhatsApp template updated (e.g. new template or approved / rejected).
      type: object
      properties:
        type:
          type: string
          example: 'whatsapp-templates-update'

    WhatsappFlowsUpdateWebhook:
      description: Payload of webhook when any WhatsApp flow updated (e.g. new flow or published / blocked).
      type: object
      properties:
        type:
          type: string
          example: 'whatsapp-flows-update'

    BusinessOpenedWebhook:
      description: Payload of webhook when business opens. Based on general settings opening hours.
      type: object
      properties:
        type:
          type: string
          example: 'business-opened'

    BusinessClosedWebhook:
      description: Payload of webhook when business closes. Based on general settings opening hours.
      type: object
      properties:
        type:
          type: string
          example: 'business-closed'

    NewNotificationWebhook:
      description: Payload of webhook when a new notification is available for a user.
      type: object
      properties:
        type:
          type: string
          example: 'new-notification'
