openapi: 3.1.0
info:
  title: BroadNet CPaaS API
  version: 1.0.0
  description: 'Unified OpenAPI 3.1 specification for the BroadNet CPaaS platform — WhatsApp, SMS, RCS, Telegram, Push, Email,
    Messenger and Instagram. Tenant requests authenticate with `Authorization: Bearer <ACCESS_TOKEN>`; operations marked [operator]
    require an operator token. The `/websmpp/*` operations are the legacy HTTP API kept for SMPP-era integrations (credentials
    as parameters). The official TypeScript/Node.js SDK, @broadnet/cpaas-sdk, is generated from the BroadNet OpenAPI specification.
    This public copy has internal examples, contact details and tooling metadata removed; operations, parameters and schemas
    are unchanged.'
  contact:
    name: BroadNet developers
    email: developers@broadnet.me
    url: https://www.broadnet.me/developers
servers:
- url: https://api.broadnet.me
  description: Production
externalDocs:
  description: BroadNet developer documentation
  url: https://www.broadnet.me/developers
tags:
- name: WhatsApp
  description: WhatsApp channel operations
- name: SMS
  description: SMS channel operations
- name: RCS
  description: RCS channel operations
- name: Telegram
  description: Telegram channel operations
- name: Push
  description: Push channel operations
- name: Email
  description: Email channel operations
- name: Messenger
  description: Messenger channel operations
- name: Instagram
  description: Instagram channel operations
security:
- bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Tenant ACCESS_TOKEN (per-account bearer token).
    operatorAuth:
      type: http
      scheme: bearer
      description: Operator SUPER_TOKEN (platform/operator bearer token).
paths:
  /messenger/clients-onboard:
    post:
      tags:
      - Messenger
      summary: '[operator] Create Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Create a new page

        Create Clients onboard for the Messenger channel (POST /clients-onboard). The request body is a `OnboardedPageRequest`. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /messenger/clients-onboard`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `pageId` | `string` |
        | `pageName` | `string` |
        | `username` | `string` |
        | `accessToken` | `string` |
        | `webhookUrl` | `string` |
        | `qualityRating` | `string` |
        | `description` | `string` |
        | `disableInfo` | `string` |
        | `banInfo` | `string` |
        | `restrictionInfo` | `string` |
        | `sandbox` | `boolean` |
        | `onboardingLink` | `string` |
        | `status` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `passthroughFeeEnabled` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `partnerAppId` | `string` |
        | `webhookToken` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_messenger_clients_onboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pageId:
                  type: string
                pageName:
                  type: string
                username:
                  type: string
                accessToken:
                  type: string
                webhookUrl:
                  type: string
                status:
                  type: string
                rateLimit:
                  type: integer
                tierId:
                  type: integer
            examples:
              '[operator] Create Page':
                value:
                  pageId: NEW_PAGE_001
                  pageName: My New Page
                  username: NewUser
                  accessToken: YOUR_TOKEN
                  webhookUrl: https://example.com/webhook
                  status: ACTIVE
                  rateLimit: 60
                  tierId: 1
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/clients-onboard/update/{MS_PAGE_ID}:
    put:
      tags:
      - Messenger
      summary: '[operator] Update Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update an existing page

        Update Update for the Messenger channel (PUT /clients-onboard/update/{id}). Path parameter `id` identifies the target resource. The request body is a `OnboardedPageRequest`. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `PUT /messenger/clients-onboard/update/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `pageId` | `string` |
        | `pageName` | `string` |
        | `username` | `string` |
        | `accessToken` | `string` |
        | `webhookUrl` | `string` |
        | `qualityRating` | `string` |
        | `description` | `string` |
        | `disableInfo` | `string` |
        | `banInfo` | `string` |
        | `restrictionInfo` | `string` |
        | `sandbox` | `boolean` |
        | `onboardingLink` | `string` |
        | `status` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `passthroughFeeEnabled` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `partnerAppId` | `string` |
        | `webhookToken` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: put_messenger_clients_onboard_update_MS_PAGE_ID
      parameters:
      - name: MS_PAGE_ID
        in: path
        required: true
        schema:
          type: string
        example: MS_PAGE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pageId:
                  type: string
                pageName:
                  type: string
                rateLimit:
                  type: integer
            examples:
              '[operator] Update Page':
                value:
                  pageId: '{{MS_PAGE_ID}}'
                  pageName: Updated Page Name
                  rateLimit: 120
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/clients-onboard/{MS_PAGE_ID}:
    get:
      tags:
      - Messenger
      summary: '[operator] Get Page by ID'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get page by ID

        Get by ID for the Messenger channel (GET /clients-onboard/{id}). Path parameter `id` identifies the target resource. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/clients-onboard/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_clients_onboard_MS_PAGE_ID
      parameters:
      - name: MS_PAGE_ID
        in: path
        required: true
        schema:
          type: string
        example: MS_PAGE_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/clients-onboard/me:
    get:
      tags:
      - Messenger
      summary: '[operator] Get My Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get page by username

        Get by username for the Messenger channel (GET /clients-onboard/me). Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/clients-onboard/me`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_clients_onboard_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/clients-onboard/all:
    get:
      tags:
      - Messenger
      summary: '[operator] Get All Pages (Paginated)'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get all pages with pagination and filters

        Get all for the Messenger channel (GET /clients-onboard/all). Optional: `page`, `size`, `startDate`, `endDate`, `status`, `search`, `toGmt`, `sortBy`, `sortDirection`. Responds with `PaginationResponse<OnboardedPageResponse>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/clients-onboard/all`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `page` | query | no |  (default `0`) |
        | `size` | query | no |  (default `10`) |
        | `startDate` | query | no |  |
        | `endDate` | query | no |  |
        | `status` | query | no |  |
        | `search` | query | no |  |
        | `toGmt` | query | no |  |
        | `sortBy` | query | no |  (default `createdAt`) |
        | `sortDirection` | query | no |  (default `asc`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_clients_onboard_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: asc
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/clients-onboard/delete/NEW_PAGE_001:
    delete:
      tags:
      - Messenger
      summary: '[operator] Delete Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete a page

        Delete Delete for the Messenger channel (DELETE /clients-onboard/delete/{id}). Path parameter `id` identifies the target resource. Responds with `String` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `DELETE /messenger/clients-onboard/delete/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_messenger_clients_onboard_delete_NEW_PAGE_001
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /messenger/oauth/generate-link:
    post:
      tags:
      - Messenger
      summary: Generate OAuth Onboarding Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Generate Encrypted Onboarding Link

        Generates a secure encrypted Messenger onboarding link.

        **Endpoint** `POST /messenger/oauth/generate-link`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_messenger_oauth_generate_link
      responses:
        '200':
          description: OK
  /messenger/message/sendbulk:
    post:
      tags:
      - Messenger
      summary: Text Simple
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### 4.01 TEXT - Simple

        Sent via the unified `{{BASE_URL}}/message/sendbulk` endpoint. This Postman item demonstrates one specific payload shape — see the request body for the exact fields used.

        For lifecycle docs (status / pause / resume / abort / scheduling rules) see the **Bulk & Lifecycle** folder.
      operationId: post_messenger_message_sendbulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                batchId:
                  type: string
                destinationNo:
                  type: string
                allowDuplicate:
                  type: string
                messageType:
                  type: string
                content:
                  type: string
                messagingType:
                  type: string
            examples:
              Text Simple:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Hello from BroadNet!
                  messagingType: RESPONSE
              Text  With Reply To:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: This is a threaded reply
                  messagingType: RESPONSE
                  replyTo: |
                    m_ZFl80qi57bK3LTO8FulXyj_UzyMLCm6RQIzMzRLkY8PvHGoEoyt3MZ-zpRAjNJ266T97xhstiL1R2XuE7-nfWA
              Text Emoji & Unicode:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: 'Emoji: 👋🎉🔥 Arabic: مرحبا Chinese: 测试 Japanese: テスト'
                  messagingType: RESPONSE
              Text  Long (2000 chars max):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                  messagingType: RESPONSE
              Text With Metadata:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Message with metadata tracking
                  messagingType: RESPONSE
                  metadata: order_12345_confirmation
              Text With Persona:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Hi! I'm Sarah from support.
                  messagingType: RESPONSE
                  personaId: PERSONA_ID_HERE
              Image By URL:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  mediaUrl: https://example.com/
                  caption: Image via URL
              Image By File Upload:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  file: MZK8CpKdP/Push flow.jpg
              Image With Reply To:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  mediaUrl: https://cdn.example.com/media/640px-Camponotus_flavomarginatus_ant.jpg
                  caption: Reply image
                  replyTo: m_ORIGINAL_MID
              Video By URL:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  mediaUrl: https://example.com/
                  caption: Video message
              Audio By URL:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  mediaUrl: https://cdn.example.com/media/SoundHelix-Song-1.mp3
              File By URL:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: FILE
                  mediaUrl: https://cdn.example.com/media/file-example_PDF_1MB.pdf
                  fileName: document.pdf
              File By File Upload:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: FILE
                  file: vNKYPD-Zk/sms (1).csv
                  fileName: report.txt
              Template Button (3 buttons, 3 types):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: btn_all_types
                  templatePayloadJson: '{"template_type":"button","text":"Choose an action:","buttons":[{"type":"web_url","url":"https://example.com","title":"Visit
                    Website"},{"type":"postback","title":"Start Chat","payload":"START"},{"type":"phone_number","title":"Call
                    Us","payload":"+447700900100"}]}'
              Template Button With Reply:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: btn_reply
                  templatePayloadJson: '{"template_type":"button","text":"Reply with buttons","buttons":[{"type":"postback","title":"Yes","payload":"YES"},{"type":"postback","title":"No","payload":"NO"}]}'
                  replyTo: m_ORIGINAL_MID
              Template Generic Carousel (2 items):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: carousel
                  templatePayloadJson: '{"template_type":"generic","elements":[{"title":"Product A","subtitle":"$29.99 - Best
                    seller","image_url":"https://cdn.example.com/media/640px-Camponotus_flavomarginatus_ant.jpg","buttons":[{"type":"postback","title":"Buy
                    Now","payload":"BUY_A"},{"type":"web_url","url":"https://example.com/a","title":"Details"}]},{"title":"Product
                    B","subtitle":"$39.99 - New arrival","buttons":[{"type":"postback","title":"Buy Now","payload":"BUY_B"}]}]}'
              Template Media (image):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: media_img
                  templatePayloadJson: |-
                    {
                      "template_type": "media",
                      "elements": [
                        {
                          "media_type": "image",
                          "url": "https://example.com/",
                          "buttons": [
                            {
                              "type": "web_url",
                              "url": "https://example.com",
                              "title": "View More"
                            }
                          ]
                        }
                      ]
                    }
              Template Receipt (order confirmation):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: receipt
                  templatePayloadJson: '{"template_type":"receipt","recipient_name":"John Doe","order_number":"ORD-12345","currency":"USD","payment_method":"Visa
                    4242","summary":{"total_cost":59.99},"elements":[{"title":"Product A","quantity":1,"price":29.99,"currency":"USD"},{"title":"Product
                    B","quantity":1,"price":30.00,"currency":"USD"}]}'
              Quick Replies (3 text options):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: How can we help?
                  quickReplyJson: '[{"content_type":"text","title":"Support","payload":"SUPPORT"},{"content_type":"text","title":"Sales","payload":"SALES"},{"content_type":"text","title":"FAQ","payload":"FAQ"}]'
              Quick Replies With Reply To:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: 'Please choose:'
                  quickReplyJson: '[{"content_type":"text","title":"Yes","payload":"YES"},{"content_type":"text","title":"No","payload":"NO"}]'
                  replyTo: m_ZFl80qi57bK3LTO8FulXyj_UzyMLCm6RQIzMzRLkY8PvHGoEoyt3MZ-zpRAjNJ266T97xhstiL1R2XuE7-nfWA
              MESSAGE_TAG - HUMAN_AGENT (7-day window):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Agent reply outside 24h window
                  messagingType: MESSAGE_TAG
                  messageTag: HUMAN_AGENT
              SILENT_PUSH Notification:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Silent notification heyyyyy
                  messagingType: RESPONSE
                  notificationType: SILENT_PUSH
              NO_PUSH Notification:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: No push at all
                  messagingType: RESPONSE
                  notificationType: NO_PUSH
              Private Reply to Comment:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Thanks for your comment! Check your DM.
                  commentId: FACEBOOK_COMMENT_ID_HERE
              Private Reply to Post:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Thanks for engaging with our post!
                  postId: FACEBOOK_POST_ID_HERE
              Scheduled Message (one-time):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Scheduled reminder
                  scheduled: 'true'
                  scheduleTime: '2026-09-15 12:21:00.000'
                  gmt: +05:30
              Scheduled Recurring (DAILY x3):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Daily update
                  scheduled: 'true'
                  scheduleTime: '2026-04-03 09:00:00.000'
                  gmt: +05:30
                  recurrence: DAILY
                  repeatCount: '3'
              Bulk - Multiple Recipients:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID,27907766498905171
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Bulk message
                  messagingType: RESPONSE
              Bulk - Dedup OFF:
                value:
                  batchId: '0'
                  destinationNo: MS_PSID,MS_PSID
                  allowDuplicate: 'false'
                  messageType: TEXT
                  content: Dedup removes duplicate PSIDs
                  campaignName: DedupTest
              Bulk - With Delay (2s):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Delayed
                  delay: '2'
              Reaction via sendbulk (unified API):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: REACTION
                  replyToMessageId: m_nFKKEIUjqM4FAWhpRFJODj_UzyMLCm6RQIzMzRLkY8PqtzPUvKV0uZE2RHtOT5l3WWBXFI2kfTct-9NAOmB4nw
                  emoji: ❤️
              Reaction Remove (unreact):
                value:
                  batchId: '0'
                  destinationNo: MS_PSID
                  allowDuplicate: 'true'
                  messageType: REACTION
                  replyToMessageId: m_nFKKEIUjqM4FAWhpRFJODj_UzyMLCm6RQIzMzRLkY8PqtzPUvKV0uZE2RHtOT5l3WWBXFI2kfTct-9NAOmB4nw
                  emoji: ❤️
      responses:
        '200':
          description: OK
  /messenger/message/read:
    post:
      tags:
      - Messenger
      summary: Mark Message as Read
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Mark Messenger message as read

        Mark message read for the Messenger channel (POST /message/read). The request body is a `ReadStatusRequest`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /messenger/message/read`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_messenger_message_read
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                recipientId:
                  type: string
                typing:
                  type: boolean
            examples:
              Mark Message as Read:
                value:
                  recipientId: '{{MS_PSID}}'
                  typing: false
              Send Typing ON:
                value:
                  recipientId: '{{MS_PSID}}'
                  typing: true
              Send Typing OFF (mark_seen):
                value:
                  recipientId: '{{MS_PSID}}'
                  typing: false
      responses:
        '200':
          description: OK
  /messenger/templates:
    post:
      tags:
      - Messenger
      summary: Create Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a message template

        Create Templates for the Messenger channel (POST /templates). The request body is a `MessageTemplateRequest`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /messenger/templates`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `templateName` | `string` |
        | `templateType` | `string` |
        | `payloadJson` | `string` |
        | `description` | `string` |
        | `status` | `string` |
        | `category` | `string` |
        | `language` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_messenger_templates
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                templateName:
                  type: string
                templateType:
                  type: string
                payloadJson:
                  type: string
                description:
                  type: string
            examples:
              Create Template:
                value:
                  templateName: welcome_button
                  templateType: BUTTON
                  payloadJson: '{"template_type":"button","text":"Welcome!","buttons":[{"type":"postback","title":"Get Started","payload":"START"},{"type":"web_url","url":"https://example.com","title":"Visit
                    Website"}]}'
                  description: Welcome message with action buttons
      responses:
        '200':
          description: OK
    get:
      tags:
      - Messenger
      summary: Get All Templates (Paginated)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get all templates for user

        Get all for the Messenger channel (GET /templates). Optional: `page`, `size`, `search`, `status`, `templateType`, `sortBy`, `sortDirection`, `toGmt`, `startDate`, `endDate`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/templates`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `page` | query | no |  (default `0`) |
        | `size` | query | no |  (default `10`) |
        | `search` | query | no |  |
        | `status` | query | no |  |
        | `templateType` | query | no |  |
        | `sortBy` | query | no |  (default `createdAt`) |
        | `sortDirection` | query | no |  (default `desc`) |
        | `toGmt` | query | no |  |
        | `startDate` | query | no | Start Date |
        | `endDate` | query | no | End Date |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_templates
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: templateType
        in: query
        required: false
        schema:
          type: string
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: desc
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /messenger/templates/{MS_TEMPLATE_ID}:
    put:
      tags:
      - Messenger
      summary: Update Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update a template

        Update Templates for the Messenger channel (PUT /templates/{id}). Path parameter `id` identifies the target resource. The request body is a `MessageTemplateRequest`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `PUT /messenger/templates/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `templateName` | `string` |
        | `templateType` | `string` |
        | `payloadJson` | `string` |
        | `description` | `string` |
        | `status` | `string` |
        | `category` | `string` |
        | `language` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: put_messenger_templates_MS_TEMPLATE_ID
      parameters:
      - name: MS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: MS_TEMPLATE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                templateName:
                  type: string
                templateType:
                  type: string
                payloadJson:
                  type: string
                description:
                  type: string
            examples:
              Update Template:
                value:
                  templateName: welcome_v2
                  templateType: GENERIC
                  payloadJson: '{"template_type":"generic","elements":[{"title":"Updated"}]}'
                  description: Updated template
      responses:
        '200':
          description: OK
    get:
      tags:
      - Messenger
      summary: Get Template by ID
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get template by ID

        Get by ID for the Messenger channel (GET /templates/{id}). Path parameter `id` identifies the target resource. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/templates/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_templates_MS_TEMPLATE_ID
      parameters:
      - name: MS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: MS_TEMPLATE_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Messenger
      summary: Delete Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a template

        Delete Templates for the Messenger channel (DELETE /templates/{id}). Path parameter `id` identifies the target resource. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `DELETE /messenger/templates/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_messenger_templates_MS_TEMPLATE_ID
      parameters:
      - name: MS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: MS_TEMPLATE_ID
      responses:
        '200':
          description: OK
  /messenger/templates/Templatenames:
    get:
      tags:
      - Messenger
      summary: Get a template by name
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a template by name

        Get by name for the Messenger channel (GET /templates/Templatenames). Required query parameter: `templateName`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/templates/Templatenames`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `templateName` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_templates_Templatenames
      parameters:
      - name: templateName
        in: query
        required: false
        schema:
          type: string
        example: TestTemplate
      responses:
        '200':
          description: OK
  /messenger/templates/grouped-by-category:
    get:
      tags:
      - Messenger
      summary: Get grouped templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get grouped templates

        Get grouped templates for the Messenger channel (GET /templates/grouped-by-category). Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/templates/grouped-by-category`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_templates_grouped_by_category
      responses:
        '200':
          description: OK
  /messenger/message/all-bulk:
    post:
      tags:
      - Messenger
      summary: Get All Bulk Messages
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## List the tenant's bulk campaigns

        Optional filter body supports `status`, `campaignType`, `messageType`, `active`, `scheduled`, date ranges.

        **Status filter accepts** any of: `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED`, `FAILED`.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)
      operationId: post_messenger_message_all_bulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                page:
                  type: string
                size:
                  type: string
                toGmt:
                  type: string
            examples:
              Get All Bulk Messages:
                value:
                  page: '0'
                  size: '10'
                  toGmt: +05:30
              Filter by Status:
                value:
                  page: '0'
                  size: '10'
                  status: INPROGRESS
      responses:
        '200':
          description: OK
  /messenger/message/edit:
    get:
      tags:
      - Messenger
      summary: Get Batch Details
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Load a batch for editing (pauses if live)

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED` (if was INPROGRESS), record returned
      operationId: get_messenger_message_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: MS_BATCH_ID
      responses:
        '200':
          description: OK
  /messenger/message/pause:
    get:
      tags:
      - Messenger
      summary: Pause Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Pause an in-flight batch

        - **Allowed initial status**: `PENDING`, `INPROGRESS`
        - Returns `400` if status is `PAUSED`, `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED`
      operationId: get_messenger_message_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: MS_BATCH_ID
      responses:
        '200':
          description: OK
  /messenger/message/resume:
    get:
      tags:
      - Messenger
      summary: Resume Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Resume a paused batch

        - **Allowed initial status**: `PAUSED` only
        - Returns `400` if status is `PENDING`, `INPROGRESS`, `DONE`, `ABORTED`, `FAILED` (prevents DONE/ABORTED re-fire)
        - On success: status → `INPROGRESS`
      operationId: get_messenger_message_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: MS_BATCH_ID
      responses:
        '200':
          description: OK
  /messenger/message/abort:
    delete:
      tags:
      - Messenger
      summary: Abort Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists
      operationId: delete_messenger_message_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: MS_BATCH_ID
      responses:
        '200':
          description: OK
  /messenger/profile/set:
    post:
      tags:
      - Messenger
      summary: Set - Get Started Button
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Set Messenger profile settings

        Set profile for the Messenger channel (POST /profile/set). The request body is a `MessengerProfile`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /messenger/profile/set`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `get_started` | `GetStarted` |
        | `greeting` | `array` |
        | `persistent_menu` | `array` |
        | `ice_breakers` | `array` |
        | `whitelisted_domains` | `array` |
        | `account_linking_url` | `string` |
        | `commands` | `array` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_messenger_profile_set
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                get_started:
                  type: object
                  properties:
                    payload:
                      type: string
            examples:
              Set - Get Started Button:
                value:
                  get_started:
                    payload: GET_STARTED
              Set - Persistent Menu:
                value:
                  persistent_menu:
                  - locale: default
                    composer_input_disabled: false
                    call_to_actions:
                    - type: postback
                      title: Help
                      payload: HELP
                    - type: postback
                      title: Orders
                      payload: ORDERS
                    - type: web_url
                      title: Website
                      url: https://example.com
              Set - Ice Breakers:
                value:
                  ice_breakers:
                  - question: How can I help?
                    payload: ICE_HELP
                  - question: Track my order
                    payload: ICE_TRACK
      responses:
        '200':
          description: OK
  /messenger/profile:
    get:
      tags:
      - Messenger
      summary: Get Profile Settings
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get Messenger profile settings

        Get profile for the Messenger channel (GET /profile). Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /messenger/profile`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_messenger_profile
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Messenger
      summary: Delete - Greeting
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete Messenger profile setting

        Delete profile for the Messenger channel (DELETE /profile). Required query parameter: `field`. Responds with `ApiResponse<?>` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `DELETE /messenger/profile`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `field` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_messenger_profile
      parameters:
      - name: field
        in: query
        required: false
        schema:
          type: string
        example: GET_STARTED
      responses:
        '200':
          description: OK
  /websmpp/xmlsms:
    post:
      tags:
      - SMS
      summary: XML Message Submission
      description: |-
        The `/websmpp/xmlsms` endpoint is an HTTP POST API used to submit SMS messages in XML format. It enables users to send single or bulk SMS messages to one or multiple recipients in a single request.

        The API supports authentication using either:

        - `username` and `password`, or

        - `accesskey` (as an alternative credential method).


        Users can send different types of messages including English, Unicode, Special Character, and Arabic SMS. Upon successful submission, the system generates a unique `batch_id`, which can be used to track delivery status via the status enquiry API.

        This API is suitable for bulk messaging, system integrations, enterprise notification services, and automated communication workflows.

        ---

        # Response

        ## ✅ Successful Submission

        ``` xml
        <?xml version=&#x27;1.0&#x27; encoding=&#x27;UTF-8&#x27;?><response><status>0</status><batch_id>2002261127504692341</batch_id></response>

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `status` | Status code of the request (`000` indicates success) |
        | `batch_id` | Unique identifier generated for the submitted SMS batch |

        ---

        ## ❌ Error Response

        If the request fails due to validation, authentication, balance, or system issues, the response will be:

        ``` xml
        <response>
          <status>24</status>
          <batch_id></batch_id>
        </response>

         ```
      operationId: post_websmpp_xmlsms
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
            examples:
              XML Message Submission:
                value: |-
                  <?xml version="1.0" encoding="UTF-8"?>
                  <campaign format="1">
                    <SMS>
                      <username>{{username}}</username>
                      <password>{{password}}</password>
                      <type>1</type>
                      <sender>{{sender}}</sender>
                      <text>testing xml request via http</text>
                      <recipients>
                        <gsm>{{destination}}</gsm>
                      </recipients>
                    </SMS>
                  </campaign>
      responses:
        '200':
          description: OK
  /websmpp/xmlstatus:
    post:
      tags:
      - SMS
      summary: XML Status Enquiry
      description: |-
        The `/websmpp/xmlstatus` endpoint is used to retrieve the delivery and processing status of a previously submitted SMS batch.

        After successful SMS submission, a unique `batch_id` is generated. This API allows clients to query the status of all messages associated with that batch. The response includes message-level delivery details such as `messageid`, `msisdn`, `dlrstatus`, and request `status`.

        Authentication is required using either:

        - `username` + `password`, or

        - `accesskey`.


        This API is typically used for:

        - Delivery tracking

        - Reconciliation reporting

        - Monitoring message success/failure

        - Enterprise SMS workflow validation


        ---

        # 📤 Response

        Upon successful status enquiry, the API returns an XML response containing the `batch_id` and one or more `report` entries.

        ---

        ### ✅ Successful Response Example

        ``` xml
        <result>
          <batch_id>1902261008195875539</batch_id>
          <report>
            <messageid>2002261127504692341</messageid>
            <msisdn>447700900101</msisdn>
            <dlrstatus>DELIVRD</dlrstatus>
            <status>000</status>
          </report>
          <report>
            <messageid>2002261127504692342</messageid>
            <msisdn>447700900102</msisdn>
            <dlrstatus>UNDELIV</dlrstatus>
            <status>000</status>
          </report>
        </result>

         ```

        ---

        ### 📊 Response Fields

        | Field | Description |
        | --- | --- |
        | `batch_id` | Batch identifier provided in the request |
        | `report` | Repeated block — one per recipient |
        | `messageid` | Unique message ID generated by SMS system |
        | `msisdn` | Recipient mobile number |
        | `dlrstatus` | Delivery status (DELIVRD, UNDELIV, ATES, UNKNOWN, etc.) |
        | `status` | Request processing status code (000 = success) |

        ---

        ### ❌ Error Response Example

        If authentication fails, batch ID is invalid, or request format is incorrect:

        ``` xml
        <result>
          <batch_id>1902261008195875539</batch_id>
          <report>
            <status>76</status>
          </report>
        </result>

         ```

        Or system-**level** error:

        ``` xml
        <result>
          <error>15</error>
        </result>

         ```
      operationId: post_websmpp_xmlstatus
      requestBody:
        required: true
        content:
          application/xml:
            schema:
              type: string
            examples:
              XML Status Enquiry:
                value: |-
                  <?xml version="1.0" encoding="UTF-8"?>
                  <enquiry>
                    <username>{{username}}</username>
                    <password>{{password}}</password>
                    <batch_id>{{batch_id}}</batch_id>
                  </enquiry>
      responses:
        '200':
          description: OK
  /websmpp/json/sms:
    post:
      tags:
      - SMS
      summary: JSON Message Submission
      description: |-
        The `/websmpp/json/sms` endpoint is an HTTP **POST** API used to submit SMS messages in JSON format.

        It supports **Format 1** (same message to multiple recipients via `gsm` array or address book `group`) and **Format 2** (personalized/custom message per recipient via `custom` array).

        Authentication is via `username` + `password` **or** `accesskey`. On successful submission, a unique `batch_id` is returned which can be used with the Status Enquiry API to track delivery. for full request payload structure and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Submission

        ``` json
        {
          "response": {
            "batch_id": "0302201404163965268",
            "status": "000",
            "description": "No error, operation successful"
          }
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `batch_id` | Unique identifier for the submitted SMS batch. Used to track delivery status. |
        | `status` | `000` indicates successful submission. Any other code indicates an error. |
        | `description` | Human-readable description of the status code. |

        ## ❌ Error Response

        ``` json
        {
          "response": {
            "batch_id": " ",
            "status": "15",
            "description": "Either System_id or password is invalid"
          }
        }

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: post_websmpp_json_sms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                campaign:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
                    format:
                      type: string
                    sender:
                      type: string
                    gsm:
                      type: array
                      items:
                        type: string
                    text:
                      type: string
                    type:
                      type: string
            examples:
              JSON Message Submission:
                value:
                  campaign:
                    username: '{{username}}'
                    password: '{{password}}'
                    format: '1'
                    sender: '{{sender}}'
                    gsm:
                    - '{{destination}}'
                    text: testing normal json api
                    type: '1'
      responses:
        '200':
          description: OK
  /websmpp/json/status:
    post:
      tags:
      - SMS
      summary: JSON Status Enquiry
      description: |-
        The `/websmpp/json/status` endpoint is an HTTP **POST** API that retrieves the delivery and processing status of a previously submitted SMS batch.

        Submit the `batch_id` received at submission time (inside an `enquiry` JSON object) to get per-recipient delivery details. The response includes `messageid`, `msisdn`, `dlr_status`, `request_status`, `submit_date`, and `done_date` for each recipient. for full request payload structure and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "result": {
            "batch_id": "1403261235211472130",
            "report": [
              {
                "request_status": "0",
                "dlr_status": "ATES",
                "done_date": "",
                "messageid": "2603141235411454431",
                "msisdn": "447700900103",
                "submit_date": "2026-03-14 12:35:41"
              },
              {
                "request_status": "0",
                "dlr_status": "ATES",
                "done_date": "",
                "messageid": "2603141235411504441",
                "msisdn": "447700900104",
                "submit_date": "2026-03-14 12:35:42"
              }
            ]
          }
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `batch_id` | The batch ID provided in the request |
        | `report` | Array — one entry per recipient |
        | `messageid` | Unique message ID generated by the SMS system |
        | `msisdn` | Recipient mobile number |
        | `dlr_status` | Delivery status: `DELIVRD`, `UNDELIV`, `ATES`, `SCHEDLD`, `QUEUED`, `UNKNOWN`, etc. |
        | `request_status` | Request processing status code (`000` = success) |
        | `submit_date` | Timestamp when the message was submitted |
        | `done_date` | Timestamp when the delivery report was received |

        ## ❌ Error Response

        ``` json
        {
          "result": {
            "batch_id": "0302201420337911363",
            "report": [
              {
                "messageid": " ",
                "msisdn": " ",
                "dlr_status": " ",
                "request_status": "15",
                "submit_date": "",
                "done_date": ""
              }
            ]
          }
        }

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: post_websmpp_json_status
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enquiry:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
                    batch_id:
                      type: string
            examples:
              JSON Status Enquiry:
                value:
                  enquiry:
                    username: '{{username}}'
                    password: '{{password}}'
                    batch_id: '{{batch_id}}'
      responses:
        '200':
          description: OK
  /websmpp/groupsms:
    get:
      tags:
      - SMS
      summary: Group SMS
      description: |-
        The `/websmpp/groupsms` endpoint is an HTTP **GET** API used to send SMS to a **named address book group** configured in the system. Instead of individual mobile numbers, a group name is passed via the `group` parameter.

        Authentication is via `user` + `pass` **or** `accesskey`.

        ---

        # 📥 Request Parameters

        ### Mandatory Parameters

        | Name | Description |
        | --- | --- |
        | `user` | System ID used for authentication. Example: `super` |
        | `pass` | System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `sid` | Sender ID — alphanumeric or numeric. Example: `test1` |
        | `group` | Name of the address book group. Example: `GR1` |
        | `text` | SMS message content. Example: `Hello Group` |
        | `type` | Message type: `1` = English, `2` = Unicode, `3` = Special Character, `4` = Arabic |

        ### Optional Parameters

        | Name | Description |
        | --- | --- |
        | `accesskey` | Can be used instead of `user` + `pass`. Example: `abc123xyz123456` |
        | `limit` | Max number of recipients per group. Example: `100` |
        | `schtime` | Schedule time. Format: `yyyyMMddhhmm`. Example: `202603072151` |
        | `gmt` | GMT offset for scheduling. Example: `+0530` |
        | `peid` | PE ID for DLT compliance. Example: `1234567890` |
        | `templateid` | DLT Template ID. Example: `9876543210` |
        | `tmid` | Telemarketer ID. Example: `1122334455` |
        | `respformat` | Set to `json` to get response in JSON format |

        ---

        # 📤 Response

        ## ✅ Successful Submission

        ```
        Request processed successfully.

         ```

        ## ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_groupsms
      parameters:
      - name: user
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: pass
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: sid
        in: query
        required: false
        schema:
          type: string
        example: sender
      - name: group
        in: query
        required: false
        schema:
          type: string
        example: GR1
      - name: text
        in: query
        required: false
        schema:
          type: string
        example: Hello+Group
      - name: type
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
  /websmpp/json/mms:
    post:
      tags:
      - SMS
      summary: JSON MMS Submission
      description: |-
        The `/websmpp/json/mms` endpoint is an HTTP **POST** API used to send **MMS (Multimedia Messaging Service)** messages in JSON format.

        Instead of a `text` field, pass a `url` pointing to the media file (image, video, audio, PDF etc.). Supports Format 1 (bulk) and Format 2 (custom per recipient). for full request payload and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Submission

        ``` json
        {
          "response": {
            "batch_id": "2302251030123456789",
            "status": "000",
            "description": "No error, operation successful"
          }
        }

         ```

        ## ❌ Error Response

        ``` json
        {
          "response": {
            "batch_id": " ",
            "status": "15",
            "description": "Either System_id or password is invalid"
          }
        }

         ```
      operationId: post_websmpp_json_mms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                campaign:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
                    sender:
                      type: string
                    gsm:
                      type: array
                      items:
                        type: string
                    url:
                      type: string
            examples:
              JSON MMS Submission:
                value:
                  campaign:
                    username: '{{username}}'
                    password: '{{password}}'
                    sender: '{{sender}}'
                    gsm:
                    - '{{destination}}'
                    url: https://example.com/media/image.jpg
      responses:
        '200':
          description: OK
  /websmpp/api/sms/sender:
    post:
      tags:
      - SMS
      summary: Add Sender
      description: |-
        Adds a Sender ID to the SMSC whitelist.

        Auth: HTTP Basic (username:password) — NOT Bearer. See folder description.
        Body: "Action":"0" = add. SenderATR.SenderShortCode and SenderATR.SenderName are both required.
        If SenderName ends with "-AD" it's registered as Blacklist type, otherwise Whitelist.
      operationId: post_websmpp_api_sms_sender
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                Action:
                  type: string
                SenderATR:
                  type: object
                  properties:
                    SenderShortCode:
                      type: string
                    SenderName:
                      type: string
            examples:
              Add Sender:
                value:
                  Action: '0'
                  SenderATR:
                    SenderShortCode: '1234'
                    SenderName: '{{sender}}'
              Remove Sender:
                value:
                  Action: '1'
                  SenderATR:
                    SenderShortCode: '1234'
                    SenderName: '{{sender}}'
      responses:
        '200':
          description: OK
  /websmpp/websms:
    get:
      tags:
      - SMS
      summary: Send SMS Now (websms)
      description: |-
        Sends an immediate (non-scheduled) SMS. Omit schtime/gmt for immediate delivery.

        Required: user, pass (or accesskey), sid (sender), mno (destination), type, text.
      operationId: get_websmpp_websms
      parameters:
      - name: user
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: pass
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: sid
        in: query
        required: false
        schema:
          type: string
        example: sender
      - name: mno
        in: query
        required: false
        schema:
          type: string
        example: destination
      - name: type
        in: query
        required: false
        schema:
          type: string
        example: '1'
      - name: text
        in: query
        required: false
        schema:
          type: string
        example: hello
      - name: gmt
        in: query
        required: false
        schema:
          type: string
        example: '+0530'
      - name: schtime
        in: query
        required: false
        schema:
          type: string
        example: '202704072151'
      responses:
        '200':
          description: OK
  /websmpp/json/schedulelist:
    post:
      tags:
      - SMS
      summary: Schedule Enquiry (list)
      description: |-
        The `/websmpp/json/schedulelist` endpoint is an HTTP **POST** API that retrieves a list of all **pending scheduled SMS batches** for the authenticated account.

        Send credentials inside a `schedules` JSON object. The response includes `batch_id`, `sender`, `created_on`, and `scheduled_on` for each scheduled entry. Returns error code `053` if no scheduled records are found.

        See [Schedule Enquiry Object](#) for full request payload structure and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "result": [
            {
              "batch_id": "1809231212375377292",
              "created_on": "2023-09-18 12:12:37",
              "sender": "TEST-SCH1",
              "scheduled_on": "18-09-2023 19:16:00"
            },
            {
              "batch_id": "1809231213113911440",
              "created_on": "2023-09-18 12:13:11",
              "sender": "TEST-SCH3",
              "scheduled_on": "19-09-2023 19:16:00"
            }
          ]
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `batch_id` | Unique identifier of the scheduled SMS batch |
        | `created_on` | Timestamp when the schedule was created |
        | `sender` | Sender ID used for the scheduled message |
        | `scheduled_on` | The date and time the SMS is scheduled to be sent |

        ## ❌ Error Response (No Records Found)

        ``` json
        {
          "result": {
            "error": "053"
          }
        }

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: post_websmpp_json_schedulelist
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                schedules:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
            examples:
              Schedule Enquiry (list):
                value:
                  schedules:
                    username: '{{username}}'
                    password: '{{password}}'
      responses:
        '200':
          description: OK
  /websmpp/json/scheduleremove:
    post:
      tags:
      - SMS
      summary: Schedule Removal (by batch_id, JSON)
      description: |-
        Removes one scheduled batch by batch_id, via JSON body under a "schedule" object.

        Required: username+password (OR accesskey), batch_id.
      operationId: post_websmpp_json_scheduleremove
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                schedule:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
                    batch_id:
                      type: string
            examples:
              Schedule Removal (by batch_id, JSON):
                value:
                  schedule:
                    username: '{{username}}'
                    password: '{{password}}'
                    batch_id: '{{batch_id}}'
      responses:
        '200':
          description: OK
  /websmpp/removeschedule:
    get:
      tags:
      - SMS
      summary: Remove Schedule (legacy, by scheduleid)
      description: |-
        The `/websmpp/json/scheduleremove` endpoint is an HTTP **POST** API that **cancels and removes** a previously scheduled SMS batch using its `batch_id`.

        The `batch_id` must be at least 15 characters. Send credentials and the `batch_id` inside a `schedule` JSON object. On success, the scheduled file is deleted and the batch is cancelled. Returns a `failed` status if the batch is not found or credentials are invalid.

        See [Schedule Removal Object](#) for full request payload structure and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Removal

        ``` json
        {
          "result": {
            "batch_id": "0608251139538269564",
            "status": "success",
            "error_code": "000"
          }
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `batch_id` | The batch ID of the removed scheduled entry |
        | `status` | `success` if removed successfully, `failed` otherwise |
        | `error_code` | `000` on success. Any other code indicates an error. |

        ## ❌ Error Response

        ``` json
        {
          "result": {
            "batch_id": "0608251139538269564",
            "status": "failed",
            "error_code": "053"
          }
        }

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_removeschedule
      parameters:
      - name: userid
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: scheduleid
        in: query
        required: false
        schema:
          type: string
        example: scheduleid
      responses:
        '200':
          description: OK
  /websmpp/websmsstatus:
    get:
      tags:
      - SMS
      summary: Web SMS Status
      description: |-
        The `/websmpp/websmsstatus` endpoint is an HTTP **GET** API that retrieves the **delivery status** of a previously submitted SMS using the message response ID (`respid`).

        Optionally pass `format=json` to get a structured JSON response instead of plain text. Pass `username` for additional filtering/logging.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `respid` | **Required.** The message ID returned after successful SMS submission. Example: `2602190836020961011` |
        | `username` | **Optional.** System ID for logging/audit purposes. Example: `super` |
        | `format` | **Optional.** Set to `json` to get a JSON response instead of plain text |

        ---

        # 📤 Response

        ## ✅ Successful Response (Default — Plain Text)

        ```
        DELIVRD

         ```

        ## ✅ Successful Response (`format=json`)

        ``` json
        {
          "msgid": "2602190836020961011",
          "status": "DELIVRD",
          "doneOn": "2024-03-02 14:25:10",
          "errCode": "000"
        }

         ```

        ### DLR Status Values

        | Status | Description |
        | --- | --- |
        | `ATES` | Pending |
        | `DELIVRD` | Delivered |
        | `UNDELIV` | Undelivered |
        | `EXPIRED` | Message Validity Period Expired |
        | `REJECTD` | Rejected |
        | `ACCEPTD` | Accepted |
        | `DELETED` | Deleted |
        | `UNKNOWN` | Unknown |

        ## ❌ Error Response

        ```
        1

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_websmsstatus
      parameters:
      - name: respid
        in: query
        required: false
        schema:
          type: string
        example: batch_id
      - name: username
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: format
        in: query
        required: false
        schema:
          type: string
        example: json
      responses:
        '200':
          description: OK
  /websmpp/api/dlrreport:
    post:
      tags:
      - SMS
      summary: DLR Report
      description: |-
        The `/websmpp/api/dlrreport` endpoint is an HTTP **GET** API that generates and downloads a **Delivery Report (DLR)** in XLSX format for a specified date/time range.

        Authentication is done via `username` + `pass` **or** an `accesskey`. The `from_date` and `to_date` parameters use the format `yyyyMMddHHmmss`.

        ---

        # 📥 Request Parameters

        ### Mandatory Parameters

        | Name | Description |
        | --- | --- |
        | `username` | System ID used for authentication. Example: `super` |
        | `pass` | System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `from_date` | Report start date-time. Format: `yyyyMMddHHmmss`. Example: `20210821124545` |
        | `to_date` | Report end date-time. Format: `yyyyMMddHHmmss`. Example: `20210821164545` |

        ### Optional Parameters

        | Name | Description |
        | --- | --- |
        | `accesskey` | Can be used instead of `username` + `pass`. Example: `abc123xyz` |
        | `sender` | Filter by source/sender address (alphanumeric or numeric). Example: `XYZ` |
        | `is_content` | Include message content in report. `0` = No (default), `1` = Yes |

        ---

        # 📤 Response

        ### ✅ Successful Response

        Returns a downloadable **XLSX file** containing DLR records for the specified date range.

        ### ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: post_websmpp_api_dlrreport
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                username:
                  type: string
                pass:
                  type: string
                from_date:
                  type: string
                to_date:
                  type: string
                is_content:
                  type: string
                sender:
                  type: string
            examples:
              DLR Report:
                value:
                  username: username
                  pass: password
                  from_date: '20250901000000'
                  to_date: '20270907000000'
                  is_content: '1'
                  sender: sender
      responses:
        '200':
          description: OK
  /websmpp/hlr/lookup:
    get:
      tags:
      - SMS
      summary: HLR Lookup
      description: |-
        The `/websmpp/hlr/lookup` endpoint is an HTTP **GET** API used to perform a **Home Location Register (HLR) lookup** on one or more destination numbers.

        This queries the live network to determine whether a number is active, its IMSI, MSC, network code, roaming status, and ported status.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `username` | **Required.** System ID for authentication. Example: `super` |
        | `password` | **Required.** System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `destination` | **Required.** Destination number(s) with country code, comma-separated. Example: `447700900103` |

        ---

        # 📤 Response

        ## ✅ Successful Response

        Returns a `BatchId` that can be used with the HLR Report endpoint:

        ```
        BatchId: 1403261203174891273

         ```

        ## ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_hlr_lookup
      parameters:
      - name: username
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: destination
        in: query
        required: false
        schema:
          type: string
        example: destination
      responses:
        '200':
          description: OK
  /websmpp/hlr/lookupandresult:
    get:
      tags:
      - SMS
      summary: HLR Lookup And Result
      description: |-
        The `/websmpp/hlr/lookupandresult` endpoint is an HTTP **GET** API that performs an **HLR lookup AND immediately returns the result** in a single call.

        Unlike `/hlr/lookup` (which returns only a BatchId for async polling), this endpoint waits and returns the full lookup result inline.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `username` | **Required.** System ID for authentication. Example: `super` |
        | `password` | **Required.** System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `destination` | **Required.** Destination number(s) with country code, comma-separated. Example: `447700900103` |

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        0 :  No error, operation successful

         ```

        ## ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_hlr_lookupandresult
      parameters:
      - name: username
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: destination
        in: query
        required: false
        schema:
          type: string
        example: destination
      responses:
        '200':
          description: OK
  /websmpp/hlr/report:
    get:
      tags:
      - SMS
      summary: HLR Report
      description: |-
        The `/websmpp/hlr/report` endpoint is an HTTP **GET** API used to retrieve the **HLR lookup result** for a previously submitted batch using its `batchid`.

        Use this after submitting a lookup via `/websmpp/hlr/lookup` which returns a `BatchId`.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `batchid` | **Required.** The batch ID returned from the HLR Lookup request. Example: `2302251030123456789` |

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "id": "12345",
          "batchid": "2302251030123456789",
          "destination": "447700900103",
          "time": "2024-03-02 14:20:33",
          "status": "active",
          "error_code": "000",
          "error": "",
          "imsi": "404451234567890",
          "msc": "447700900105",
          "cc": "91",
          "nnc": "9826",
          "isPorted": "N",
          "p_nnc": "",
          "isRoaming": "N",
          "r_cc": "",
          "r_nnc": ""
        }

         ```

        ## ❌ Error Response (No Record)

        ```
        No Record Found

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_hlr_report
      parameters:
      - name: batchid
        in: query
        required: false
        schema:
          type: string
        example: batch_id
      responses:
        '200':
          description: OK
  /websmpp/mnp/report:
    get:
      tags:
      - SMS
      summary: MNP Report
      description: |-
        The `/websmpp/mnp/report` endpoint is an HTTP **GET** API used to retrieve **Mobile Number Portability (MNP)** lookup results for a submitted batch using its `batchid`.

        MNP lookup determines whether a number has been ported to another operator.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `batchid` | **Required.** The batch ID from a previous MNP lookup request. Example: `2302251030123456789` |

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "id": "12345",
          "batchid": "2302251030123456789",
          "destination": "447700900103",
          "time": "2024-03-02 14:20:33",
          "error_code": "000",
          "error": "",
          "cc": "91",
          "nnc": "9826",
          "isPorted": "Y",
          "p_nnc": "9869",
          "isRoaming": "N",
          "r_cc": "",
          "r_nnc": ""
        }

         ```

        ## ❌ Error Response (No Record)

        ```
        No Record Found

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_mnp_report
      parameters:
      - name: batchid
        in: query
        required: false
        schema:
          type: string
        example: batch_id
      responses:
        '200':
          description: OK
  /websmpp/balanceReport:
    get:
      tags:
      - SMS
      summary: Balance Enquiry (legacy)
      description: |-
        The `/websmpp/balanceReport` endpoint is an HTTP **GET** API that retrieves the current **SMS credit balance** for the authenticated account.

        Authentication is done via `userid` + `password` **or** an `accesskey`. Both `userid` and `password` are mandatory if `accesskey` is not provided.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `userid` | System ID used for authentication. Example: `super` |
        | `password` | System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `accesskey` | Can be used instead of `userid` + `password`. Example: `abc123xyz` |

        > \* Either `userid` + `password` **OR** `accesskey` is required.


        ---

        # 📤 Response

        ### ✅ Successful Response

        ```
        Balance: 10000.00

         ```

        ### ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_balanceReport
      parameters:
      - name: userid
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: password
      responses:
        '200':
          description: OK
  /websmpp/downloadcoverage:
    get:
      tags:
      - SMS
      summary: Coverage Download
      description: |-
        The `/websmpp/downloadcoverage` endpoint is an HTTP **GET** API that allows users to download the **SMS coverage and routing list** in their preferred format (XLS, PDF, or CSV).

        Authentication is done via `userid` + `password` **or** an `accesskey`. The `format` parameter is optional and defaults to `1` (XLS).

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `userid` | System ID used for authentication. Example: `super` |
        | `password` | System password. Example: `{{SMS_LEGACY_PASSWORD}}` |
        | `accesskey` | Can be used instead of `userid` + `password`. Example: `abc123xyz` |
        | `format` | Download format. Optional. Default is `1`. Values: `1` = XLS, `2` = PDF, `3` = CSV |

        > \* Either `userid` + `password` **OR** `accesskey` is required.


        ### Format Values

        | Value | Downloaded Format |
        | --- | --- |
        | 1 | XLS (default) |
        | 2 | PDF |
        | 3 | CSV |

        ---

        # 📤 Response

        ### ✅ Successful Response

        Returns a **file download** in the requested format containing the full SMS coverage list.

        ### ❌ Error Response

        ```
        15

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_downloadcoverage
      parameters:
      - name: userid
        in: query
        required: false
        schema:
          type: string
        example: username
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: password
      - name: format
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
  /websmpp/otprequest:
    get:
      tags:
      - SMS
      summary: OTP Request
      description: |-
        The `/websmpp/otp/request` endpoint is an HTTP **GET** API used to generate and retrieve a **One-Time Password (OTP)** for a specified system user.

        If a valid (non-expired) OTP already exists for the user, it is returned. Otherwise, a new 6-digit OTP is generated and saved with an expiry timestamp.

        ---

        # 📥 Request Parameters

        | Name | Description |
        | --- | --- |
        | `username` | **Required.** System ID of the user for whom OTP is requested. Example: `super` |

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "status": "0",
          "otp": "482951",
          "expiresOn": "2024-03-02 14:50:33"
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `status` | `0` = Success, any other value = Error |
        | `otp` | The 6-digit one-time password |
        | `expiresOn` | OTP expiry date-time in `yyyy-MM-dd HH:mm:ss` format |

        ## ❌ Error Response

        ``` json
        {
          "status": "15",
          "otp": "0",
          "expiresOn": ""
        }

         ```

        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_otprequest
      parameters:
      - name: username
        in: query
        required: false
        schema:
          type: string
        example: username
      responses:
        '200':
          description: OK
  /websmpp/webbalance:
    post:
      tags:
      - SMS
      summary: Web Balance (OTP-based)
      description: |-
        The `/websmpp/web/balance` endpoint is an HTTP **POST** API that retrieves the **current credit/wallet balance** of a specified user account.

        Useful for resellers to check sub-account balances or for any user to check their own balance. for full request payload and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Response

        ``` json
        {
          "status": "0",
          "target_user": "super",
          "balance_mode": "credit",
          "amount": "10000.00"
        }

         ```

        ### Response Fields

        | Field | Description |
        | --- | --- |
        | `status` | `0` = Success |
        | `target_user` | The user account queried |
        | `balance_mode` | `credit` or `wallet` |
        | `amount` | Current balance amount |

        ## ❌ Auth Error

        ``` json
        {
          "status": "15",
          "target_user": "",
          "balance_mode": "",
          "amount": "0"
        }

         ```
      operationId: post_websmpp_webbalance
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                password:
                  type: string
                target_user:
                  type: string
            examples:
              Web Balance (OTP-based):
                value:
                  username: '{{username}}'
                  password: '{{otp}}'
                  target_user: '{{target_user}}'
      responses:
        '200':
          description: OK
  /websmpp/web/recharge:
    post:
      tags:
      - SMS
      summary: Web Recharge (OTP-based)
      description: |-
        The `/websmpp/web/recharge` endpoint is an HTTP **POST** API used to **add or deduct balance** for a target user account.

        Use `operation: "plus"` to top-up and `operation: "minus"` to deduct. Supports both `credit` and `wallet` balance modes. for full request payload and parameter reference.

        ---

        # 📤 Response

        ## ✅ Successful Recharge

        ``` json
        {
          "status": "0"
        }

         ```

        ## ❌ Error Response

        ``` json
        {
          "status": "75"
        }

         ```

        ### Status Codes for Recharge

        | Code | Description |
        | --- | --- |
        | 0 | Success |
        | 75 | Invalid target user |
        | 78 | Invalid operation (must be `plus` or `minus`) |
        | 15 | Invalid credentials |
        | 16 | Insufficient balance (for deduction) |
      operationId: post_websmpp_web_recharge
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                password:
                  type: string
                target_user:
                  type: string
                amount:
                  type: string
                operation:
                  type: string
                balance_mode:
                  type: string
            examples:
              Web Recharge (OTP-based):
                value:
                  username: '{{username}}'
                  password: '{{otp}}'
                  target_user: '{{target_user}}'
                  amount: '100'
                  operation: plus
                  balance_mode: wallet
      responses:
        '200':
          description: OK
  /websmpp/Hlr/Result:
    get:
      tags:
      - SMS
      summary: the carrier HLR Result Callback
      description: |-
        The `/websmpp/Hlr/Result` endpoint is an HTTP **GET** inbound callback that receives **HLR (Home Location Register) lookup results** posted asynchronously by the **carrier** after processing an HLR request.

        This endpoint is registered as the callback URL with the carrier. When the carrier completes the HLR lookup, it calls this URL with the result parameters. The system processes and stores the result, then responds with `Ok`.

        # 📥 Request Parameters

        This is a **GET/POST callback endpoint** — parameters are posted by the carrier system as query parameters:

        | Name | Description |
        | --- | --- |
        | `id` | **Required.** Unique message/result ID from the carrier. Example: `msg_abc123def456` |
        | `reference` | **Required.** Reference ID linking back to the original HLR request batch. Example: `2302251030123456789` |
        | `msisdn` | **Required.** The destination number that was looked up (with country code). Example: `447700900103` |
        | `status` | **Required.** HLR lookup result status from the carrier. Example: `active`, `absent`, `unknown` |
        | `createdDatetime` | **Required.** Timestamp when the HLR request was created. Format: `yyyy-MM-dd HH:mm:ss`. Example: `2024-03-02 14:20:33` |
        | `statusDatetime` | **Required.** Timestamp when the status was last updated. Format: `yyyy-MM-dd HH:mm:ss`. Example: `2024-03-02 14:21:10` |

        ---

        # 📤 Response

        ```
        Ok

         ```

        The endpoint always responds with `Ok` to acknowledge receipt of the DLR callback from the carrier. The system internally logs and processes the result.

        > **Note:** This endpoint is invoked by the **carrier/route system **, not by end users directly. It is the callback URL that must be registered with the carrier during HLR setup.


        ---

        # Status Code Table

        | Code | Name | Description |
        | --- | --- | --- |
        | 000 | NO_ERROR | Success |
        | 15 | ESME_RINVSYSID | Either System_id or password is invalid |
        | 003 | ESME_RINVCMDID | Invalid command ID / request |
        | 18 | ESME_RACCEXP | Account has been Expired |
        | 16 | ESME_RINSBAL | Insufficient balance |
        | 11 | ESME_RINVDSTADR | Invalid Destination Address |
        | 9 | ESME_RCOVERR | Requested Destination is not Allowed |
        | 8 | ESME_RSYSERR | System Error |
        | 10 | ESME_RINVSRCADR | Invalid Source Address |
        | 1 | ESME_RINVMSGLEN | Invalid message Length |
        | 22 | ESME_RACCBLOCK | Either Web Access Not Allowed or Account is Blocked |
        | 74 | ESME_RIOSTREAMERR | Input Stream Error |
        | 76 | ESME_RINVBATCHID | Invalid Batch Id (must be 15 digits) |
        | 78 | ESME_RINVOPERATION | Invalid operation (must be plus or minus) |
        | 75 | ESME_RINVTARUSER | Invalid target User to recharge |
        | 24 | ESME_RINVACCIP | Access IP not valid |
        | 71 | ESME_RINVOTP | Invalid OTP |
        | 44 | ESME_RPASSEXP | Password Expired |
      operationId: get_websmpp_Hlr_Result
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: '123456789876543'
      - name: reference
        in: query
        required: false
        schema:
          type: string
        example: batch_id
      - name: msisdn
        in: query
        required: false
        schema:
          type: string
        example: destination
      - name: status
        in: query
        required: false
        schema:
          type: string
        example: active
      - name: createdDatetime
        in: query
        required: false
        schema:
          type: string
        example: 2024-03-02%2014:20:33
      - name: statusDatetime
        in: query
        required: false
        schema:
          type: string
        example: 2026-09-02%2014:21:10
      responses:
        '200':
          description: OK
  /websmpp/json/route:
    post:
      tags:
      - SMS
      summary: Route/Delivery Status Webhook
      description: |-
        ### Json Route Response

        Json Route Response — legacy websmpp HTTP API (POST /websmpp/json/route). Authenticates with the account credentials passed as parameters (legacy scheme); responses are plain text / XML / JSON as the endpoint name indicates. Kept for existing integrations — new integrations should use the `/sms` API.

        **Endpoint** `POST /websmpp/json/route`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_websmpp_json_route
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                message_uuid:
                  type: string
                status:
                  type: string
            examples:
              Route/Delivery Status Webhook:
                value:
                  message_uuid: '{{batch_id}}'
                  status: delivered
      responses:
        '200':
          description: OK
  /websmpp/web/action:
    post:
      tags:
      - SMS
      summary: Web DLR Action Webhook
      description: |-
        ### Web DLRAction

        Web DLRAction — legacy websmpp HTTP API (POST /websmpp/web/action). Parameters: `Destination`, `DoneDate`, `MessageId`, `Source`, `Status`, `SubmitDate`, `mcc`, `mnc`. Authenticates with the account credentials passed as parameters (legacy scheme); responses are plain text / XML / JSON as the endpoint name indicates. Kept for existing integrations — new integrations should use the `/sms` API.

        **Endpoint** `POST /websmpp/web/action`

        **Request body** `application/x-www-form-urlencoded`

        | Field | Type |
        | --- | --- |
        | `Destination` | `string` |
        | `DoneDate` | `string` |
        | `MessageId` | `string` |
        | `Source` | `string` |
        | `Status` | `string` |
        | `SubmitDate` | `string` |
        | `mcc` | `string` |
        | `mnc` | `string` |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_websmpp_web_action
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                MessageId:
                  type: string
                Source:
                  type: string
                Destination:
                  type: string
                Status:
                  type: string
                SubmitDate:
                  type: string
                DoneDate:
                  type: string
                mcc:
                  type: string
                mnc:
                  type: string
            examples:
              Web DLR Action Webhook:
                value:
                  MessageId: batch_id
                  Source: sender
                  Destination: destination
                  Status: DELIVRD
                  SubmitDate: ''
                  DoneDate: ''
                  mcc: ''
                  mnc: ''
      responses:
        '200':
          description: OK
  /websmpp/url/request/test:
    get:
      tags:
      - SMS
      summary: URL Request Test
      description: |-
        ### Url Request Test

        Url Request Test — legacy websmpp HTTP API (POST /websmpp/url/request/test). Authenticates with the account credentials passed as parameters (legacy scheme); responses are plain text / XML / JSON as the endpoint name indicates. Kept for existing integrations — new integrations should use the `/sms` API.

        **Endpoint** `POST /websmpp/url/request/test`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_websmpp_url_request_test
      parameters:
      - name: ping
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
  /sms/sendSms:
    post:
      tags:
      - SMS
      summary: Quick SMS
      description: |-
        The `/sms/sendSms` endpoint is an HTTP **POST** API used to submit a **single SMS message** to a specified destination number via the SMPP gateway. Supports both instant and scheduled delivery.

        > 💡 Use `POST /sms/identify` to calculate `messageType`, `charCount`, `smsParts`, and `charLimit` before calling this endpoint.


        # 📤 Response

        ```
        2603121407537573731

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |

        Notes from the example body: Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional
      operationId: post_sms_sendSms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                senderId:
                  type: string
                destinationNumber:
                  type: string
                message:
                  type: string
                messageType:
                  type: string
                charCount:
                  type: integer
                smsParts:
                  type: integer
                charLimit:
                  type: integer
                expiryHour:
                  type: integer
                isSchedule:
                  type: boolean
                delay:
                  type: number
                gmt:
                  type: string
                time: {}
                repeat: {}
                peId:
                  type: string
                templateId:
                  type: string
                telemarketerId:
                  type: string
                campaignName:
                  type: string
            examples:
              Quick SMS:
                value:
                  senderId: ACME-ALRT
                  destinationNumber: '447700900101'
                  message: 'Emergency Alert: Fire drill in progress. Please evacuate calmly.'
                  messageType: TEXT
                  charCount: 62
                  smsParts: 1
                  charLimit: 160
                  expiryHour: 24
                  isSchedule: false
                  delay: 0.0
                  gmt: +05:30
                  time: null
                  repeat: null
                  peId: '1001234567890'
                  templateId: '1007232314558898'
                  telemarketerId: '110200100000001'
                  campaignName: FireDrillAlert
      responses:
        '200':
          description: OK
  /sms/sendSmsGroupData:
    post:
      tags:
      - SMS
      summary: Group Data SMS
      description: |-
        The `/sms/sendSmsGroupData` endpoint is an HTTP **POST** API used to send a single SMS message to multiple recipients provided directly within the request body.

        This API accepts an array of destination mobile numbers under the `contacts` field and submits the message immediately to the SMPP gateway for processing.

        It is designed for small group messaging scenarios where recipient numbers are already available in the application and file upload is not required.

        The request must include valid encoding details (`messageType`, `charCount`, `smsParts`, `charLimit`) to ensure accurate message segmentation and credit calculation.

        ---

        # 📤 Success Response — `SmsResponse`

        ## 🔎 Example JSON Response

        ``` json
        {
            "credits": "9963550.00610",
            "deductcredits": "0.40000",
            "status": "success",
            "bulkSessionId": "super_20260307094302680",
            "bulkListInfo": {
                "total": 2,
                "validCount": 2,
                "invalidCount": 0,
                "duplicate": 0,
                "errors": null
            }
        }

         ```

        ---

        # 📋 Response Fields

        | Field | Description |
        | --- | --- |
        | `respMsgId` | Unique message reference ID assigned by the SMPP gateway |
        | `msgCount` | Total number of SMS segments submitted (based on recipients × message parts) |
        | `credits` | Remaining account credit balance after submission |
        | `deductcredits` | Total credits deducted for this request |
        | `status` | Submission result — `SUBMITTED` or `FAILED` |

        ---

        Notes from the example body: Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional
      operationId: post_sms_sendSmsGroupData
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                campaignName:
                  type: string
                senderId:
                  type: string
                message:
                  type: string
                messageType:
                  type: string
                smsParts:
                  type: integer
                charCount:
                  type: integer
                charLimit:
                  type: integer
                smscount:
                  type: string
                uploadedNumbers:
                  type: string
                totalContact:
                  type: string
                delay:
                  type: string
                schedule:
                  type: boolean
                gmt:
                  type: string
                timestart:
                  type: string
                repeat:
                  type: string
                tracking:
                  type: boolean
                expiryHour:
                  type: string
                exclude:
                  type: string
                groupId:
                  type: integer
            examples:
              Group Data SMS:
                value:
                  campaignName: groupdata
                  senderId: TESTCO
                  message: mesage text
                  messageType: GSM-7
                  smsParts: 1
                  charCount: 11
                  charLimit: 160
                  smscount: '1'
                  uploadedNumbers: |-
                    447700900106
                    447700900107
                  totalContact: '2'
                  delay: '99'
                  schedule: true
                  gmt: GMT+05:30#1
                  timestart: 07-03-2027 23:52:43
                  repeat: 'No'
                  tracking: false
                  expiryHour: '48'
                  exclude: '447700900108'
                  groupId: 104
      responses:
        '200':
          description: OK
  /sms/identify:
    post:
      tags:
      - SMS
      summary: Identify SMS
      description: |-
        The `/sms/identify` endpoint is an HTTP **POST** API used to **analyse a message string** and return its detected encoding type, total character count, required SMS segments, and per-segment character limit.

        > ℹ️ Use the returned values to populate `messageType`, `charCount`, `smsParts`, and `charLimit` in any subsequent send request.


        ---

        # 📤 Response

        | Field | Description |
        | --- | --- |
        | `message` | `String` · The original message text that was analysed |
        | `messageType` | `String` · Detected encoding — `TEXT` (GSM-7 only) or `UNICODE` (special/regional characters present) |
        | `smscount` | `Integer` · Number of SMS segments required to deliver the message |
        | `charCount` | `Integer` · Total character count |
        | `charLimit` | `Integer` · Characters per segment — `160` (TEXT, single) · `153` (TEXT, multi) · `70` (UNICODE, single) · `67` (UNICODE, multi) |

        ---

        ```
        {
            "message": "Hello this is a test SMS message",
            "messageType": "GSM-7",
            "smscount": 1,
            "charCount": 32,
            "charLimit": 160
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_identify
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                message:
                  type: string
            examples:
              Identify SMS:
                value:
                  message: Hello this is a test SMS message
      responses:
        '200':
          description: OK
  /sms/sendbulk:
    post:
      tags:
      - SMS
      summary: Bulk Sms
      description: |-
        The `/sms/sendbulk` endpoint is an HTTP **POST** API used to send **bulk SMS messages** to multiple recipients via uploaded destination file(s) with a shared message and Sender ID.

        ---

        # 📤 Response — `BulkResponse`

        | Field | Description |
        | --- | --- |
        | `BulkListInfo` | `Object` · Batch metadata — contains `batchId` (unique batch ID), `totalCount` (total recipients), `processedCount` (successfully queued count) |
        | `credits` | `String` · Account credit balance after submission |
        | `deductcredits` | `String` · Total credits consumed for this batch |
        | `status` | `String` · Submission result — `SUBMITTED` / `FAILED` / `SCHEDULED` |
        | `bulkSessionId` | `String` · Unique session identifier for this bulk operation |

        ---

        ``` json
        {
            "credits": "9966465.42850",
            "deductcredits": "0.60000",
            "status": "success",
            "bulkSessionId": "1_20260228105000887",
            "bulkListInfo": {
                "total": 4,
                "validCount": 3,
                "invalidCount": 0,
                "duplicate": 1,
                "errors": {}
            }
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_sendbulk
      parameters:
      - name: destinationNumberFile
        in: query
        required: false
        schema:
          type: string
      - name: bulkRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                destinationNumberFile:
                  type: string
                  format: binary
                bulkRequest:
                  type: string
            examples:
              Bulk Sms:
                value:
                  destinationNumberFile: recipients.csv
                  bulkRequest: |-
                    {
                      "senderId": "TESTCO",
                      "message": "Dear Customer, your OTP is 123456. Valid for 10 minutes. Do not share.",
                      "messageType": "TEXT",
                      "smsParts": 1,
                      "charCount": 73,
                      "charLimit": 160,
                      "smscount": "1",
                      "delay": 0.0,
                      "schedule": false,
                      "alert": false,
                      "allowDuplicate": false,
                      "expiryHour": 24,
                      "tracking": false,
                      "weblink": [],
                      "exclude": "",
                      "campaignName": "OTPCampaign2026",
                      "peId": "1001234567890",
                      "templateId": "1007232314558898",
                      "telemarketerId": "110200100000001"
                    }
      responses:
        '200':
          description: OK
  /sms/sendbulk/custom:
    post:
      tags:
      - SMS
      summary: Bulk Custom Sms
      description: |-
        The `/sms/sendbulk/custom` endpoint is an HTTP **POST** API used to send a **shared bulk SMS message** to all destination numbers from a single uploaded file — every recipient gets the same Sender ID and message text.

        ---

        # 📤 Response — `BulkResponse`

        | Field | Description |
        | --- | --- |
        | `BulkListInfo` | `Object` · Batch metadata — contains `batchId` (unique batch ID), `totalCount` (total recipients), `processedCount` (successfully queued count) |
        | `credits` | `String` · Account credit balance after submission |
        | `deductcredits` | `String` · Total credits consumed for this batch |
        | `status` | `String` · Submission result — `SUBMITTED` / `FAILED` / `SCHEDULED` |
        | `bulkSessionId` | `String` · Unique session identifier for this bulk operation |

        ---

        ```
        {
            "credits": "9963549.40610",
            "deductcredits": "0.40000",
            "status": "success",
            "bulkSessionId": "1_20260307095717711",
            "bulkListInfo": {
                "total": 0,
                "validCount": 2,
                "invalidCount": 0,
                "duplicate": 1,
                "errors": {}
            }
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_sendbulk_custom
      parameters:
      - name: bulkRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                destinationNumberFile:
                  type: string
                  format: binary
                bulkRequest:
                  type: string
            examples:
              Bulk Custom Sms:
                value:
                  destinationNumberFile: recipients.csv
                  bulkRequest: |-
                    {
                      "senderId": "TESTCO",
                      "message": "Dear Customer, your account balance has been updated. Please login to confirm.",
                      "messageType": "TEXT",
                      "smsParts": 1,
                      "charCount": 74,
                      "charLimit": 160,
                      "smscount": "1",
                      "expiryHour": 24,
                      "delay": 0.0,
                      "alert": false,
                      "tracking": false,
                      "allowDuplicate": false,
                      "exclude": "",
                      "schedule": false,
                      "campaignName": "BalanceUpdate2026",
                      "peId": "1001234567890",
                      "templateId": "1007232314558898",
                      "telemarketerId": "110200100000001"
                    }
      responses:
        '200':
          description: OK
  /sms/sendbulkopt:
    post:
      tags:
      - SMS
      summary: Send Bulk Opt
      description: |-
        The `/sms/sendbulkopt` endpoint is an HTTP **POST** API used to send **per-recipient personalised bulk SMS** from structured files where each row already carries its own Sender ID, destination number, and message text.

        ---

        # 📤 Response — `BulkResponse`

        ```
        {
          "campaignName": "acme Campaign ",
          "senderId": "TESTCO",
          "messageType": "GSM-7",
          "message": "hello",
          "charCount": 5,
          "smsParts": 1,
          "charLimit": 160,
          "expiryHour": 0,
          "delay": "1",
          "alert": true,
          "destinationNumber": "447700900109",
          "tracking": false,
          "allowDuplicate": false,
          "exclude": "",
          "schedule": true,
          "gmt": "GMT+05:30#1",
          "timestart": "2026-03-13 11:46:58",
          "repeat": "No",
          "smscount": 1
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_sendbulkopt
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                smsFiles:
                  type: string
                  format: binary
                options:
                  type: string
            examples:
              Send Bulk Opt:
                value:
                  smsFiles: recipients.csv
                  options: |-
                    {
                      "campaignName": "acme Campaign ",
                      "senderId": "TESTCO",
                      "messageType": "GSM-7",
                      "message": "hello",
                      "charCount": 5,
                      "smsParts": 1,
                      "charLimit": 160,
                      "expiryHour": 0,
                      "delay": "1",
                      "alert": true,
                      "destinationNumber": "447700900109",
                      "tracking": false,
                      "allowDuplicate": false,
                      "exclude": "",
                      "schedule": true,
                      "gmt": "GMT+05:30#1",
                      "timestart": "2026-03-13 11:46:58",
                      "repeat": "No",
                      "smscount": 1
                    }
      responses:
        '200':
          description: OK
  /sms/sendSmsMms:
    post:
      tags:
      - SMS
      summary: Send SMS MMS
      description: |-
        The `/sms/sendSmsMms` endpoint is an HTTP **POST** API used to send **MMS (Multimedia Messaging Service) messages** to multiple recipients via uploaded destination file(s), with optional media attachment (image, audio, video, or vCard).

        ---

        # 📤 Response — `SmsResponse`

        ```
        {
            "credits": "9963539.80610",
            "deductcredits": "9.00000",
            "status": "success",
            "bulkSessionId": "super_20260307101502415",
            "bulkListInfo": {
                "total": 4,
                "validCount": 3,
                "invalidCount": 0,
                "duplicate": 1,
                "errors": {}
            }
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_sendSmsMms
      parameters:
      - name: destinationNumberFile
        in: query
        required: false
        schema:
          type: string
      - name: bulkMmsRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                destinationNumberFile:
                  type: string
                  format: binary
                bulkMmsRequest:
                  type: string
            examples:
              Send SMS MMS:
                value:
                  destinationNumberFile: recipients.csv
                  bulkMmsRequest: |-
                    {
                      "senderId": "TESTCO",
                      "message": "Check out our Summer Sale 2026!",
                      "from": "HTIIND",
                      "messageType": "TEXT",
                      "smsParts": 1,
                      "charCount": 31,
                      "charLimit": 160,
                      "smscount": "1",
                      "mmsType": "image",
                      "caption": "Summer Sale 2026 Banner",
                      "schedule": false,
                      "alert": false,
                      "allowDuplicate": false,
                      "expiryHour": 24,
                      "campaignName": "SummerSale2026",
                      "peId": "1001234567890",
                      "templateId": "1007232314558898",
                      "telemarketerId": "110200100000001"
                    }
      responses:
        '200':
          description: OK
  /sms/sendModified:
    post:
      tags:
      - SMS
      summary: Send Modified
      description: |-
        The `/sms/sendModified` endpoint is an HTTP **POST** API used to **update the content of an existing bulk SMS job** (Sender ID, message, encoding, delay, expiry) and re-dispatch it immediately. The destination file and recipient list remain unchanged.

        ### Note

        - `id` is taken from **`/sms/list`** API.

        - This `id` identifies **which bulk entry is being re-submitted after modification**.


        Flow:
        `sms/list (id) → sms/sendModified (id)`

        ---

        # 📤 Response

        ```
        Modified Bulk Send Successfully

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |

        Notes from the example body: Optional : you can update this feild if required
      operationId: post_sms_sendModified
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                reqType:
                  type: string
                senderId:
                  type: string
                message:
                  type: string
                messageType:
                  type: string
                delay:
                  type: string
                expiryHour:
                  type: string
            examples:
              Send Modified:
                value:
                  id: 210
                  reqType: bulk
                  senderId: TESTCO
                  message: HYYYY
                  messageType: GSM-7
                  delay: '10'
                  expiryHour: '0'
      responses:
        '200':
          description: OK
  /sms/modify:
    post:
      tags:
      - SMS
      summary: Update Scheduled List
      description: |-
        The `/sms/modify` endpoint is an HTTP **POST** API used to modify an existing scheduled bulk SMS campaign.

        This endpoint allows users to update message content, sender details, schedule time, and delivery configuration of a previously created scheduled campaign.

        The request must be sent as **multipart/form-data**, where:

        - `sendBulkScheduleRequest` contains a serialized JSON string with updated campaign details.

        - `destinationNumberFile` (optional) allows replacing the original recipient file.


        This API is typically used to reschedule, update content, or adjust configuration before final dispatch.

        ---

        # 📤 Success Response — `BulkResponse`

        ``` json
        {
            "credits": "9960820.18590",
            "deductcredits": "0.00100",
            "status": "success",
            "bulkSessionId": null,
            "bulkListInfo": {
                "total": 1,
                "validCount": 1,
                "invalidCount": 0,
                "duplicate": 0,
                "errors": null
            }
        }

         ```

        ---

        # 📋 Response Fields

        ### 🔹 Root Level Fields

        | Field | Description |
        | --- | --- |
        | `BulkListInfo` | Object containing updated batch submission details |
        | `credits` | Remaining account credit balance |
        | `deductcredits` | Credits consumed for the scheduled batch |
        | `status` | Current campaign status — `SCHEDULED`, `SUBMITTED`, or `FAILED` |
        | `bulkSessionId` | Unique session identifier for this campaign |

        ---

        ### 🔹 `BulkListInfo` Object Fields

        | Field | Description |
        | --- | --- |
        | `batchId` | Unique batch ID of the modified campaign |
        | `totalCount` | Total number of recipients in the batch |
        | `processedCount` | Number of messages successfully queued |

        ---
      operationId: post_sms_modify
      parameters:
      - name: sendBulkScheduleRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                sendBulkScheduleRequest:
                  type: string
            examples:
              Update Scheduled List:
                value:
                  sendBulkScheduleRequest: |-
                    {
                      "id": 145,
                      "senderId": "TESTCO",
                      "destinationNumber": "",
                      "message": "wedwehttps:updated121",
                      "schedTime": "21-02-2028 01:00:00",
                      "totalNumbers": "1",
                      "uploadedNumbers": "447700900110",
                      "gmt": "GMT+05:30",
                      "smscount": 1,
                      "delay": "0.0",
                      "repeat": "No",
                      "alert": false,
                      "messageType": "GSM-7",
                      "smsParts": 1,
                      "charCount": 21,
                      "charLimit": 160,
                      "expiryHour": "0",
                      "reqType": "bulk",
                      "reCheck": "no",
                      "fileName": "super_13032026101858287",
                      "peId": "",
                      "templateId": "",
                      "telemarketerId": ""
                    }
      responses:
        '200':
          description: OK
  /sms/list:
    get:
      tags:
      - SMS
      summary: List Bulk
      description: |-
        The `/sms/list` endpoint is an HTTP **GET** API used to **retrieve a list of all bulk SMS jobs** associated with the authenticated user, including current status and configuration details.

        ---

        # 📤 Response — `BulkProccessResponse[]`

        ```
        [
          {
            "id": 135,
            "systemId": "HTI001",
            "senderId": "HTIIND",
            "delay": 0.0,
            "reqType": "bulk",
            "serverId": 1,
            "ston": 1,
            "snpi": 1,
            "messageType": "GSM-7",
            "alert": false,
            "alertNumbers": null,
            "expiryHour": 0,
            "total": 1000,
            "firstNumber": 447700900110,
            "content": "48656c6c6f20576f726c64",
            "campaignName": "Promo Campaign",
            "peId": "PE123456",
            "templateId": "TMP123456",
            "telemarketerId": "TM123456",
            "mmsType": null,
            "caption": null,
            "requestIp": "203.0.113.10",
            "systemType": "API",
            "processed": 450,
            "pending": 550,
            "active": true,
            "createdOn": "2026-03-08T21:15:20"
          }
        ]

         ```

        ## 📤 Response Fields :

        | Field | Description |
        | --- | --- |
        | `id` | Unique batch ID |
        | `systemId` | Client system ID |
        | `senderId` | Sender ID used for SMS |
        | `delay` | Delay between messages |
        | `reqType` | Request type (`bulk`, `single`, etc.) |
        | `serverId` | SMS server identifier |
        | `messageType` | Message encoding type |
        | `alert` | Whether alert notification is enabled |
        | `expiryHour` | Message validity time |
        | `total` | Total numbers in batch |
        | `processed` | Messages already processed |
        | `pending` | Remaining messages |
        | `active` | Whether batch is currently active |
        | `createdOn` | Batch creation timestamp |

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success — Bulk job list returned |
        | `400` | Bad Request |
        | `401` | Unauthorized |
        | `500` | Internal Server Error |
      operationId: get_sms_list
      responses:
        '200':
          description: OK
  /sms/edit:
    get:
      tags:
      - SMS
      summary: Edit Using Batch Id
      description: |-
        The `/sms/edit` endpoint is an HTTP **GET** API used to **retrieve full details of an existing bulk SMS job** by its batch ID — for review or pre-modification inspection.

        StartFragment

        ### Note

        - The **`batch_Id`** **used in** **`/sms/edit`** **is derived from the Bulk List API (****`/sms/list`****)**.

        - When calling `/sms/list`, each bulk SMS entry contains an **`id`** field.

        - This **`id`** **is the same value as** **`batch_Id`** required in `/sms/edit`.


        Flow:
        `sms/list (id) → sms/edit (batch_Id)`

        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | `batch_Id` | **Required** · `int` · Unique Batch ID of the bulk job to retrieve |

        ---

        # 📤 Response — `BulkProccessResponse`

        | Field | Description |
        | --- | --- |
        | `from` | `String` · Timestamp of job creation or last modification |
        | `sender` | `String` · Sender ID configured for the batch |
        | `message` | `String` · Message content of the batch |
        | `delay` | `String` · Configured transmission delay in seconds |
        | `expiry` | `String` · Message validity period in hours |
        | `reqType` | `String` · Request type — e.g. `bulk` |
        | `batchId` | `String` · Unique batch job identifier |

        ```
        {
          "from": "Name",
          "sender": "HTIIND",
          "message": "Automated reminder: Your appointment is confirmed for tomorrow at 10:00 AM.",
          "delay": "0.0",
          "expiry": "0",
          "reqType": "bulk",
          "batchId": "135"
        }

         ```

        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: get_sms_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: '1024'
      responses:
        '200':
          description: OK
  /sms/pause:
    get:
      tags:
      - SMS
      summary: Pause Bulk
      description: |-
        The `/sms/pause` endpoint is an HTTP **GET** API used to **pause an in-progress bulk SMS job**. The job halts at its current dispatch position and remains paused until explicitly resumed via `GET /sms/resume.`

        ### Note

        - `batch_Id` is taken from **`/sms/list`** API.

        - Only **active bulk entries** can be paused.


        Flow:
        `sms/list (id) → sms/pause (batch_Id)`


        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | `batch_Id` | **Required** · `int` · Unique Batch ID of the in-progress job to pause |

        ---

        # 📤 Response — `BulkProccessRespons`

        ```
        "Batch Paused"

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: get_sms_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: '1024'
      responses:
        '200':
          description: OK
  /sms/resume:
    get:
      tags:
      - SMS
      summary: Resume Bulk
      description: |-
        The `/sms/resume` endpoint is an HTTP **GET** API used to **resume a previously paused bulk SMS job**, continuing dispatch from the position where it was halted.

        ### Note

        - `batch_Id` is taken from **`/sms/list`** API.

        - Only **paused bulk entries** can be resumed.


        Flow:
        `sms/list (id) → sms/resume (batch_Id)`


        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | `batch_Id` | **Required** · `int` · Unique Batch ID of the paused job to resume |

        ---

        # 📤 Response — `BulkProccessResponse`

        ```
        Batch resumed

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: get_sms_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: '211'
      responses:
        '200':
          description: OK
  /sms/abort:
    delete:
      tags:
      - SMS
      summary: Abort Bulk
      description: |-
        The `/sms/abort` endpoint is an HTTP **DELETE** API used to **permanently abort (cancel) a bulk SMS job**. All pending messages in the batch will not be sent.

        ### Note

        - `batch_Id` is taken from **`/sms/list`** API.

        - Only **active bulk entries** can be aborted.


        Flow:
        `sms/list (id) → sms/abort (batch_Id)`


        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | scheduleId | **Required** · `int` · Unique scheduleId of the job to abort |

        ---

        # 📤 Response

        ```
        Abort Paused

         ```

        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: delete_sms_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: '211'
      responses:
        '200':
          description: OK
  /sms/abortedNumberList:
    get:
      tags:
      - SMS
      summary: Aborted number list
      description: |-
        ### Aborted number list

        Aborted number list for the SMS channel (GET /sms/abortedNumberList). Required query parameter: `abort_batch_id`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /sms/abortedNumberList`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `abort_batch_id` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_sms_abortedNumberList
      parameters:
      - name: abort_batch_id
        in: query
        required: false
        schema:
          type: string
        example: <abort_batch_id>
      responses:
        '200':
          description: OK
  /sms/auto-schedule:
    post:
      tags:
      - SMS
      summary: Auto Schedule
      description: |-
        The `/sms/auto-schedule` endpoint is an HTTP **POST** API used to create an **automatic scheduled bulk SMS campaign**. The gateway manages dispatch timing based on configured parameters and the recipient list from the uploaded file. auto schedule object.

        ---

        # 📤 Response — `SmsResponse`

        ```
        [
            {
                "id": 142,
                "username": "super",
                "serverTime": "1930",
                "clientGmt": "GMT+05:30",
                "clientTime": "21-02-2028 01:00:00",
                "serverId": 1,
                "status": "false",
                "fileName": "super_13032026054541175",
                "repeated": "No",
                "scheduleType": "bulk",
                "webId": null,
                "date": null,
                "createdOn": "2026-03-13T05:45:41.176486721",
                "messageType": "GSM-7",
                "totalNumbers": 1,
                "customContent": false,
                "senderId": "TESTCO",
                "campaign": null,
                "firstNum": null
            },
            {
                "id": 143,
                "username": "super",
                "serverTime": "0030",
                "clientGmt": "GMT+02:30",
                "clientTime": "02-05-2028 03:00:00",
                "serverId": 1,
                "status": "false",
                "fileName": "super_13032026054541181",
                "repeated": "No",
                "scheduleType": "bulk",
                "webId": null,
                "date": null,
                "createdOn": "2026-03-13T05:45:41.182766481",
                "messageType": "GSM-7",
                "totalNumbers": 1,
                "customContent": false,
                "senderId": "TESTCO",
                "campaign": null,
                "firstNum": null
            }
        ]

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_auto_schedule
      parameters:
      - name: bulkAutoScheduleRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                destinationNumberFile:
                  type: string
                  format: binary
                bulkAutoScheduleRequest:
                  type: string
            examples:
              Auto Schedule:
                value:
                  destinationNumberFile: recipients.xlsx
                  bulkAutoScheduleRequest: '{"senderId":"TESTCO","message":"wdwd","charCount":4,"charLimit":160,"smscount":1,"messageType":"GSM-7","tracking":false,"weblink":[""],"campaignName":"Alex"}'
      responses:
        '200':
          description: OK
  /sms/send-now:
    post:
      tags:
      - SMS
      summary: Send Now
      description: |-
        The `/sms/send-now` endpoint is an HTTP **POST** API used to **immediately dispatch a previously created scheduled SMS campaign**, bypassing its original scheduled time. see bulk schedule request object.

        ### Note

        - `id` is taken from **`/sms/listSchedule`** API.

        - Used to **trigger immediate sending of a scheduled SMS**.


        Flow:
        `sms/listSchedule (id) → sms/send-now (id)`


        ---

        # 📤 Response — `BulkResponse`

        | Field | Description |
        | --- | --- |
        | `BulkListInfo` | `Object` · Batch metadata — contains `batchId` (unique batch ID), `totalCount` (total recipients), `processedCount` (successfully queued count) |
        | `credits` | `String` · Account credit balance after submission |
        | `deductcredits` | `String` · Total credits consumed for this batch |
        | `status` | `String` · Submission result — `SUBMITTED` / `FAILED` / `SCHEDULED` |
        | `bulkSessionId` | `String` · Unique session identifier for this bulk operation |

        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: post_sms_send_now
      parameters:
      - name: sendBulkScheduleRequest
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                sendBulkScheduleRequest:
                  type: string
                destinationNumberFile:
                  type: string
                  format: binary
            examples:
              Send Now:
                value:
                  sendBulkScheduleRequest: '{"id":131,"destinationNumber":"","reqType":"bulk","alert":false,"messageType":"TEXT","senderId":"HTIIND","uploadedNumbers":"447700900110","totalNumbers":"1","message":"Automated
                    reminder: Your appointment is confirmed for tomorrow at 10:00 AM.","gmt":"GMT+05:30","smscount":0,"expiryHour":"0","delay":"0.0","repeat":"No","smsParts":"","charCount":0,"charLimit":0,"schedTime":"21-02-2028
                    01:00:00","fileName":"super_07032026104455421","reCheck":"no"}'
                  destinationNumberFile: recipients.csv
      responses:
        '200':
          description: OK
  /sms/listSchedule:
    get:
      tags:
      - SMS
      summary: List Schedule
      description: |-
        The `/sms/listSchedule` endpoint is an HTTP **GET** API used to **retrieve all scheduled SMS campaigns** associated with the authenticated user, including timing configuration and current campaign status.

        ---

        # 📤 Response — `ScheduleEntryExt[]`

        ```
         {
                "id": 130,
                "username": "super",
                "serverTime": "1822",
                "clientGmt": "GMT+05:30",
                "clientTime": "07-03-2026 23:52:43",
                "serverId": 1,
                "status": "false",
                "fileName": "super_07032026094302734",
                "repeated": "No",
                "scheduleType": "GroupData",
                "webId": null,
                "date": null,
                "createdOn": "2026-03-07T09:43:02.736256",
                "messageType": "GSM-7",
                "totalNumbers": 2,
                "customContent": true,
                "senderId": "TESTCO",
                "campaign": "groupdata",
                "firstNum": "447700900107"
            }
         }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success — Schedule list returned |
        | `400` | Bad Request |
        | `401` | Unauthorized |
        | `500` | Internal Server Error |
      operationId: get_sms_listSchedule
      responses:
        '200':
          description: OK
  /sms/edit/schedule:
    get:
      tags:
      - SMS
      summary: Edit Schedule
      description: |-
        The `/sms/edit/schedule` endpoint retrieves the current configuration of a scheduled SMS campaign using its schedule ID.
        This data is typically used to **review and edit an existing scheduled SMS before modification or resubmission**.

        ### Note

        - `scheduleId` is taken from **`/sms/listSchedule`** API.


        Flow:
        `sms/listSchedule (id) → sms/edit/schedule (scheduleId)`


        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | `scheduleId` | **Required · int** · Unique identifier of the scheduled SMS campaign |

        ---

        # 📤 Response — ScheduleEditResponse

        | Field | Description |
        | --- | --- |
        | `groupList` | **Array** · List of contact groups associated with the schedule (only when `reqType = contact`) |
        | `listSizeStr` | **String** · Total number of recipients |
        | `tempList` | **String\[\]** · List of destination mobile numbers |
        | `gmt` | **String** · GMT timezone label used for scheduling (e.g. `GMT+05:30#1`) |
        | `gmtValue` | **String** · Extracted GMT offset value |
        | `schaduleTime` | **String** · Scheduled SMS dispatch time |
        | `msg` | **String** · Scheduled message content |
        | `senderId` | **String** · Sender ID used for SMS |
        | `filename` | **String** · Name of the stored schedule file |
        | `reqType` | **String** · Request type (`bulk`, `contact`, etc.) |
        | `delay` | **String** · Delay between sending SMS messages |
        | `repeat` | **String** · Repeat configuration |
        | `username` | **String** · System ID of the schedule owner |
        | `expiry` | **String** · Message validity period in hours |

        ---

        # 📄 Example Response

        ``` json
        {
          "groupList": [],
          "listSizeStr": "3",
          "tempList": [
            "447700900110",
            "447700900111",
            "447700900112"
          ],
          "gmt": "GMT+05:30#1",
          "gmtValue": "",
          "schaduleTime": "21-03-2026 10:30:00",
          "msg": "Your OTP is 123456",
          "senderId": "HTIIND",
          "filename": "schedule_07032026123635648",
          "reqType": "bulk",
          "delay": "0.0",
          "repeat": "No",
          "username": "HTI001",
          "expiry": "0"
        }

         ```

        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | **200** | Success |
        | **401** | Unauthorized — User not allowed |
        | **404** | Schedule or file not found |
        | **500** | Internal server error |

        ---
      operationId: get_sms_edit_schedule
      parameters:
      - name: scheduleId
        in: query
        required: false
        schema:
          type: string
        example: '140'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              Edit Schedule:
                value: ''
      responses:
        '200':
          description: OK
  /sms/abort/schedule:
    delete:
      tags:
      - SMS
      summary: Abort Schedule
      description: |-
        The `/sms/abort/schedule` endpoint is an HTTP **DELETE** API used to **permanently cancel a pending scheduled SMS campaign**. The schedule is removed and will not be dispatched at its configured time.

        ### Note

        - `scheduleId` is taken from **`/sms/listSchedule`** API.

        - The **`id`** **from schedule list =** **`scheduleId`**.


        Flow:
        `sms/listSchedule (id) → sms/abort/schedule (schedule ID)`

        ---

        # 📥 Query Parameters

        | Parameter | Description |
        | --- | --- |
        | `scheduleId` | **Required** · `int` · Unique ID of the scheduled campaign to cancel |

        ---

        # 📤 Response

        Returns a plain-text confirmation string.

        **Example:** `"success."`

        > ⚠️ **This action is irreversible.** The schedule cannot be reactivated once cancelled.


        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |
      operationId: delete_sms_abort_schedule
      parameters:
      - name: scheduleId
        in: query
        required: false
        schema:
          type: string
        example: '140'
      responses:
        '200':
          description: OK
  /sms/resend:
    post:
      tags:
      - SMS
      summary: Resend
      description: |-
        The `/sms/resend` endpoint is an HTTP **POST** API used to **re-submit historical messages** matching the provided filter criteria back into the SMPP gateway for re-delivery. Useful for bulk-retrying failed or undelivered messages.

        ---

        # 📤 Response

        | Field | Description |
        | --- | --- |
        | `resentCount` | `Integer` · Number of messages successfully requeued for resend |
        | `status` | `String` · Operation result — Value: `ATES` |

        ---

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |

        Notes from the example body: Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional
      operationId: post_sms_resend
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                startDate:
                  type: string
                endDate:
                  type: string
                senderId:
                  type: string
                senderReply: {}
                messageStatus:
                  type: string
                clientId:
                  type: string
                smscName: {}
                reroute: {}
                country: {}
                operator: {}
                fromMessageId: {}
                toMessageId: {}
                checkFlag: {}
                delay:
                  type: number
            examples:
              Resend:
                value:
                  startDate: '2026-02-01'
                  endDate: '2026-02-24'
                  senderId: HTIIND
                  senderReply: null
                  messageStatus: FAILED
                  clientId: CLIENT123
                  smscName: null
                  reroute: null
                  country: null
                  operator: null
                  fromMessageId: null
                  toMessageId: null
                  checkFlag: null
                  delay: 0.0
      responses:
        '200':
          description: OK
  /sms/resendDlr:
    post:
      tags:
      - SMS
      summary: Resend DLR
      description: |-
        The `/sms/resendDlr` endpoint is an HTTP **POST** API used to **re-trigger Delivery Receipt (DLR) callbacks** for messages matching the filter criteria. Use this when DLR webhook events failed to reach the callback URL and need to be re-pushed.

        ---

        # 📤 Response

        ```
        ResendDLR Success

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |

        Notes from the example body: Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional; Optional
      operationId: post_sms_resendDlr
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                startDate:
                  type: string
                endDate:
                  type: string
                senderId:
                  type: string
                senderReply: {}
                messageStatus:
                  type: string
                clientId:
                  type: string
                smscName: {}
                reroute: {}
                country: {}
                operator: {}
                fromMessageId: {}
                toMessageId: {}
                checkFlag: {}
                delay:
                  type: number
            examples:
              Resend DLR:
                value:
                  startDate: '2026-02-01'
                  endDate: '2026-02-24'
                  senderId: HTIIND
                  senderReply: null
                  messageStatus: DELIVERED
                  clientId: CLIENT123
                  smscName: null
                  reroute: null
                  country: null
                  operator: null
                  fromMessageId: null
                  toMessageId: null
                  checkFlag: null
                  delay: 0.0
      responses:
        '200':
          description: OK
  /sms/sendMessageWithSmscName:
    post:
      tags:
      - SMS
      summary: Send Message With SMSC Name
      description: |-
        The `/sms/sendMessageWithSmscName` endpoint is an HTTP **POST** API used to send a **coverage test message via one or more specified SMSC connections** to validate SMSC connectivity and test delivery routes before routing production traffic.

        > 📋 **Optional Query Parameter:** `refresh=true` — Forces a refresh of the SMSC connection cache before sending.


        ---

        # 📤 Response

        | Field | Description |
        | --- | --- |
        | `{smscName}` | `String` · Delivery result per SMSC — `SUBMITTED` or `FAILED`. Example key: `SMSC_AIRTEL_IN` |

        ---

        ```
        {
            "testResult": [],
            "otherResult": [],
            "testCount": 0,
            "otherCount": 0,
            "testSql": "select A.msg_id,A.response_id,A.source_no, A.dest_no, A.route_to_smsc, A.submitted_time, A.deliver_time, A.status, A.err_code, B.content from mis_super A,content_super B where A.msg_id in(2603071154562113501,2603071154574603511) and A.msg_id=B.msg_id",
            "otherSql": "select A.msg_id,A.response_id,A.source_no, A.dest_no, A.route_to_smsc, A.submitted_time, A.deliver_time, A.status, A.err_code, B.content from mis_super A,content_super B where A.msg_id not in(2603071154562113501,2603071154574603511) and A.dest_no in('447700900111','447700900111') and A.msg_id >'2603071154562113501' and A.msg_id=B.msg_id limit 10000"
        }

         ```

        # 📌 Status Codes

        | Status Code | Description |
        | --- | --- |
        | `200` | Success |
        | `400` | Bad Request — Validation error or missing required field |
        | `401` | Unauthorized — Invalid or missing Bearer token |
        | `500` | Internal Server Error — Unexpected error occurred while processing the request |

        Notes from the example body: Optional; Optional
      operationId: post_sms_sendMessageWithSmscName
      parameters:
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'true'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                smscList:
                  type: array
                  items:
                    type: string
                destinationNumber:
                  type: string
                senderId:
                  type: string
                message:
                  type: string
                messageType:
                  type: string
                smsParts:
                  type: integer
                charCount:
                  type: integer
                charLimit:
                  type: integer
                header: {}
                temp: {}
            examples:
              Send Message With SMSC Name:
                value:
                  smscList:
                  - SMSC_AIRTEL_IN
                  - SMSC_JIO_IN
                  destinationNumber: '447700900111'
                  senderId: HTIIND
                  message: This is a coverage test message via SMSC.
                  messageType: TEXT
                  smsParts: 1
                  charCount: 41
                  charLimit: 160
                  header: null
                  temp: null
      responses:
        '200':
          description: OK
  /sms/list/bulk-mgmt:
    get:
      tags:
      - SMS
      summary: List Bulk Management(Active— Pending Entries)
      description: |-
        Retrieves all **pending Bulk SMS submissions** that are awaiting admin approval or rejection.

        Call this endpoint before `PUT /sms/update/bulk-mgmt` — the `id` field returned in each entry is the `bulkMgmtId` required for the approve/reject action.

        ⚠️ **Dependency:** The `id` values returned by this API are required as input for `PUT /sms/update/bulk-mgmt` (Approve / Reject Bulk Management).

        ---

        ## 📌 Query Parameters

        | Parameter | Required | Value | Description |
        | --- | --- | --- | --- |
        | `method` | ✅ Yes | `act` | Returns pending/active bulk management entries only |

        ---

        ### 🔎 Response Fields

        | Field | Type | Description |
        | --- | --- | --- |
        | `id` | `int` | Unique identifier of the bulk management entry. **Use this as** **`bulkMgmtId`** **in the update API** |
        | `systemId` | `String` | System/account ID of the user who submitted the bulk request |
        | `senderId` | `String` | Sender ID (alphanumeric label shown to recipients) used in the submission |
        | `totalNum` | `int` | Total number of destination numbers in the bulk submission |
        | `firstNum` | `long` | First destination number in the batch (E.164 format, no `+`) |
        | `delay` | `int` | Configured delay in seconds between message dispatches |
        | `reqType` | `String` | Request category — e.g. `Bulk`, `Custom`, `MMS` |
        | `active` | `boolean` | Whether the bulk entry is currently in an active/pending state |
        | `serverId` | `int` | Internal SMSC server ID assigned to process this batch |
        | `ston` | `int` | SMPP source TON (Type of Number) — `5` = Alphanumeric |
        | `snpi` | `int` | SMPP source NPI (Numbering Plan Indicator) — `0` = Unknown |
        | `alert` | `boolean` | Whether a delivery alert/notification is enabled for this submission |
        | `alertNumber` | `String` | Mobile number to receive the delivery alert. `null` if `alert` is `false` |
        | `expiryHour` | `int` | Message validity in hours. `0` means no expiry set |
        | `content` | `String` | The SMS message text body |
        | `msgType` | `String` | Encoding type — `GSM-7` (standard ASCII) or `UNICODE` (regional/special characters) |
        | `campaignName` | `String` | Campaign label assigned to this submission. Empty string if not set |
        | `peId` | `String` | TRAI DLT Principal Entity ID. `null` if not applicable |
        | `templateId` | `String` | TRAI DLT registered Template ID. `null` if not applicable |
        | `telemarketerId` | `String` | TRAI DLT Telemarketer Registration ID. `null` if not applicable |
        | `msgCount` | `int` | Total SMS segments submitted (recipients × parts per message) |
        | `cost` | `int` | Total credit cost calculated for this bulk submission |
        | `userMode` | `String` | Billing mode of the account — e.g. `credit`, `postpaid` |
        | `campaignType` | `String` | Delivery type — `Immediate` for instant dispatch, `Scheduled` for future delivery |
        | `status` | `String` | Current status of the entry — `PENDING`, `APPROVE`, or `REJECT` |
        | `updateBy` | `String` | Username of the admin who last actioned this entry. `null` if not yet actioned |
        | `remarks` | `String` | Admin remark added during approval or rejection. `null` if not yet actioned |
        | `requestIp` | `String` | IP address from which the bulk submission was made |
        | `systemType` | `String` | Client interface used — e.g. `WEB`, `API` |
        | `createdOn` | `String` | ISO-8601 timestamp of when the submission was created |
        | `updateOn` | `String` | ISO-8601 timestamp of the last update to this entry |

        ---

        ### 📋 Sample Response

        ``` json
        [
          {
            "id": 18,
            "systemId": "stest",
            "senderId": "tst",
            "totalNum": 3,
            "firstNum": 447700900113,
            "delay": 0,
            "reqType": "Bulk",
            "active": true,
            "serverId": 1,
            "ston": 5,
            "snpi": 0,
            "alert": false,
            "alertNumber": null,
            "expiryHour": 0,
            "content": "helo qqe",
            "msgType": "GSM-7",
            "campaignName": "",
            "peId": null,
            "templateId": null,
            "telemarketerId": null,
            "msgCount": 3,
            "cost": 3,
            "userMode": "credit",
            "campaignType": "Immediate",
            "status": "PENDING",
            "updateBy": null,
            "remarks": null,
            "requestIp": "203.0.113.10",
            "systemType": "WEB",
            "createdOn": "2025-12-16T13:08:10.582645",
            "updateOn": "2025-12-16T13:08:10.582646"
          }
        ]

         ```

        ---

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Request succeeded — returns array of pending bulk entries. Returns empty array `[]` if none found |
        | `400` | Bad Request | Invalid or missing query parameters |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | Unexpected server-side error while processing the request |

        ---
      operationId: get_sms_list_bulk_mgmt
      parameters:
      - name: method
        in: query
        required: false
        schema:
          type: string
        example: act
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                variables:
                  type: string
            examples:
              List Bulk Management(Active— Pending Entries):
                value:
                  query: ''
                  variables: ''
      responses:
        '200':
          description: OK
  /sms/update/bulk-mgmt:
    put:
      tags:
      - SMS
      summary: Approve Bulk Management
      description: |-
        Updates the status of one or more **pending Bulk SMS submissions** to **APPROVED**.

        ⚠️ **Dependency:** Call `GET /sms/list/bulk-mgmt?method=act` first to retrieve the `id` (used as `bulkMgmtId` here) of entries pending action.

        **Note**

        - `bulkMgmtId` is taken from **`/sms/list/bulk-mgmt?method=act`** API.

        - Represents **pending bulk entries for approval/rejection**.


        Flow:
        `sms/list/bulk-mgmt → bulkMgmtId → update/bulk-mgmt`


        ---

        ## 📥 Request Body — `List`

        Accepts a JSON array — multiple entries can be approved in a single request.

        | Field | Required | Description |
        | --- | --- | --- |
        | `bulkMgmtId` | Yes | `int` · ID of the bulk management entry to approve. Obtained from `GET /sms/list/bulk-mgmt?method=act` |
        | `status` | Yes | `String` · Must be `APPROVE` |
        | `remark` | Optional | `String` · Admin remark or reason for approval |

        ---

        ### 📋 Sample Request

        ``` json
        [
          {
            "bulkMgmtId": 19,
            "status": "APPROVE",
            "remark": "approve"
          }
        ]

         ```

        ---

        ## 📤 Response

        | Field | Description |
        | --- | --- |
        | `Operations completed` | List of `bulkMgmtId` values that were successfully approved |
        | `Operations failed` | List of `bulkMgmtId` values that could not be processed |

        ### 📋 Sample Response

        ```
        Operations completed: [19], Operations failed: []

         ```

        💡 **If** **`Operations completed`** **is empty** **`[]`** — the `bulkMgmtId` was not found, the entry is no longer in `PENDING` state, or the authenticated user does not have sufficient role/permission (`superadmin`, `system`, or `admin` with `bulkAct` enabled).

        ---

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Request processed — check `Operations completed` and `Operations failed` in response body for actual result |
        | `400` | Bad Request | Invalid or malformed request body |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | Unexpected server-side error while processing the request |

        ---
      operationId: put_sms_update_bulk_mgmt
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  status:
                    type: string
                  remark:
                    type: string
                  bulkMgmtId:
                    type: integer
            examples:
              Approve Bulk Management:
                value:
                - status: APPROVE
                  remark: approve
                  bulkMgmtId: 19
      responses:
        '200':
          description: OK
  /sms/sender-mgmt:
    get:
      tags:
      - SMS
      summary: '[operator] List Sender Management (Pending— Active Requests)'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        Retrieves the list of **pending Sender ID registration requests** awaiting admin approval or rejection.

        >

        ⚠️ **Dependency:** The `id` values returned by this API are required as input for `PUT /sms/update-sender-mgmt` (Approve / Reject Sender Management).




        ---

        ## 📌 Query Parameters

        | Parameter | Required | Value | Description |
        | --- | --- | --- | --- |
        | `purpose` | ❌ Optional | `act` | Returns pending Sender ID entries awaiting admin action |

        ---

        ## 📤 Response — `List`

        Returns a JSON array. Each object represents one pending Sender ID registration request.

        ### 🔎 Response Fields

        | Field | Type | Description |
        | --- | --- | --- |
        | `id` | `int` | Unique identifier of the sender management entry. **Use this as** **`id`** **in the update API** |
        | `sender` | `String` | The Sender ID string submitted for registration |
        | `systemId` | `String` | System/account ID of the user who submitted the sender registration request |
        | `remarks` | `String` | Remark provided at the time of submission. `null` if not yet actioned |
        | `status` | `String` | Current status of the entry — `PENDING`, `APPROVE`, or `REJECT` |
        | `addedBy` | `String` | Username of the admin or user who added this sender entry |
        | `updateBy` | `String` | Username of the admin who last actioned this entry. `null` if not yet actioned |
        | `senderType` | `String` | Category of the sender — e.g. `Whitelist`, `Blacklist` |
        | `alertFlag` | `String` | Alert flag associated with this sender. `null` if not configured |
        | `senderShortCode` | `String` | Short code mapped to this sender ID. `null` if not applicable |
        | `addedOn` | `String` | ISO-8601 timestamp of when the sender request was created |
        | `updateOn` | `String` | ISO-8601 timestamp of the last update to this entry. `null` if not yet actioned |

        ---

        ### 📋 Sample Response

        ``` json
        [
          {
            "id": 3,
            "sender": "1",
            "systemId": "alertUser",
            "remarks": "approve",
            "status": "PENDING",
            "addedBy": "super",
            "updateBy": null,
            "senderType": "Whitelist",
            "alertFlag": null,
            "senderShortCode": "123",
            "addedOn": "2026-03-14T07:41:34",
            "updateOn": null
          }
        ]

         ```

        ---

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Request succeeded — returns array of pending sender entries. Returns `"No Pendings Found"` if none exist |
        | `400` | Bad Request | Invalid or missing query parameters |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | Unexpected server-side error while processing the request |

        ---
      operationId: get_sms_sender_mgmt
      parameters:
      - name: purpose
        in: query
        required: false
        schema:
          type: string
        example: act
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              '[operator] List Sender Management (Pending— Active Requests)':
                value: ''
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /sms/update-sender-mgmt:
    put:
      tags:
      - SMS
      summary: Approve Sender Management
      description: |-
        Updates the status of one or more **pending Sender ID registration requests** to **APPROVED**.

        >

        ⚠️ **Dependency:** Call `GET /sms/sender-mgmt?purpose=act` first to retrieve the `id` values of pending sender entries required for this request.




        ---

        ## 📥 Request Body — `SenderMgmtRequest`

        The `id`, `status`, and `remarks` fields are **parallel arrays** — index `0` of `id` maps to index `0` of `status` and `remarks`. Multiple sender IDs can be approved in a single request.

        | Field | Required | Description |
        | --- | --- | --- |
        | `id` | Yes | `int[]` · Array of Sender Management entry IDs to approve. Obtained from `GET /sms/sender-mgmt?purpose=act` |
        | `status` | Yes | `String[]` · Must be `APPROVE` for each entry |
        | `remarks` | Optional | `String[]` · Parallel array of admin remarks for each entry |

        ---

        ### 📋 Sample Request — Single Entry

        ``` json
        {
          "id": [1],
          "status": ["APPROVE"],
          "remarks": ["Approved by admin"]
        }

         ```

        ### 📋 Sample Request — Multiple Entries

        ``` json
        {
          "id": [1, 2, 3],
          "status": ["APPROVE", "APPROVE", "APPROVE"],
          "remarks": ["Approved by admin", "Approved by admin", "Approved by admin"]
        }

         ```

        ---

        ## 📤 Response

        | Value | Description |
        | --- | --- |
        | `Operation success.` | All entries in the request were successfully approved |

        ### 📋 Sample Response

        ```
        Operation success.

         ```

        ---

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Request processed — all provided sender entries were successfully approved |
        | `400` | Bad Request | Invalid or malformed request body |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | Unexpected server-side error while processing the request |

        ---
      operationId: put_sms_update_sender_mgmt
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: array
                  items:
                    type: integer
                status:
                  type: array
                  items:
                    type: string
                remarks:
                  type: array
                  items:
                    type: string
            examples:
              Approve Sender Management:
                value:
                  id:
                  - 1
                  status:
                  - APPROVE
                  remarks:
                  - Approved by admin
      responses:
        '200':
          description: OK
  /sms/log-sender-mgmt:
    post:
      tags:
      - SMS
      summary: Log Sender Management
      description: |-
        Queries the **historical log of all Sender ID management actions** — approvals and rejections — filtered by various parameters.

        📌 **Note:** This endpoint returns only entries where `status` is **not** `PENDING` — i.e. only already-actioned records are returned.

        ---

        ## 📥 Request Body — `SenderMgmtRequest`

        All fields are optional filters **except** **`sday`** **and** **`eday`** which are required for the date range.

        🔍 **Supported Filters:** `systemId`, `sender`, `status[]`, `senderType`, `sday`, `eday`

        | Field | Required | Type | Description |
        | --- | --- | --- | --- |
        | `systemId` | Yes | `String` | Filter by system/user ID. Pass `"ALL"` to fetch logs across all users |
        | `sday` | Yes | `String` | Start date of the query range in `YYYY-MM-DD` format |
        | `eday` | Yes | `String` | End date of the query range in `YYYY-MM-DD` format |
        | `sender` | Optional | `String` | Filter by sender name — supports partial/exact match |
        | `status` | Optional | `String[]` | Filter by status — `APPROVE` or `REJECT`. Pass `"-"` or omit to fetch all statuses |
        | `senderType` | Optional | `String` | Filter by sender category — e.g. `Whitelist`, `Blacklist`. Pass `"-"` or omit to fetch all types |

        ---

        ### 📋 Sample Request — Minimal (All Users, Date Range Only)

        ``` json
        {
          "systemId": "ALL",
          "sday": "2026-03-14",
          "eday": "2026-03-05"
        }

         ```

        ### 📋 Sample Request — With All Filters

        ``` json
        {
          "systemId": "alertUser",
          "sday": "2026-01-01",
          "eday": "2026-03-14",
          "sender": "ACME-ALRT",
          "status": ["APPROVE"],
          "senderType": "Whitelist"
        }

         ```

        ---

        ## 📤 Response — `List`

        Returns a JSON array of actioned sender entries matching the filter criteria.

        ### 🔎 Response Fields

        | Field | Type | Description |
        | --- | --- | --- |
        | `id` | `int` | Unique identifier of the sender management entry |
        | `sender` | `String` | The Sender ID string |
        | `systemId` | `String` | System/account ID of the user who submitted the sender request |
        | `remarks` | `String` | Admin remark added during approval or rejection |
        | `status` | `String` | Final actioned status — `APPROVE` or `REJECT` |
        | `addedBy` | `String` | Username of the user who originally added this sender entry |
        | `updateBy` | `String` | Username of the admin who actioned this entry |
        | `senderType` | `String` | Category of the sender — e.g. `Whitelist`, `Blacklist` |
        | `alertFlag` | `String` | Alert flag associated with this sender. `null` if not configured |
        | `senderShortCode` | `String` | Short code mapped to this sender ID. `null` if not applicable |
        | `addedOn` | `String` | ISO-8601 timestamp of when the sender request was originally created |
        | `updateOn` | `String` | ISO-8601 timestamp of when the admin actioned this entry |

        ---

        ```
        [
            {
                "id": 2,
                "sender": "SENDER1",
                "systemId": "demo-tenant",
                "remarks": "approve ",
                "status": "APPROVE",
                "addedBy": "super",
                "updateBy": "super",
                "senderType": "Whitelist",
                "alertFlag": null,
                "senderShortCode": "123",
                "addedOn": "2026-03-10T06:18:13",
                "updateOn": "2026-03-14T06:25:14"
            }
        ]

         ```

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Request succeeded — returns array of actioned sender log entries |
        | `404` | Not Found | No logs found matching the provided filters and date range |
        | `400` | Bad Request | Invalid or malformed request body |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | Unexpected server-side error while processing the request |

        ---

        💡 **Tip:** To fetch all logs without filtering by status or sender type, pass `"-"` in the `status` array and omit `senderType` — or simply use only `systemId`, `sday`, and `eday` as shown in the minimal request example above.
      operationId: post_sms_log_sender_mgmt
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                systemId:
                  type: string
                sday:
                  type: string
                eday:
                  type: string
            examples:
              Log Sender Management:
                value:
                  systemId: ALL
                  sday: '2026-03-05'
                  eday: '2026-03-20'
      responses:
        '200':
          description: OK
  /sms/save-sender-mgmt:
    post:
      tags:
      - SMS
      summary: Save Sender Management
      description: |-
        Registers a **new Sender ID** into the system for admin approval. The submitted entry is saved with `PENDING` status and remains inactive until approved by an admin.

        📌 This endpoint uses `multipart/form-data`. The JSON payload must be sent as a form part named `senderMgmtRequest`.

        ---

        ## 📤 Response

        | Value | Description |
        | --- | --- |
        | `Sender management entry added successfully` | Sender ID entry saved and queued for admin approval |

        ### 📋 Sample Response

        ```
        Sender management entry added successfully

         ```

        ---

        ## 🚦 HTTP Status Codes

        | Status Code | Meaning | Description |
        | --- | --- | --- |
        | `200` | OK | Sender entry saved successfully and queued for admin review |
        | `400` | Bad Request | Invalid or missing required fields |
        | `401` | Unauthorized | Missing, expired, or invalid Bearer token |
        | `403` | Forbidden | Authenticated user does not have the required role/permission |
        | `500` | Internal Server Error | No valid record to process or unexpected server error |

        ---
      operationId: post_sms_save_sender_mgmt
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                senderMgmtRequest:
                  type: string
            examples:
              Save Sender Management:
                value:
                  senderMgmtRequest: |-
                    {
                      "sender": "121",
                      "systemId": "alertUser",
                      "remarks": ["remark"],
                      "senderType": "Whitelist",
                      "senderShortCode": "1231",
                      "type": "single"
                    }
      responses:
        '200':
          description: OK
  /sms/lookup:
    post:
      tags:
      - SMS
      summary: Look up number status (HLR / MNP) before sending
      description: |-
        ### Look up number status (HLR / MNP) before sending

        This API endpoint allows you -- specified in a file.

        **Endpoint** `POST /sms/lookup`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `destinationNumber` | query | no |  |
        | `reqType` | query | no |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 |  successfully |
        | 400 | Bad Request |
        | 500 | Internal Server Error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_sms_lookup
      parameters:
      - name: destinationNumber
        in: query
        required: false
        schema:
          type: string
      - name: reqType
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /instagram/clients-onboard:
    post:
      tags:
      - Instagram
      summary: '[operator] Create Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Create a new Instagram page

        Create Clients onboard for the Instagram channel (POST /clients-onboard). The request body is a `OnboardedPageRequest`. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/clients-onboard`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `pageId` | `string` |
        | `igUserId` | `string` |
        | `pageName` | `string` |
        | `username` | `string` |
        | `accessToken` | `string` |
        | `webhookUrl` | `string` |
        | `qualityRating` | `string` |
        | `description` | `string` |
        | `disableInfo` | `string` |
        | `banInfo` | `string` |
        | `restrictionInfo` | `string` |
        | `sandbox` | `boolean` |
        | `onboardingLink` | `string` |
        | `status` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `passthroughFeeEnabled` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `partnerAppId` | `string` |
        | `webhookToken` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_clients_onboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pageId:
                  type: string
                igUserId:
                  type: string
                pageName:
                  type: string
                username:
                  type: string
                accessToken:
                  type: string
                webhookUrl:
                  type: string
                status:
                  type: string
            examples:
              '[operator] Create Page':
                value:
                  pageId: PM_TEST
                  igUserId: PM_TEST
                  pageName: Postman
                  username: PMUser
                  accessToken: YOUR_TOKEN
                  webhookUrl: https://pm.test
                  status: ACTIVE
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/update/{APP_ID}:
    put:
      tags:
      - Instagram
      summary: '[operator] Update Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update an existing Instagram page

        Update Update for the Instagram channel (PUT /clients-onboard/update/{id}). Path parameter `id` identifies the target resource. The request body is a `OnboardedPageRequest`. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `PUT /instagram/clients-onboard/update/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `pageId` | `string` |
        | `igUserId` | `string` |
        | `pageName` | `string` |
        | `username` | `string` |
        | `accessToken` | `string` |
        | `webhookUrl` | `string` |
        | `qualityRating` | `string` |
        | `description` | `string` |
        | `disableInfo` | `string` |
        | `banInfo` | `string` |
        | `restrictionInfo` | `string` |
        | `sandbox` | `boolean` |
        | `onboardingLink` | `string` |
        | `status` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `passthroughFeeEnabled` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `partnerAppId` | `string` |
        | `webhookToken` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: put_instagram_clients_onboard_update_APP_ID
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pageName:
                  type: string
            examples:
              '[operator] Update Page':
                value:
                  pageName: Updated
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/{APP_ID}:
    get:
      tags:
      - Instagram
      summary: '[operator] Get Page by ID'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get Instagram page by ID

        Get by ID for the Instagram channel (GET /clients-onboard/{id}). Path parameter `id` identifies the target resource. Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /instagram/clients-onboard/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_instagram_clients_onboard_APP_ID
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/me:
    get:
      tags:
      - Instagram
      summary: '[operator] Get My Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get Instagram page by username

        Get by username for the Instagram channel (GET /clients-onboard/me). Responds with `OnboardedPageResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /instagram/clients-onboard/me`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_instagram_clients_onboard_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/all:
    get:
      tags:
      - Instagram
      summary: '[operator] Get All Pages'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get all Instagram pages with pagination and filters

        Get all for the Instagram channel (GET /clients-onboard/all). Optional: `page`, `size`, `startDate`, `endDate`, `status`, `search`, `toGmt`, `sortBy`, `sortDirection`. Responds with `PaginationResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /instagram/clients-onboard/all`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `page` | query | no | (default `0`) |
        | `size` | query | no | (default `10`) |
        | `startDate` | query | no |  |
        | `endDate` | query | no |  |
        | `status` | query | no |  |
        | `search` | query | no |  |
        | `toGmt` | query | no |  |
        | `sortBy` | query | no | (default `createdAt`) |
        | `sortDirection` | query | no | (default `desc`) |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_instagram_clients_onboard_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: desc
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/delete/PM_TEST:
    delete:
      tags:
      - Instagram
      summary: '[operator] Delete Page'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete an Instagram page

        Delete Delete for the Instagram channel (DELETE /clients-onboard/delete/{id}). Path parameter `id` identifies the target resource. Responds with `String` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `DELETE /instagram/clients-onboard/delete/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_instagram_clients_onboard_delete_PM_TEST
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/clients-onboard/sender/26438500372453773:
    get:
      tags:
      - Instagram
      summary: '[operator] Get Sender Details'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        **Description:**

        Fetches sender profile details for a given Instagram user, including name, profile picture, latest conversation info, and unread message count. Requires the requesting user's Instagram page to be onboarded with a valid access token.

        #### Headers

        | Key | Value | Required |
        | --- | --- | --- |
        | Authorization | Bearer | Yes |

        #### Path Params

        | Param | Type | Description |
        | --- | --- | --- |
        | instagramUserId | String | Instagram scoped user ID (sender's numeric ID) |

        #### Sample Request

        ```
        GET /instagram/clients-onboard/sender/26438500372453773
        Authorization: {{ACCESS_TOKEN}}

         ```

        #### Sample Response — 200 OK

        json

        ```
        {
            "senderNumber": "26438500372453773",
            "senderName": "BroadNet Technologies",
            "lastOnline": null,
            "senderProfilePic": "https://example.com/",
            "conversationId": "26438500372453773_957112640547755",
            "lastMessagePreview": "hiiiiiiiiiiiiiiiii",
            "unreadCount": 239
        }

         ```

        #### Error Responses

        | Status | Case |
        | --- | --- |
        | 400 Bad Request | `instagramUserId` null/blank |
        | 401 Unauthorized | User not authorized (role check fail) |
        | 404 Not Found | User not found / page not onboarded / sender profile not found |
        | 500 Internal Server Error | Unexpected failure (Graph API/DB error) |
      operationId: get_instagram_clients_onboard_sender_26438500372453773
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /instagram/oauth/generate-link:
    post:
      tags:
      - Instagram
      summary: Generate OAuth Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Generate Encrypted Onboarding Link

        Generates a secure encrypted Instagram onboarding link.

        **Endpoint** `POST /instagram/oauth/generate-link`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_oauth_generate_link
      responses:
        '200':
          description: OK
  /instagram/message/sendbulk:
    post:
      tags:
      - Instagram
      summary: Text simple
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### 4.1.1 TEXT — simple

        Sent via the unified `{{BASE_URL}}/message/sendbulk` endpoint. This Postman item demonstrates one specific payload shape — see the request body for the exact fields used.

        For lifecycle docs (status / pause / resume / abort / scheduling rules) see the **Bulk & Lifecycle** folder.
      operationId: post_instagram_message_sendbulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                batchId:
                  type: string
                destinationNo:
                  type: string
                campaignName:
                  type: string
                allowDuplicate:
                  type: string
                messageType:
                  type: string
                content:
                  type: string
            examples:
              Text simple:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Hello from BroadNet!
              Text with Emoji/Unicode:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Hello 👋 🎉 ❤️
              Text with Reply_to (quote reply):
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: This is my reply!
                  replyToMid: IG_MESSAGE_MID
              Text with human agent tag:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Agent follow-up
                  tag: HUMAN_AGENT
              Text via URL:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  mediaUrl: https://cdn.example.com/media/640px-Camponotus_flavomarginatus_ant.jpg
                  caption: Image via URL
              Image via File Upload:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  caption: Image via file
                  file: ''
              Image with Reply_to:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  mediaUrl: https://cdn.example.com/media/640px-Camponotus_flavomarginatus_ant.jpg
                  replyToMid: IG_MESSAGE_MID
              Video via URL:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  mediaUrl: https://cdn.example.com/media/mov_bbb.mp4
                  caption: Video test
              Video via File Upload:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  caption: Video file
                  file: ''
              Audio via URL:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  mediaUrl: https://cdn.example.com/media/SoundHelix-Song-1.mp3
              Audio via File Upload:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  file:
                  - ''
                  - lz2VErecq/sigmamusicart-football-football-music-551346.mp3
              Sticker via URL:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: STICKER
                  mediaUrl: https://cdn.example.com/media/PNG_transparency_demonstration_1.png
              File PDF via URL:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: FILE
                  mediaUrl: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf
              File via file upload:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: FILE
                  file: ''
              Send heart sticker:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: LIKE_HEART
              Quick Reply basic (3 options):
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: QUICK_REPLY
                  content: How can we help?
                  quickReplyJson: '[{"content_type":"text","title":"Support","payload":"SUPPORT"},{"content_type":"text","title":"Sales","payload":"SALES"},{"content_type":"text","title":"Other","payload":"OTHER"}]'
              Quick Reply with email/phone:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: QUICK_REPLY
                  content: 'Share your contact:'
                  quickReplyJson: '[{"content_type":"user_email"},{"content_type":"user_phone_number"}]'
              Generic template single card:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: GENERIC_TEMPLATE
                  templateJson: '[{"title":"Product A","subtitle":"$19.99","imageUrl":"https://cdn.example.com/media/640px-Camponotus_flavomarginatus_ant.jpg","buttons":[{"type":"postback","title":"Buy","payload":"BUY_A"},{"type":"web_url","title":"View","url":"https://example.com"}]}]'
              Generic template carousel (2 cards):
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: GENERIC_TEMPLATE
                  templateJson: '[{"title":"Item 1","buttons":[{"type":"postback","title":"Select","payload":"SEL_1"}]},{"title":"Item
                    2","buttons":[{"type":"postback","title":"Select","payload":"SEL_2"}]}]'
              Media share published post:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: MEDIA_SHARE
                  mediaUrl: IG_MEDIA_ID
              Product Template catalog product:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: PRODUCT_TEMPLATE
                  templatePayloadJson: '{"product_id":"12345","elements":[{"title":"Premium Widget","subtitle":"High quality
                    product","image_url":"https://example.com/product.jpg","buttons":[{"type":"web_url","url":"https://example.com/buy","title":"View
                    Product"}]}]}'
              Reaction via sendbulk (unified API):
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: REACTION
                  replyToMessageId: IG_MESSAGE_MID
                  emoji: ❤️
              Reaction - Remove (unreact via sendbulk):
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: REACTION
                  replyToMessageId: IG_MESSAGE_MID
                  emoji: ❤️
              Bulk multi-recipient:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID,9876543210
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Bulk message
                  delay: '0.5'
              Scheduled future delivery:
                value:
                  batchId: '0'
                  destinationNo: IG_RECIPIENT_ID
                  campaignName: Test
                  allowDuplicate: 'true'
                  messageType: TEXT
                  content: Scheduled msg
                  scheduled: 'true'
                  scheduleTime: '2026-12-31 10:00:00.000'
                  gmt: +05:30
      responses:
        '200':
          description: OK
  /instagram/message/read:
    post:
      tags:
      - Instagram
      summary: Mark as Read (Instagram)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Mark Instagram message as read

        Mark message read for the Instagram channel (POST /message/read). Required query parameter: `recipientId`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/message/read`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `recipientId` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_message_read
      parameters:
      - name: recipientId
        in: query
        required: false
        schema:
          type: string
        example: IG_RECIPIENT_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                recipientId:
                  type: string
                typing:
                  type: boolean
            examples:
              Mark as Read (Instagram):
                value:
                  recipientId: '{{IG_RECIPIENT_ID}}'
                  typing: false
      responses:
        '200':
          description: OK
  /instagram/message/typing:
    post:
      tags:
      - Instagram
      summary: Typing On
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Typing indicator for  Instagram message

        Typing indicator for the Instagram channel (POST /message/typing). Required query parameter: `recipientId`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/message/typing`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `recipientId` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_message_typing
      parameters:
      - name: recipientId
        in: query
        required: false
        schema:
          type: string
        example: IG_RECIPIENT_ID
      responses:
        '200':
          description: OK
  /instagram/message/sendReaction:
    post:
      tags:
      - Instagram
      summary: Send Reaction
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### React on message  for  Instagram message

        Reaction message for the Instagram channel (POST /message/sendReaction). The request body is a `ReactionRequest`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/message/sendReaction`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `recipientId` | `string` |
        | `messageId` | `string` |
        | `emoji` | `string` |
        | `action` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_message_sendReaction
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                recipientId:
                  type: string
                messageId:
                  type: string
                emoji:
                  type: string
                action:
                  type: string
            examples:
              Send Reaction:
                value:
                  recipientId: '{{IG_RECIPIENT_ID}}'
                  messageId: aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDA1MDg1MTgxMTA3OjM0MDI4MjM2Njg0MTcxMDMwMTI0NDI2MDE5Njc3OTg5Mjk3Mzg5OTozMjkzMTgxOTQ2MDk2MzQ2Mjg0NzM3ODcyMTcwODQ0MTYwMAZDZD
                  emoji: ❤️
                  action: react
      responses:
        '200':
          description: OK
  /instagram/message/markReadByAgent:
    post:
      tags:
      - Instagram
      summary: Marked by Agent
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### React on message  for  Instagram message

        Marked by agent for the Instagram channel (POST /message/markReadByAgent). Required query parameter: `conversationId`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/message/markReadByAgent`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `conversationId` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_message_markReadByAgent
      parameters:
      - name: conversationId
        in: query
        required: false
        schema:
          type: string
        example: '17841405085181107_2838041469865177'
      responses:
        '200':
          description: OK
  /instagram/message/sendPrivateMessage:
    post:
      tags:
      - Instagram
      summary: React on message  for  Instagram message
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### React on message  for  Instagram message

        Private message for the Instagram channel (POST /message/sendPrivateMessage). Required query parameter: `commentId`. The request body is a `String`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/message/sendPrivateMessage`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `commentId` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_message_sendPrivateMessage
      parameters:
      - name: commentId
        in: query
        required: false
        schema:
          type: string
        example: <commentId>
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              React on message  for  Instagram message:
                value: ''
      responses:
        '200':
          description: OK
  /instagram/template:
    post:
      tags:
      - Instagram
      summary: Create Text Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a new template

        Create Template for the Instagram channel (POST /template). The request body is a `IgTemplateRequest`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/template`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `name` | `string` |
        | `templateType` | `string` |
        | `elementsJson` | `string` |
        | `promptText` | `string` |
        | `quickRepliesJson` | `string` |
        | `category` | `string` |
        | `description` | `string` |
        | `language` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_template
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                templateType:
                  type: string
                promptText:
                  type: string
                category:
                  type: string
            examples:
              Create Text Template:
                value:
                  name: welcome
                  templateType: TEXT_TEMPLATE
                  promptText: Welcome!
                  category: ONBOARDING
              Create Quick Create Template:
                value:
                  name: support
                  templateType: QUICK_REPLY
                  promptText: Help?
                  quickRepliesJson: '[{"content_type":"text","title":"Yes","payload":"Y"}]'
                  category: SUPPORT
      responses:
        '200':
          description: OK
    get:
      tags:
      - Instagram
      summary: Get by Name
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a template by name

        Get by name for the Instagram channel (GET /template). Required query parameter: `name`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /instagram/template`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `name` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_instagram_template
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: welcome
      responses:
        '200':
          description: OK
  /instagram/template/1:
    put:
      tags:
      - Instagram
      summary: Update Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update an existing template

        Update Template for the Instagram channel (PUT /template/{id}). Path parameter `id` identifies the target resource. The request body is a `IgTemplateRequest`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `PUT /instagram/template/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `name` | `string` |
        | `templateType` | `string` |
        | `elementsJson` | `string` |
        | `promptText` | `string` |
        | `quickRepliesJson` | `string` |
        | `category` | `string` |
        | `description` | `string` |
        | `language` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: put_instagram_template_1
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                description:
                  type: string
            examples:
              Update Template:
                value:
                  description: Updated
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Instagram
      summary: Delete Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a template

        Delete Template for the Instagram channel (DELETE /template/{id}). Path parameter `id` identifies the target resource. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `DELETE /instagram/template/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_instagram_template_1
      responses:
        '200':
          description: OK
  /instagram/template/list:
    get:
      tags:
      - Instagram
      summary: List Templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List all templates with pagination, filters, sorting and date range

        List all for the Instagram channel (GET /template/list). Optional: `category`, `page`, `size`, `search`, `templateType`, `active`, `sortBy`, `sortDirection`, `startDate`, `endDate`, `toGmt`, `language`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /instagram/template/list`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `category` | query | no |  |
        | `page` | query | no |  (default `0`) |
        | `size` | query | no |  (default `10`) |
        | `search` | query | no |  |
        | `templateType` | query | no |  |
        | `active` | query | no |  |
        | `sortBy` | query | no |  |
        | `sortDirection` | query | no |  |
        | `startDate` | query | no |  |
        | `endDate` | query | no |  |
        | `toGmt` | query | no |  |
        | `language` | query | no |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_instagram_template_list
      parameters:
      - name: category
        in: query
        required: false
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: templateType
        in: query
        required: false
        schema:
          type: string
      - name: active
        in: query
        required: false
        schema:
          type: string
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      - name: language
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /instagram/template/send:
    post:
      tags:
      - Instagram
      summary: Send by Name
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Send a message using a saved template name

        Send by template name for the Instagram channel (POST /template/send). Required query parameters: `templateName`, `destinationNo`. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /instagram/template/send`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `templateName` | query | yes |  |
        | `destinationNo` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_instagram_template_send
      parameters:
      - name: templateName
        in: query
        required: false
        schema:
          type: string
        example: welcome
      - name: destinationNo
        in: query
        required: false
        schema:
          type: string
        example: IG_RECIPIENT_ID
      responses:
        '200':
          description: OK
  /instagram/template/grouped:
    get:
      tags:
      - Instagram
      summary: Get Grouped Templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        Returns all active templates for the authenticated account grouped by category. Only `AUTHENTICATION`, `MARKETING`, and `UTILITY` categories are returned. Empty lists are included for categories with no templates.

        **Endpoint:** `GET /instagram/template/grouped`

        ### Response — 200 OK

        ``` json
        {
            "UTILITY": [
                {
                    "id": 15,
                    "name": "welcome_message_v90"
                }
            ],
            "MARKETING": [
                {
                    "id": 16,
                    "name": "new template test v2"
                }
            ],
            "AUTHENTICATION": [
                {
                    "id": 19,
                    "name": "auth_otp_verification"
                }
            ]
        }

         ```

        ### Notes

        - Only active templates are returned.

        - Always returns all 3 keys even if empty.

        - Supported categories: `AUTHENTICATION`, `MARKETING`, `UTILITY`.
      operationId: get_instagram_template_grouped
      responses:
        '200':
          description: OK
  /instagram/message/all-bulk:
    post:
      tags:
      - Instagram
      summary: Get All Batches
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## List the tenant's bulk campaigns

        Optional filter body supports `status`, `campaignType`, `messageType`, `active`, `scheduled`, date ranges.

        **Status filter accepts** any of: `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED`, `FAILED`.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)
      operationId: post_instagram_message_all_bulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                page:
                  type: string
                size:
                  type: string
                toGmt:
                  type: string
                sortBy:
                  type: string
                sortDir:
                  type: string
            examples:
              Get All Batches:
                value:
                  page: '0'
                  size: '10'
                  toGmt: +05:30
                  sortBy: batchId
                  sortDir: DESC
      responses:
        '200':
          description: OK
  /instagram/message/edit:
    get:
      tags:
      - Instagram
      summary: Get Batch Details
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Load a batch for editing (pauses if live)

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED` (if was INPROGRESS), record returned
      operationId: get_instagram_message_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: IG_BATCH_ID
      responses:
        '200':
          description: OK
  /instagram/message/pause:
    get:
      tags:
      - Instagram
      summary: Pause Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Pause an in-flight batch

        - **Allowed initial status**: `PENDING`, `INPROGRESS`
        - Returns `400` if status is `PAUSED`, `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED`
      operationId: get_instagram_message_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: IG_BATCH_ID
      responses:
        '200':
          description: OK
  /instagram/message/resume:
    get:
      tags:
      - Instagram
      summary: Resume Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Resume a paused batch

        - **Allowed initial status**: `PAUSED` only
        - Returns `400` if status is `PENDING`, `INPROGRESS`, `DONE`, `ABORTED`, `FAILED` (prevents DONE/ABORTED re-fire)
        - On success: status → `INPROGRESS`
      operationId: get_instagram_message_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: IG_BATCH_ID
      responses:
        '200':
          description: OK
  /instagram/message/abort:
    delete:
      tags:
      - Instagram
      summary: Abort Batch
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists
      operationId: delete_instagram_message_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: IG_BATCH_ID
      responses:
        '200':
          description: OK
  /push/apps:
    post:
      tags:
      - Push
      summary: '[operator] Register Application'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Onboarding step 1 — register a tenant application and obtain a public `appId` plus an `sdkKey`. ONE registration serves ALL channels via the `platforms` array (`ANDROID` | `IOS` | `WEB`).

        **Platforms:** send `platforms` (e.g. `["WEB"]`, `["ANDROID","WEB"]`, `["ANDROID","IOS","WEB"]`). Legacy single-value `platform` (ANDROID | IOS | BOTH | ALL) is still honoured when `platforms` is omitted. An unknown platform → 400.

        **WEB fields (required only when** **`platforms`** **contains WEB):** `apiKey`, `webAppId`, `vapidPublicKey` (plus optional `authDomain`, `messagingSenderId`). The browser fetches these back via `GET /apps/{appId}/config` (`.web` block). `authDomain` defaults to `.firebaseapp.com`.

        **ANDROID / IOS:** provision a Firebase Android app + google-services on first registration; no extra body fields.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_apps
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                _comment:
                  type: string
                appName:
                  type: string
                packageName:
                  type: string
                platforms:
                  type: array
                  items:
                    type: string
                apiKey:
                  type: string
                authDomain:
                  type: string
                webAppId:
                  type: string
                messagingSenderId:
                  type: string
                vapidPublicKey:
                  type: string
            examples:
              '[operator] Register Application':
                value:
                  _comment: 'platforms drives channels: [''ANDROID''] | [''IOS''] | [''WEB''] | [''ANDROID'',''WEB''] | [''ANDROID'',''IOS'',''WEB''].
                    When WEB is present apiKey, webAppId and vapidPublicKey are REQUIRED. Legacy single ''platform'' (ANDROID|IOS|BOTH|ALL)
                    still works when ''platforms'' is omitted.'
                  appName: BroadNet Demo App
                  packageName: com.broadnet.demo
                  platforms:
                  - WEB
                  apiKey: YOUR_TOKEN
                  authDomain: your-firebase-project.firebaseapp.com
                  webAppId: 1:220260377621:web:PASTE_WEB_APP_ID
                  messagingSenderId: '220260377621'
                  vapidPublicKey: PASTE_VAPID_PUBLIC_KEY
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    get:
      tags:
      - Push
      summary: '[operator] List Applications'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** List every application registered under the tenant.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_apps
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/apps/google-services/{APP_ID}:
    get:
      tags:
      - Push
      summary: '[operator] Get google-services.json'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Return the stored `google-services.json` for the Android app so the client team can drop it into the mobile build.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_apps_google_services_APP_ID
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/apps/{APP_ID}/config:
    get:
      tags:
      - Push
      summary: '[operator] Get App Config'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Unified client-config for an app across ALL channels. Returns `platforms` plus a conditional `android` block (firebaseAppId + google-services, when the app targets ANDROID) and a conditional `web` block (the browser `firebaseConfig` + `vapidKey`, when the app has a WEB config). The web harness fetches this on load to build `firebase.initializeApp(...)` and the `getToken` VAPID key.

        404 if the app does not exist. **DB:** `onboarded_business_client` (read). The legacy `GET /apps/google-services/{appId}` remains for Android-only back-compat.
      operationId: get_push_apps_APP_ID_config
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/apps/google-services-ios/{APP_ID}:
    get:
      tags:
      - Push
      summary: '[operator] Get google services iOS'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Get google services iOS

        Get google services iOS for the Push channel (GET /apps/google-services-ios/{appId}). Path parameter `appId` identifies the target resource. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/apps/google-services-ios/{appId}`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `appId` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_apps_google_services_ios_APP_ID
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/apps/{APP_ID}/apns-credential:
    post:
      tags:
      - Push
      summary: '[operator] Onboard a direct-APNs credential (.p8 token or .p12 cert)'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Onboard a direct-APNs credential (.p8 token or .p12 cert)

        Attaches APNs credentials (AES-encrypted at rest) and sets provider=APNS_DIRECT for the app.

        **Endpoint** `POST /push/apps/{appId}/apns-credential`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `appId` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        | --- | --- |
        | `authMode` | `string` |
        | `bundleId` | `string` |
        | `p8Key` | `string` |
        | `keyId` | `string` |
        | `teamId` | `string` |
        | `p12Base64` | `string` |
        | `p12Password` | `string` |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_push_apps_APP_ID_apns_credential
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                authMode:
                  type: string
                bundleId:
                  type: string
                p8Key:
                  type: string
                keyId:
                  type: string
                teamId:
                  type: string
                p12Base64:
                  type: string
                p12Password:
                  type: string
            examples:
              '[operator] Onboard a direct-APNs credential (.p8 token or .p12 cert)':
                value:
                  authMode: ''
                  bundleId: ''
                  p8Key: ''
                  keyId: ''
                  teamId: ''
                  p12Base64: ''
                  p12Password: ''
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/apps/{APP_ID}/status:
    get:
      tags:
      - Push
      summary: '[operator] Get App Provisioning Status'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        Polls the fine-grained auto-provisioning status of an app that was registered with provision: true.

        Path variable:

        - appId (string, required): The generated app id returned from Register Application.


        Response includes provisionStatus (PENDING through READY / FAILED), any provisionError, the selected platforms, and the projectId.

        Headers:

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_apps_APP_ID_status
      parameters:
      - name: APP_ID
        in: path
        required: true
        schema:
          type: string
        example: APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard:
    post:
      tags:
      - Push
      summary: '[operator] Create Tenant Credential'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Onboarding step 2 — create the per-tenant push credential record (FCM project binding, rate limit, billing tier, customer webhook URL). The private key is AES-encrypted at rest and NEVER returned.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: post_push_push_clients_onboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                webhookUrl:
                  type: string
                webhookToken:
                  type: string
                description:
                  type: string
                status:
                  type: string
                rateLimit:
                  type: integer
                tierId:
                  type: integer
                passthroughFeeEnabled:
                  type: boolean
            examples:
              '[operator] Create Tenant Credential':
                value:
                  username: '{{USERNAME}}'
                  webhookUrl: https://example.com/push/webhook
                  webhookToken: REPLACE_WITH_WEBHOOK_TOKEN
                  description: Android E2E test tenant
                  status: ACTIVE
                  rateLimit: 60
                  tierId: 1
                  passthroughFeeEnabled: false
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard/update/{CREDENTIAL_ID}:
    put:
      tags:
      - Push
      summary: '[operator] Update Tenant Credential'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Update a tenant credential (rotate webhook URL/secret, change rate limit, tier, status). Hot-swaps the running webhook-forward workers so a changed `webhookUrl` takes effect without a restart.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: put_push_push_clients_onboard_update_CREDENTIAL_ID
      parameters:
      - name: CREDENTIAL_ID
        in: path
        required: true
        schema:
          type: string
        example: CREDENTIAL_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                projectId:
                  type: string
                clientEmail:
                  type: string
                privateKey:
                  type: string
                webhookUrl:
                  type: string
                webhookToken:
                  type: string
                description:
                  type: string
                status:
                  type: string
                rateLimit:
                  type: integer
                tierId:
                  type: integer
                passthroughFeeEnabled:
                  type: boolean
                applyToIncoming:
                  type: boolean
                sandbox:
                  type: boolean
            examples:
              '[operator] Update Tenant Credential':
                value:
                  username: '{{USERNAME}}'
                  projectId: your-firebase-project
                  clientEmail: push-service@your-firebase-project.iam.gserviceaccount.com
                  privateKey: YOUR_TOKEN
                  webhookUrl: https://example.com/push/webhook
                  webhookToken: REPLACE_WITH_WEBHOOK_TOKEN
                  description: Updated demo tenant push credential
                  status: ACTIVE
                  rateLimit: 120
                  tierId: 1
                  passthroughFeeEnabled: false
                  applyToIncoming: false
                  sandbox: false
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard/delete/{CREDENTIAL_ID}:
    delete:
      tags:
      - Push
      summary: '[operator] Delete Tenant Credential'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Off-board a tenant — delete the credential and stop its queue processor.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: delete_push_push_clients_onboard_delete_CREDENTIAL_ID
      parameters:
      - name: CREDENTIAL_ID
        in: path
        required: true
        schema:
          type: string
        example: CREDENTIAL_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard/all:
    get:
      tags:
      - Push
      summary: '[operator] List Tenant Credentials (paginated)'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Admin console listing of all onboarded tenants, with pagination, date-range, status and free-text filters plus GMT conversion.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: get_push_push_clients_onboard_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: status
        in: query
        required: false
        schema:
          type: string
        example: ACTIVE
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: desc
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard/{CREDENTIAL_ID}:
    get:
      tags:
      - Push
      summary: '[operator] Get Tenant Credential by ID'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Fetch one credential by its numeric id.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: get_push_push_clients_onboard_CREDENTIAL_ID
      parameters:
      - name: CREDENTIAL_ID
        in: path
        required: true
        schema:
          type: string
        example: CREDENTIAL_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/push-clients-onboard/me:
    get:
      tags:
      - Push
      summary: '[operator] Get My Tenant Credential'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        **Business purpose:** Return the caller's own credential (resolved from the `username` header) — the self-service variant. Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_push_clients_onboard_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /push/message/send:
    post:
      tags:
      - Push
      summary: 1 - Simple Notification (by userRef)
      description: |-
        TYPE 1 - REQUIRED: userRefs, title, body, category. Simplest send — target resolved by userRef (your registered user identifier), NOT an FCM token. dataOnly=true so the SDK still receives it even if the app is backgrounded. priority=HIGH recommended for anything time-sensitive.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_message_send
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              1 - Simple Notification (by userRef):
                value: |-
                  {
                  "userRefs": [
                      "android-83e27eea4a25",
                      "android-83e27eea4a25",
                      "android-83e27eea4a25"
                      ],
                      "title": "Hello!",
                      "body": "This is a simple notification.",
                      "priority": "HIGH",  //Optional
                      "category": "UTILITY",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 3600,                    //Optional
                      "collapseKey": "generic-alert", //Optional
                      "dryRun": false                 //Optional
                  }
              2 - Send by Explicit Device Token:
                value: |-
                  {
                      "tokens": ["dSq_UAoVQOi9Jb0GsVMq8b:APA91bERvHZg91lfiZtAVFreTyXyR_lD-tdKHx8U2A8bC3eQNJM4nLT2-AiEtub9O9LP-Ve9bHI_A8WdK7LKzQpaWLafn2loTXz887n-H67HLY4F6Ph1Rk4"],
                      "title": "Direct Token Send",
                      "body": "Sent to an explicit FCM device token.",
                      "priority": "HIGH",  //Optional
                      "category": "UTILITY",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 3600,        //Optional
                      "collapseKey": "x", //Optional
                      "dryRun": false     //Optional
                  }
              3 - Send to FCM Topic (Broadcast):
                value: |-
                  {
                      "topics": ["news-alerts"],
                      "title": "Breaking News",
                      "body": "Topic-based broadcast to all subscribed devices.",
                      "priority": "HIGH",  //Optional
                      "category": "MARKETING",  //Optional
                      "dataOnly": false,  //Optional
                      "ttl": 3600,          //Optional
                      "collapseKey": "news" //Optional
                  }
              4 - Image Notification (Big Picture):
                value: |-
                  {
                  "userRefs": [
                      "android-83e27eea4a25",
                      "android-83e27eea4a25",
                      "android-83e27eea4a25"
                      ],
                      "title": "New Offer!",
                      "body": "Tap to see your exclusive offer.",
                      "image": "https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png",  //Optional
                      "priority": "HIGH",  //Optional
                      "category": "MARKETING",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 86400,       //Optional
                      "channel": "promotions" //Optional
                  }
              5 - Deep-Link Notification:
                value: |-
                  {
                  "userRefs": [
                      "android-83e27eea4a25",
                      "android-83e27eea4a25",
                      "android-83e27eea4a25"
                      ],
                      "title": "Your order shipped!",
                      "body": "Tap to track your package.",
                      "deepLink": "https://www.broadnet.me/login",  //Optional
                      "priority": "HIGH",  //Optional
                      "category": "UTILITY",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 3600, //Optional
                      "data": { "screen": "OrderTracking" } //Optional
                  }
              6 - Action Buttons:
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "title": "Appointment Reminder",
                      "body": "You have an appointment tomorrow at 10 AM.",
                      "priority": "HIGH",  //Optional
                      "category": "UTILITY",  //Optional
                      "dataOnly": true,  //Optional
                      "actions": [
                          { "id": "confirm", "title": "Confirm", "action": "myapp://appt/confirm/12" },
                          { "id": "cancel",  "title": "Cancel",  "action": "myapp://appt/cancel/12" }
                      ],  //Optional
                      "ttl": 3600, //Optional
                      "image": "https://..." //Optional
                  }
              7 - Silent / Background-Sync Push:
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "silent": true,  //Optional
                      "data": {
                          "syncType": "INBOX_REFRESH",
                          "timestamp": "2026-07-20T10:00:00Z"
                      },  //Optional
                      "category": "UTILITY",  //Optional
                      "ttl": 300 //Optional
                  }
              8 - Data-Only Push (no title/body):
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "dataOnly": true,  //Optional
                      "data": {
                          "event": "CONFIG_UPDATE",
                          "version": "3.1"
                      },  //Optional
                      "category": "UTILITY",  //Optional
                      "ttl": 3600 //Optional
                  }
              9 - Send via Stored Template:
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "templateId": "TPL_B342F9BA9507",
                      "data": {
                          "name": "Sourabh",
                          "promoCode": "SAVE20"
                      },  //Optional
                      "category": "MARKETING",  //Optional
                      "dataOnly": true,  //Optional
                      "priority": "HIGH", //Optional
                      "ttl": 3600         //Optional
                  }
              10 - Dry-Run Send (validation only):
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "title": "Test",
                      "body": "Dry-run — no actual delivery.",
                      "priority": "HIGH",  //Optional
                      "category": "UTILITY",  //Optional
                      "dataOnly": true,  //Optional
                      "dryRun": true  //Optional
                  }
              11 - TTL + Collapse Key:
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "title": "FLASH SALE EXTENDED!",
                      "body": "Now 7 hours left! Don't miss out!",
                      "priority": "HIGH",  //Optional
                      "ttl": 25200,  //Optional
                      "collapseKey": "flash-sale",  //Optional
                      "category": "MARKETING",  //Optional
                      "dataOnly": true  //Optional
                  }
              12 - Image + Deep Link (Combo):
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "title": "Special Offer!",
                      "body": "Tap to claim your exclusive discount now.",
                      "image": "https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png",  //Optional
                      "deepLink": "https://www.broadnet.me/login",  //Optional
                      "priority": "HIGH",  //Optional
                      "category": "MARKETING",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 86400,              //Optional
                      "channel": "promotions",   //Optional
                      "data": { "offer_id": "OFFER_2026" } //Optional
                  }
              13 - OTP / Authentication Push:
                value: |-
                  {
                      "userRefs": ["android-83e27eea4a25"],
                      "title": "Your OTP Code",
                      "body": "Your verification code is 482913. Valid for 5 minutes.",
                      "priority": "HIGH",  //Optional
                      "category": "AUTHENTICATION",  //Optional
                      "dataOnly": true,  //Optional
                      "ttl": 300,  //Optional
                      "collapseKey": "otp" //Optional
                  }
              Send scheduled campaign:
                value:
                  appId: '{{APP_ID}}'
                  title: Weekly
                  body: newsletter
                  campaignName: weekly-1
                  schedule:
                    scheduled: true
                    scheduleTime: '2099-01-01 10:00:00'
                    gmt: +00:00
                    campaignType: BROADCAST
              Send broadcast campaign (immediate):
                value:
                  appId: '{{APP_ID}}'
                  title: Flash
                  body: sale now
                  campaignName: flash-1
                  schedule:
                    scheduled: false
                    campaignType: BROADCAST
              Send multiple userRefs:
                value:
                  appId: '{{APP_ID}}'
                  userRefs:
                  - USER001
                  - USER002
                  campaignName: promo-1
                  title: Sale
                  body: 50% off
                  category: PROMO
              Send segment (criteria + tags):
                value:
                  appId: '{{APP_ID}}'
                  segment:
                    country: AE
                    city: Dubai
                    language: en
                    tags:
                      tier: gold
                  title: Hi
                  body: segment send
      responses:
        '200':
          description: OK
  /push/message/pause:
    get:
      tags:
      - Push
      summary: Pause Batch (pause)
      description: |-
        **Business purpose:** Pause an in-flight batch (status → PAUSED) without discarding progress.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_message_pause
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /push/message/resume:
    get:
      tags:
      - Push
      summary: Resume Batch (resume)
      description: |-
        **Business purpose:** Resume a previously PAUSED batch from its last checkpoint (status → INPROGRESS).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_message_resume
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /push/message/edit:
    get:
      tags:
      - Push
      summary: Edit Batch (edit)
      description: |-
        **Business purpose:** Load a batch for editing — pauses it if live and returns the full batch record so it can be modified and re-submitted via /message/send.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_message_edit
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /push/message/batches:
    post:
      tags:
      - Push
      summary: Get Batch by id (batches filter)
      description: |-
        **Business purpose:** Fetch a single campaign batch by id (filter the tenant's batches by batchId). Replaces the old GET /schedule/{batchId}.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_message_batches
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              Get Batch by id (batches filter):
                value: |-
                  {
                    "batchId": {{BATCH_ID}}
                  }
              List / Filter Batches (batches):
                value:
                  page: 0
                  size: 20
                  sortBy: batchId
                  sortDir: DESC
      responses:
        '200':
          description: OK
  /push/message/abort:
    delete:
      tags:
      - Push
      summary: Abort Batch (abort)
      description: |-
        **Business purpose:** Abort a scheduled/in-progress/paused batch (status → ABORTED) and stop its worker thread. A DONE/ABORTED batch returns `400`. Replaces POST /schedule/{batchId}/cancel.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: delete_push_message_abort
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /push/template/create:
    post:
      tags:
      - Push
      summary: Create Template
      description: |-
        **Business purpose:** Create a reusable push template. The local DB is the system of record (FCM has no server-side templates); title/body may carry `{{PUSH_PLACEHOLDER}}` tokens substituted from the send-time `data` map.

        **Validation:** `templateName` required + unique per tenant (duplicate → 400); at least one of title/body/data must be set. `category` = TRANSACTIONAL (default) | PROMO.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                templateName:
                  type: string
                category:
                  type: string
                language:
                  type: string
                title:
                  type: string
                body:
                  type: string
                data:
                  type: object
                  properties:
                    deepLink:
                      type: string
                status:
                  type: string
            examples:
              Create Template:
                value:
                  templateName: order-shipped
                  category: TRANSACTIONAL
                  language: en
                  title: Order {{ORDER_ID}} shipped
                  body: Hi {{NAME}}, your order is on its way!
                  data:
                    deepLink: broadnet://orders/{{ORDER_ID}}
                  status: ACTIVE
              Create Template — localized (+overrides +actions):
                value:
                  templateName: order-shipped-i18n
                  category: TRANSACTIONAL
                  language: en
                  title: Hi {{NAME}}, order {{ORDER_ID}} shipped
                  body: Your order is on its way!
                  imageUrl: https://cdn.example.com/shipped.png
                  data:
                    deepLink: broadnet://orders/{{ORDER_ID}}
                  defaults:
                    name: there
                  localizations:
                  - locale: ar
                    title: مرحباً {{NAME}}، تم شحن الطلب {{ORDER_ID}}
                    body: طلبك في الطريق!
                  - locale: es
                    title: Hola {{NAME}}, pedido {{ORDER_ID}} enviado
                    body: ¡Tu pedido va en camino!
                  overrides:
                    IOS:
                      title: Order {{ORDER_ID}} shipped
                      body: Tap to track
                  actions:
                  - id: track
                    title: Track
                    action: broadnet://orders/{{ORDER_ID}}/track
                  status: DRAFT
      responses:
        '200':
          description: OK
  /push/template/list:
    post:
      tags:
      - Push
      summary: List Templates
      description: |-
        **Business purpose:** List templates with optional category/search filter + pagination. **DB:** `template` (read).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_list
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                category:
                  type: string
                search:
                  type: string
                page:
                  type: integer
                size:
                  type: integer
            examples:
              List Templates:
                value:
                  category: TRANSACTIONAL
                  search: ''
                  page: 0
                  size: 50
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}:
    get:
      tags:
      - Push
      summary: Get Template
      description: |-
        **Business purpose:** Fetch one template by id.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_template_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
    put:
      tags:
      - Push
      summary: Update Template
      description: |-
        **Business purpose:** Update a template by id.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: put_push_template_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                templateName:
                  type: string
                category:
                  type: string
                language:
                  type: string
                title:
                  type: string
                body:
                  type: string
                data:
                  type: object
                  properties:
                    deepLink:
                      type: string
                status:
                  type: string
            examples:
              Update Template:
                value:
                  templateName: order-shipped
                  category: TRANSACTIONAL
                  language: en
                  title: Order {{ORDER_ID}} shipped
                  body: Hi {{NAME}}, great news — your order is on its way!
                  data:
                    deepLink: broadnet://orders/{{ORDER_ID}}
                  status: ACTIVE
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Push
      summary: Delete Template
      description: |-
        **Business purpose:** Delete a template by id.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: delete_push_template_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      - name: hard
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}/publish:
    post:
      tags:
      - Push
      summary: Publish Template
      description: |-
        **Publish** a DRAFT template → PUBLISHED (version bump). Tested live: DRAFT→PUBLISHED.

        ⚠️ Requires a **PRODUCTION** credential — a sandbox/DEVELOPMENT credential returns 400 _"Sandbox credential cannot perform LIVE template operations."_

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_TEMPLATE_ID_publish
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}/preview:
    post:
      tags:
      - Push
      summary: Preview Template
      description: |-
        **Preview** = render a template WITHOUT sending. Body uses **`variables`** (the `{{PUSH_PLACEHOLDER}}` values), plus optional `locale` (pick a localization) and `platform` (apply an override). Substitution DOES work — send `variables` (not `data`). `locale:"ar"` returns the Arabic localization if one exists, else the base.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_TEMPLATE_ID_preview
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                variables:
                  type: object
                  properties:
                    name:
                      type: string
                    orderId:
                      type: string
                locale:
                  type: string
                platform:
                  type: string
            examples:
              Preview Template:
                value:
                  variables:
                    name: Alex
                    orderId: ORD-12345
                  locale: ar
                  platform: ANDROID
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}/test-send:
    post:
      tags:
      - Push
      summary: Test-send Template
      description: |-
        **Test-send** a rendered one-off to a single `userRef` (or `token`). Body uses **`variables`** + optional `locale`. Internally maps variables → the send `data` and delivers.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_TEMPLATE_ID_test_send
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                userRef:
                  type: string
                variables:
                  type: object
                  properties:
                    name:
                      type: string
                    orderId:
                      type: string
                locale:
                  type: string
            examples:
              Test-send Template:
                value:
                  userRef: '{{USER_REF}}'
                  variables:
                    name: Alex
                    orderId: ORD-12345
                  locale: en
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}/clone:
    post:
      tags:
      - Push
      summary: Clone Template
      description: |-
        **Clone** a template as `-copy` (new templateId, DRAFT). Tested live: HTTP 200.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_template_TEMPLATE_ID_clone
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
  /push/template/{TEMPLATE_ID}/history:
    get:
      tags:
      - Push
      summary: Get Template History (versions)
      description: |-
        **Version history**, newest first (`template_version` table). Every _publish/update_ snapshots the full template (incl. all localizations) into a new immutable version. Use for **audit** (what wording went out & when), **rollback**, and **reproducibility**.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_template_TEMPLATE_ID_history
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
  /push/template/device-tokens:
    get:
      tags:
      - Push
      summary: List distinct userRef + token pairs for the logged-in tenant
      description: |-
        ### List distinct userRef + token pairs for the logged-in tenant

        List device tokens for the Push channel (GET /template/device-tokens). Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/template/device-tokens`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_template_device_tokens
      responses:
        '200':
          description: OK
  /push/template/grouped:
    get:
      tags:
      - Push
      summary: Get grouped templates by category
      description: |-
        ### Get grouped templates by category

        Get grouped for the Push channel (GET /template/grouped). Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/template/grouped`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_template_grouped
      responses:
        '200':
          description: OK
  /push/template/name/{TEMPLATE_NAME}:
    get:
      tags:
      - Push
      summary: Get latest template by template name
      description: |-
        ### Get latest template by template name

        Get by name for the Push channel (GET /template/name/{templateName}). Path parameter `templateName` identifies the target resource. Responds with the operation result on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/template/name/{templateName}`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `templateName` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_template_name_TEMPLATE_NAME
      parameters:
      - name: TEMPLATE_NAME
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_NAME
      responses:
        '200':
          description: OK
  /push/geofence:
    post:
      tags:
      - Push
      summary: Create Geofence
      description: |-
        **Business purpose:** Create a geofence (lat/lon + radius) optionally bound to a template (`messageId`) that auto-sends on ENTER. **Validation:** `name`, `lat`, `lon` required; `radiusM` positive. **DB:** `push_geofence` (insert).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_geofence
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                lat:
                  type: number
                lon:
                  type: number
                radiusM:
                  type: integer
                messageId:
                  type: string
                status:
                  type: string
            examples:
              Create Geofence:
                value:
                  name: HQ Office
                  lat: 17.4485
                  lon: 78.3908
                  radiusM: 200
                  messageId: '{{TEMPLATE_ID}}'
                  status: ACTIVE
      responses:
        '200':
          description: OK
    get:
      tags:
      - Push
      summary: List Geofences
      description: |-
        **Business purpose:** List all geofences for the tenant. **DB:** `push_geofence` (read).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_geofence
      parameters:
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: category
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: desc
      responses:
        '200':
          description: OK
  /push/geofence/active:
    get:
      tags:
      - Push
      summary: List Active Geofences
      description: |-
        **Business purpose:** List ACTIVE geofences — consumed by the device SDK for local geofence registration. **DB:** `push_geofence` (read where status=ACTIVE).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_geofence_active
      parameters:
      - name: lat
        in: query
        required: false
        schema:
          type: string
        example: '78.2893'
      - name: lon
        in: query
        required: false
        schema:
          type: string
        example: '88.37'
      - name: max
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /push/geofence/{GEOFENCE_ID}:
    get:
      tags:
      - Push
      summary: Get Geofence
      description: |-
        **Business purpose:** Fetch one geofence by id. **DB:** `push_geofence` (read).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_push_geofence_GEOFENCE_ID
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
    put:
      tags:
      - Push
      summary: Update Geofence
      description: |-
        **Business purpose:** Update a geofence by id. **DB:** `push_geofence` (update).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: put_push_geofence_GEOFENCE_ID
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                lat:
                  type: number
                lon:
                  type: number
                radiusM:
                  type: integer
                messageId:
                  type: string
                status:
                  type: string
            examples:
              Update Geofence:
                value:
                  name: HQ Office
                  lat: 17.4485
                  lon: 78.3908
                  radiusM: 300
                  messageId: '{{TEMPLATE_ID}}'
                  status: ACTIVE
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Push
      summary: Delete Geofence
      description: |-
        **Business purpose:** Delete a geofence by id. **DB:** `push_geofence` (delete).

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: delete_push_geofence_GEOFENCE_ID
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
  /push/geofence/event:
    post:
      tags:
      - Push
      summary: Record Geofence Event (via /geofence/event)
      description: |-
        **Business purpose:** Ingest a geofence transition from the device SDK. On ENTER, if the fence has a bound template, a TRANSACTIONAL push is auto-sent to the user. **Validation:** `type` (ENTER | EXIT | DWELL) + `geofenceId` required. **DB:** `push_geofence_event` (insert); may trigger a send.

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: post_push_geofence_event
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                geofenceId:
                  type: integer
                userRef:
                  type: string
                ts:
                  type: string
            examples:
              Record Geofence Event (via /geofence/event):
                value:
                  type: ENTER
                  geofenceId: 1
                  userRef: '{{USER_REF}}'
                  ts: '2026-06-26 12:00:00'
      responses:
        '200':
          description: OK
  /push/geofence/resync:
    post:
      tags:
      - Push
      summary: Resync Geofence Resync
      description: |-
        ### Resync Geofence Resync

        Resync Geofence Resync for the Push channel (POST /geofence/resync). Responds with `Map` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /push/geofence/resync`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_push_geofence_resync
      responses:
        '200':
          description: OK
  /push/geofence/{GEOFENCE_ID}/audit:
    get:
      tags:
      - Push
      summary: Audit Geofence Audit
      description: |-
        ### Audit Geofence Audit

        Audit Geofence Audit for the Push channel (GET /geofence/{id}/audit). Path parameter `id` identifies the target resource. Responds with `List` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/geofence/{id}/audit`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_geofence_GEOFENCE_ID_audit
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
  /push/geofence/{GEOFENCE_ID}/disable:
    post:
      tags:
      - Push
      summary: Disable Geofence Disable
      description: |-
        ### Disable Geofence Disable

        Disable Geofence Disable for the Push channel (POST /geofence/{id}/disable). Path parameter `id` identifies the target resource. Responds with `GeofenceResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /push/geofence/{id}/disable`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_push_geofence_GEOFENCE_ID_disable
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
  /push/geofence/{GEOFENCE_ID}/enable:
    post:
      tags:
      - Push
      summary: Enable Geofence Enable
      description: |-
        ### Enable Geofence Enable

        Enable Geofence Enable for the Push channel (POST /geofence/{id}/enable). Path parameter `id` identifies the target resource. Responds with `GeofenceResponse` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `POST /push/geofence/{id}/enable`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_push_geofence_GEOFENCE_ID_enable
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
  /push/geofence/{GEOFENCE_ID}/versions:
    get:
      tags:
      - Push
      summary: Versions Geofence Versions
      description: |-
        ### Versions Geofence Versions

        Versions Geofence Versions for the Push channel (GET /geofence/{id}/versions). Path parameter `id` identifies the target resource. Responds with `List` on success; any failure is returned as an `ExceptionResponse` with the HTTP status and an error code. The tenant is identified by the `username` header.

        **Endpoint** `GET /push/geofence/{id}/versions`

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_push_geofence_GEOFENCE_ID_versions
      parameters:
      - name: GEOFENCE_ID
        in: path
        required: true
        schema:
          type: string
        example: GEOFENCE_ID
      responses:
        '200':
          description: OK
  /rcs/agent/onboard:
    post:
      tags:
      - RCS
      summary: Onboard Agent
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Description

        This API is used to **onboard a new RCS agent into the system**.

        It links the Broadnet system with external providers (such as the RCS provider) using shared project credentials (auto-filled from server config), app configuration, and authentication keys.

        The onboarding process sets up:

        - Agent identity mapping (Broadnet + the RCS provider)

        - Project and app linkage

        - Billing and routing configuration

        - Rate limiting and processing mode

        - Webhook configuration (optional)


        ---

        ## Authorization Note (IMPORTANT)

        | Role | Access |
        | --- | --- |
        | `SUPERADMIN` | Allowed to create agent onboarding |
        | `SYSTEM` | Allowed to create agent onboarding |
        | `NORMAL USER` | Not allowed (access denied) |

        Only **SUPERADMIN and SYSTEM roles can execute this API**.

        ---

        ## Endpoint

        ```
        POST /rcs/agent/onboard

         ```

        ---

        # Request Fields

        | Field | Type | Required | Description |
        | --- | --- | --- | --- |
        | username | String | Yes | Tenant username (case-sensitive) |
        | appId | String | Yes | RCS application ID |
        | agentId | String | Yes | Internal Broadnet agent identifier |
        | sinchAgentId | String | Yes | the RCS provider agent ID mapped to this onboarding |
        | agentBearerToken | String | Yes | Bearer token for agent-level authentication |
        | region | String | Yes | Deployment region (e.g., eu, us) |
        | displayName | String | Yes | Human-readable agent name |
        | webhookUrl | String | Optional | Callback URL for webhook events |
        | webhookSecret | String | Optional | Secret for webhook validation |
        | tierId | Integer | Yes | Pricing/billing tier identifier |
        | category | String | Yes | Agent category (e.g., Conversational) |
        | useCase | String | Yes | Business use case (e.g., Promotional) |
        | passthroughFeeEnabled | Boolean | Yes | Enables passthrough billing fees |
        | applyToIncoming | Boolean | Yes | Whether incoming messages are billed |
        | billingCategory | String | Yes | Billing type classification |
        | processingMode | String | Yes | Message processing mode (e.g., DISPATCH) |
        | rateLimit | Integer | Yes | Max messages per second/minute allowed |

        ---

        🔒 **Required role:** SUPER
        **Caller header (****`username`****):** `super`
      operationId: post_rcs_agent_onboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                appId:
                  type: string
                agentId:
                  type: string
                sinchAgentId:
                  type: string
                agentBearerToken:
                  type: string
                region:
                  type: string
                displayName:
                  type: string
                webhookUrl:
                  type: string
                webhookSecret:
                  type: string
                tierId:
                  type: integer
                category:
                  type: string
                useCase:
                  type: string
                passthroughFeeEnabled:
                  type: boolean
                applyToIncoming:
                  type: boolean
                billingCategory:
                  type: string
                processingMode:
                  type: string
                rateLimit:
                  type: integer
            examples:
              Onboard Agent:
                value:
                  username: TEST104
                  appId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  agentId: broadnet_ucaafnfj_agent
                  sinchAgentId: 00000000-0000-4000-8000-000000000000
                  agentBearerToken: YOUR_TOKEN
                  region: eu
                  displayName: ACME RCS App
                  webhookUrl: ''
                  webhookSecret: ''
                  tierId: 1
                  category: Conversational
                  useCase: Promotional
                  passthroughFeeEnabled: true
                  applyToIncoming: false
                  billingCategory: NON_CONVERSATIONAL
                  processingMode: DISPATCH
                  rateLimit: 20
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/create:
    post:
      tags:
      - RCS
      summary: '[operator] Create Agent (Stage 1)'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ## Stage 1 — Create the agent stub (SUPER/SYSTEM token)

        Creates the agent record server-side. Only `username` and `appName` are required; other fields are optional and can be filled at `/agent/configure`.

        **No the RCS provider call yet.** Returns **HTTP 201** with the new `agentRef` and `onboardingStatus=CREATED`.

        ---

        🔒 **Required role:** SUPER
        **Caller header (****`username`****):** `super`
      operationId: post_rcs_agent_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                appName:
                  type: string
                region:
                  type: string
            examples:
              '[operator] Create Agent (Stage 1)':
                value:
                  username: '{{RCS_AGENT_USERNAME}}'
                  appName: BroadNet RCS
                  region: US
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/configure:
    put:
      tags:
      - RCS
      summary: Configure Agent (Stage 2)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Stage 2 — Configure the agent (Admin token)

        Server validates 24 required fields and persists them. No the RCS provider call yet. On success: HTTP 200, `onboardingStatus=DETAILS_COMPLETED`.

        ### the RCS provider-mandated vocab (exact strings, case-sensitive)

        - **`useCase`** — one of: `PROMOTIONAL` | `TRANSACTIONAL` | `OTP` | `MULTIUSE` (one word, no underscore)

        - **`legalForm`** — one of: `Corporation` | `Limited Liability Corporation (LLC)` | `Partnership` | `S Corporation` | `Sole Proprietorship` (exact case, with parentheses)

        - **`businessCategory`** — one of the RCS provider's 23 industries: Agriculture, Communication, Construction, Education, Energy, Entertainment, Financial, Gambling, Government, Healthcare, Hospitality, Human Resources, Insurance, Legal, Manufacturing, NGO, Political, Postal, Professional, Real Estate, Retail, Technology, Transportation


        ### Field-level rules

        - `description` must be **≤ 100 chars**

        - `brandColor` must have **WCAG contrast > 4.5** vs white (use a darker hex like `#003388` or darker)

        - `logoUrl` must be **HTTPS, 224×224 PNG/JPG, ≤ 50 KB**

        - `bannerUrl` must be **HTTPS, exactly 1440×448** (if supplied)

        - `brandEmail` + `brandContactEmail` must **NOT** be gmail / yahoo / hotmail / outlook / icloud / aol / live

        - Phones must be **E.164** (e.g. `+447700900114`)

        - US: `addressState` must be 2-char code (`NJ`), `addressPostalCode` must be 5-digit ZIP, `taxId` is the EIN


        ### Required questionnaire block

        `questionnaire.general` MUST contain ALL four non-blank strings: `optInDescription`, `triggerDescription`, `interactionsDescription`, `optOutDescription`. the RCS provider's `launchSender` will reject the agent at Stage 3 without these.

        The body shown here is the and got us to `DETAILS_COMPLETED`.

        ---

        🔒 **Required role:** ANY (super/admin/tenant)
        **Caller header (****`username`****):** `{{RCS_AGENT_USERNAME}}`

        ---

        ### Auth fix (2026-05-29)

        Previously the role check on this endpoint was inverted and accidentally rejected admins/tenants while letting unrelated callers through. The guard now uses `isAuthorizedAll`, so any authenticated principal (SUPER, ADMIN, tenant) can configure their own agent. No body change required.
      operationId: put_rcs_agent_configure
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                displayName:
                  type: string
                description:
                  type: string
                billingCategory:
                  type: string
                useCase:
                  type: string
                brandName:
                  type: string
                legalCompanyName:
                  type: string
                businessCategory:
                  type: string
                legalForm:
                  type: string
                logoUrl:
                  type: string
                bannerUrl:
                  type: string
                brandColor:
                  type: string
                termsOfServiceUrl:
                  type: string
                brandWebsite:
                  type: string
                privacyPolicyUrl:
                  type: string
                brandPhone:
                  type: string
                brandEmail:
                  type: string
                aggregatorName:
                  type: string
                directPartner:
                  type: string
                addressLine1:
                  type: string
                addressLine2:
                  type: string
                addressCity:
                  type: string
                addressState:
                  type: string
                addressPostalCode:
                  type: string
                addressCountry:
                  type: string
                brandContactFirstName:
                  type: string
                brandContactSurname:
                  type: string
                brandContactPosition:
                  type: string
                brandContactEmail:
                  type: string
                brandContactPhone:
                  type: string
                taxId:
                  type: string
                taxIdCountry:
                  type: string
                processingMode:
                  type: string
                launchCountries:
                  type: array
                  items:
                    type: string
                testNumbers:
                  type: array
                  items:
                    type: string
                questionnaire:
                  type: object
                  properties:
                    general:
                      type: object
                      properties:
                        optInDescription:
                          type: string
                        triggerDescription:
                          type: string
                        interactionsDescription:
                          type: string
                        optOutDescription:
                          type: string
            examples:
              Configure Agent (Stage 2):
                value:
                  username: '{{RCS_AGENT_USERNAME}}'
                  displayName: BroadNet Technologies Sarl
                  description: Account alerts, OTPs, and order updates from Broadnet. Reply for support.
                  billingCategory: BASIC
                  useCase: MULTIUSE
                  brandName: BroadNet Technologies Sarl
                  legalCompanyName: BroadNet Technologies Sarl
                  businessCategory: Communication
                  legalForm: Limited Liability Corporation (LLC)
                  logoUrl: https://cdn.example.com/media/2605251026566836215.png
                  bannerUrl: https://cdn.example.com/media/2605251026093035365.jpg
                  brandColor: '#003388'
                  termsOfServiceUrl: https://www.broadnet.me/terms-conditions/
                  brandWebsite: https://www.broadnet.me
                  privacyPolicyUrl: https://www.broadnet.me/privacy-policy/
                  brandPhone: '+447700900114'
                  brandEmail: user@example.com
                  aggregatorName: BroadNet
                  directPartner: the RCS provider
                  addressLine1: 100 Matawan Road
                  addressLine2: Ste 325
                  addressCity: Matawan
                  addressState: NJ
                  addressPostalCode: '07747'
                  addressCountry: US
                  brandContactFirstName: ALEX
                  brandContactSurname: MORGAN
                  brandContactPosition: Senior Team Lead
                  brandContactEmail: user@example.com
                  brandContactPhone: '+447700900114'
                  taxId: 88-2921217
                  taxIdCountry: US
                  processingMode: DISPATCH
                  launchCountries:
                  - US
                  testNumbers:
                  - '+447700900115'
                  - '+447700900116'
                  - '+447700900117'
                  - '+447700900118'
                  questionnaire:
                    general:
                      optInDescription: Users opt in via signup on broadnet.me, SMS keyword JOIN to short code, or in-store
                        registration with brand consent.
                      triggerDescription: Account alerts, OTPs for authentication, order/delivery status updates, and user-initiated
                        support inquiries.
                      interactionsDescription: 'Two-way: users can reply to any message, request support, check order status,
                        or trigger automated workflows.'
                      optOutDescription: Reply STOP, call +447700900114, or unsubscribe at broadnet.me/preferences. Confirmation
                        sent on opt-out.
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/launch:
    post:
      tags:
      - RCS
      summary: Launch Agent
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`

        ## ⚠️ CAUTION — Stage 3 — Launch the agent (Admin token)

        Atomic `createSender → updateSender → launchSender`. If the sender already exists from a prior failed launch, only `updateSender + launchSender` are called (idempotent recovery). Returns `appId`, `agentId`, `senderId` on success.

        **This is a CHARGED the RCS provider operation** — `createSender` is irreversible.

        Allowed source states: `DETAILS_COMPLETED`, `LAUNCHING` (for retry).

        On success: HTTP 200 with `onboardingStatus=PENDING` (carrier + Google review).

        Body fields:

        - `username` — the tenant agent to launch

        - `reviewedBy` — the operator who signed off on the internal review (LOA / proof-of-ownership / final carrier check)

        - `launchCountries` — optional override; if omitted, uses what was captured at create time


        ---

        🔒 **Required role:** SUPER/ADMIN
        **Caller header (****`username`****):** `{{RCS_OPERATOR_USERNAME}}`

        ---

        ### Webhook unification (2026-05-29)

        Single URL handles BOTH Conversation API and Provisioning API events — `WebhookController` auto-dispatches by payload shape. No need to register a separate `/webhook/provisioning` route.

        The request body now accepts two NEW optional overrides:

        - **`webhookUrl`** — optional override; falls back to the `provider.app.webhook-url` global

        - **`webhookSecret`** — optional override; falls back to the `provider.webhook.secret` global


        If BOTH the body override AND the global are blank, `/agent/launch` now returns **`400 Bad Request`** with message _"Webhook URL is not configured — refusing to launch …"_. No more silent launches without a webhook bound.
      operationId: post_rcs_agent_launch
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                reviewedBy:
                  type: string
                launchCountries:
                  type: array
                  items:
                    type: string
                webhookUrl:
                  type: string
                webhookSecret:
                  type: string
            examples:
              Launch Agent:
                value:
                  username: '{{RCS_AGENT_USERNAME}}'
                  reviewedBy: '{{RCS_OPERATOR_NAME}}'
                  launchCountries:
                  - US
                  webhookUrl: https://api.broadnet.me/rcs/webhook
                  webhookSecret: <your-shared-secret>
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/provisioning-webhook:
    post:
      tags:
      - RCS
      summary: Provisioning Webhook Callback
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Register the Provisioning webhook (per tenant project)

        Subscribes the tenant's the RCS provider **project** to provisioning events so updates flow to `/webhook` → `/webhook/provisioning` and sync into `onboarded_agent`.

        **Triggers:** subscribes with `ALL` — every provisioning event type, current and future. For RCS this includes `RCS_SENDER_STATUS_UPDATED` (agent status **and test-number verification** — there is no separate test-number trigger), `RCS_SENDER_OPERATOR_STATUS_UPDATED`, `RCS_BRAND_REGISTRATION_PROCESS_STATUS_UPDATED`, and `RCS_SENDER_COMMENT_ADDED` (carrier review comments).

        **Important:**

        - Requires an **operator / SUPER / SYSTEM** account — a tenant token is rejected with 401.

        - Requires `the provider webhook URL` configured on the server.

        - Idempotent: reuses an existing webhook only if it already subscribes `ALL`; otherwise it deletes + recreates with `ALL` (so older 3-trigger registrations get upgraded).

        - Run once per tenant project if provisioning callbacks aren't arriving (normally auto-registered at `/agent/launch`).
      operationId: post_rcs_agent_provisioning_webhook
      parameters:
      - name: agentUsername
        in: query
        required: false
        schema:
          type: string
        example: RCS_AGENT_USERNAME
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/sender/{RCS_SENDER_ID}:
    patch:
      tags:
      - RCS
      summary: Manage Sender (All-in-One)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Manage test numbers & launch countries on a live sender

        Adds and/or removes **test numbers**, and adds **launch countries**, in one call.

        ### Test numbers — full add + remove (dedicated the RCS provider endpoints)

        Test numbers are managed through the RCS provider's dedicated provisioning endpoints, so **both add and remove work**:

        - **add** → `POST /v1/projects/{p}/rcs/senders/{id}/testNumbers` — each number receives an RBM tester invite. Re-adding an already-verified number resets it to _unverified_ and re-sends the invite. the RCS provider limit: **20 invites/day, 200 total**.

        - **remove** → `DELETE /v1/projects/{p}/rcs/senders/{id}/testNumbers/{number}` (the `{number}` is the literal E.164 with `+`).


        ### Countries — add only via API

        Countries use the sender `PATCH`, which is **additive**: **adding** a country works, but **removing** one is **not** supported by the provisioning API — remove it in the the RCS provider dashboard. The response carries a `note` when a country removal can't be applied.

        ### Fields

        - `addTestNumbers` / `removeTestNumbers`: E.164 numbers, e.g. `+447700900119` (bare digits are auto-prefixed with `+`).

        - `addCountries` / `removeCountries`: ISO codes, e.g. `US`. Supply at least one of the four arrays.

        - Brand & questionnaire details are preserved.


        ### Response

        Always returns the **canonical** state re-fetched from the RCS provider: `testNumbers`, `testNumberStates`, `countryStatus`, an `appliedOnSinch` flag, and a `testNumberChanges` block (`added`, `addedStates`, `removed`, and any per-number `removeErrors`). A `note` appears if a country removal was requested.

        _Requires the redeployed RcsClient (dedicated test-number endpoints). The_ `_username_` _header is injected by the gateway from the JWT._
      operationId: patch_rcs_agent_sender_RCS_SENDER_ID
      parameters:
      - name: RCS_SENDER_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_SENDER_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                addTestNumbers:
                  type: array
                  items:
                    type: string
                removeTestNumbers:
                  type: array
                  items: {}
                addCountries:
                  type: array
                  items: {}
                removeCountries:
                  type: array
                  items: {}
            examples:
              Manage Sender (All-in-One):
                value:
                  addTestNumbers:
                  - '+447700900119'
                  removeTestNumbers: []
                  addCountries: []
                  removeCountries: []
              Add Sender Test Number:
                value:
                  addTestNumbers:
                  - '+447700900119'
              Remove Sender Test Number:
                value:
                  removeTestNumbers:
                  - '+447700900119'
              Add Sender Country:
                value:
                  addCountries:
                  - GB
              Remove Sender Country:
                value:
                  removeCountries:
                  - GB
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    get:
      tags:
      - RCS
      summary: Get Sender By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Step 6 — Check live status / test-number verification

        Reads the sender straight from the RCS provider. Use the returned **`state`** (`IN_TEST` → `LAUNCHING` → `LAUNCHED` = live / `REJECTED`) and **`testNumberStates[]`** to see verification.

        - Header `username` = operator; optional `agentUsername` = target tenant (defaults to operator).


        ---

        🔒 **Required role:** ANY (super/admin/tenant)
        **Caller header (****`username`****):** `{{RCS_AGENT_USERNAME}}`
      operationId: get_rcs_agent_sender_RCS_SENDER_ID
      parameters:
      - name: RCS_SENDER_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_SENDER_ID
      - name: agentUsername
        in: query
        required: false
        schema:
          type: string
        example: RCS_AGENT_USERNAME
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/senders:
    get:
      tags:
      - RCS
      summary: '[operator] Get All Senders'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        List all RCS senders on the tenant's the RCS provider project. Header `username` = operator; optional `agentUsername` = target tenant.

        ---
        🔒 **Required role:** SUPER/ADMIN
        **Caller header (`username`):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: get_rcs_agent_senders
      parameters:
      - name: agentUsername
        in: query
        required: false
        schema:
          type: string
        example: RCS_AGENT_USERNAME
      - name: pageSize
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: filterStates
        in: query
        required: false
        schema:
          type: string
        example: PREPARING_LAUNCH
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/sender/{RCS_SENDER_ID}/questionnaires:
    get:
      tags:
      - RCS
      summary: '[operator] Get Sender Questionnaires'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        Country-specific questionnaires already attached to the sender. Header `username` = operator; optional `agentUsername` = target tenant.

        ---
        🔒 **Required role:** SUPER/ADMIN
        **Caller header (`username`):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: get_rcs_agent_sender_RCS_SENDER_ID_questionnaires
      parameters:
      - name: RCS_SENDER_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_SENDER_ID
      - name: agentUsername
        in: query
        required: false
        schema:
          type: string
        example: RCS_AGENT_USERNAME
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/questionnaire:
    get:
      tags:
      - RCS
      summary: '[operator] Get Questionnaire'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        Fetch the provisioning questionnaire definition for a use case + countries (use to build the agent questionnaire).

        ---
        🔒 **Required role:** SUPER/ADMIN
        **Caller header (`username`):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: get_rcs_agent_questionnaire
      parameters:
      - name: agentUsername
        in: query
        required: false
        schema:
          type: string
        example: RCS_AGENT_USERNAME
      - name: useCase
        in: query
        required: false
        schema:
          type: string
        example: MULTIUSE
      - name: countries
        in: query
        required: false
        schema:
          type: string
        example: US
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/update:
    put:
      tags:
      - RCS
      summary: Update Onboarded Agent
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Description

        This API is used to **update configuration details of an existing onboarded RCS agent** in the system.

        It allows modification of billing settings, rate limits, processing mode, and traffic handling parameters without recreating the agent.

        This is mainly used for:

        -
            Adjusting pricing/tier configuration

        -
            Updating message processing behavior

        -
            Changing rate limits for traffic control

        -
            Modifying billing rules for an existing agent


        Only **authorized system users (SUPERADMIN / SYSTEM roles)** are allowed to perform updates.

        ---

        ## Authorization Rules

        | Role | Access |
        | --- | --- |
        | SUPERADMIN | Allowed |
        | SYSTEM | Allowed |
        | NORMAL USER | Not allowed |

        ---

        ## Endpoint

        ```
        PUT https://api.broadnet.me/rcs/agent/update

         ```

        ---

        ## Request Fields

        | Field | Type | Required | Description |
        | --- | --- | --- | --- |
        | username | String | Yes | Tenant username whose agent is being updated |
        | tierId | Integer | Yes | Pricing tier assigned to the agent |
        | passthroughFeeEnabled | Boolean | Yes | Enables/disables passthrough fee charging |
        | applyToIncoming | Boolean | Yes | Determines whether incoming messages are billed |
        | billingCategory | String | Yes | Billing category type (e.g. BASIC, NON_CONVERSATIONAL) |
        | processingMode | String | Yes | Message processing mode (e.g. DISPATCH) |
        | rateLimit | Integer | Yes | Maximum allowed message throughput limit |

        ---

        ## Headers

        | Header | Type | Required | Description |
        | --- | --- | --- | --- |
        | username | String | Yes | Authenticated system username performing update |
        | ipAddress | String | Yes | Client IP address for audit logging |
        | accept | String | Yes | Response format (application/json) |
        | Authorization | String | Yes | Bearer JWT token for authentication |

        ---
        🔒 **Required role:** SUPER/ADMIN
        **Caller header (`username`):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: put_rcs_agent_update
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                tierId:
                  type: integer
                passthroughFeeEnabled:
                  type: boolean
                applyToIncoming:
                  type: boolean
                billingCategory:
                  type: string
                processingMode:
                  type: string
                rateLimit:
                  type: integer
            examples:
              Update Onboarded Agent:
                value:
                  username: acme
                  tierId: 1
                  passthroughFeeEnabled: true
                  applyToIncoming: false
                  billingCategory: BASIC
                  processingMode: DISPATCH
                  rateLimit: 60
      responses:
        '200':
          description: OK
  /rcs/agent/list:
    post:
      tags:
      - RCS
      summary: Get All Onboarded Agents
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        List onboarded agents (paged/filtered). NOTE: this endpoint is now **POST** with a body (was GET).

        ---

        🔒 **Required role:** SUPER/ADMIN
        **Caller header (****`username`****):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: post_rcs_agent_list
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                page:
                  type: integer
                size:
                  type: integer
                search:
                  type: string
                status:
                  type: string
                region:
                  type: string
                fromDate:
                  type: string
                toDate:
                  type: string
                toGmt:
                  type: string
            examples:
              Get All Onboarded Agents:
                value:
                  page: 0
                  size: 10
                  search: ''
                  status: ''
                  region: ''
                  fromDate: '2025-05-01 00:00:00'
                  toDate: '2027-05-31 23:59:59'
                  toGmt: GMT+05:30
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/refresh:
    post:
      tags:
      - RCS
      summary: '[operator] Refresh Onboarded Agents'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ## Description

        This API is used to **refresh the in-memory cache of RCS agents/tenants in the system**.

        It reloads all onboarded agent data from the database into the application’s runtime cache (`GlobalVars` or equivalent storage).

        This ensures that any newly added, updated, or deleted agents are immediately reflected in the system without restarting the service.

        ---

        ## Authorization Rules

        | Role | Access |
        | --- | --- |
        | SUPERADMIN | Allowed |
        | SYSTEM | Allowed |
        | NORMAL USER | Not allowed |

        Only privileged system roles can trigger cache refresh.

        ---

        ## Endpoint

        ```
        POST https://api.broadnet.me/rcs/agent/refresh

         ```

        ---

        ## Request

        This API does **not require any request body or query parameters**

        ---

        ## Headers

        | Header | Type | Required | Description |
        | --- | --- | --- | --- |
        | Authorization | String | Yes | Bearer JWT token for authentication |

        ---
        🔒 **Required role:** SUPER/ADMIN
        **Caller header (`username`):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: post_rcs_agent_refresh
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/me:
    get:
      tags:
      - RCS
      summary: Get My Agent
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        Fetch the onboarded RCS agent for the authenticated `username` (header).

        ---

        🔒 **Required role:** ANY (super/admin/tenant)
        **Caller header (****`username`****):** `{{RCS_AGENT_USERNAME}}`
      operationId: get_rcs_agent_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/{USERNAME}:
    delete:
      tags:
      - RCS
      summary: Delete Agent By Username
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN`— tenant token.

        ## Description

        This API is used to **delete an onboarded RCS agent from the system** based on the provided username (tenant).

        Once deleted, the agent configuration is removed from the database and will no longer be available for messaging, billing, or provisioning operations.

        This operation is **destructive and irreversible**, so it should be used with caution.

        ---

        ## Authorization Rules

        | Role | Access |
        | --- | --- |
        | SUPERADMIN | Allowed |
        | SYSTEM | Allowed |
        | NORMAL USER | Not allowed |

        ---

        ## Endpoint

        ```
        DELETE https://api.broadnet.me/rcs/agent/{username}

         ```

        ---

        ## Request Parameters

        | Field | Type | Required | Description |
        | --- | --- | --- | --- |
        | username | String (Path Param) | Yes | Tenant username whose agent configuration will be deleted |

        ---

        ## Headers

        | Header | Type | Required | Description |
        | --- | --- | --- | --- |
        | Authorization | String | Yes | Bearer JWT token for authentication |

        ---

        🔒 **Required role:** SUPER/ADMIN
        **Caller header (****`username`****):** `{{RCS_OPERATOR_USERNAME}}`
      operationId: delete_rcs_agent_USERNAME
      parameters:
      - name: USERNAME
        in: path
        required: true
        schema:
          type: string
        example: USERNAME
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/agent/{RCS_ID}:
    get:
      tags:
      - RCS
      summary: '[operator] Get Onboarded Agent By Id'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get onboarded RCS agent by ID

        Operator-only: fetch a single onboarded RCS agent by its primary key.

        **Endpoint** `GET /rcs/agent/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_rcs_agent_RCS_ID
      parameters:
      - name: RCS_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/capability/query:
    post:
      tags:
      - RCS
      summary: Query Recipient Capability
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Description

        This API is used to check whether a mobile number supports **RCS messaging capabilities**.

        The system submits a capability lookup request to the RCS platform and returns a request ID for tracking.

        It helps determine:

        -
            Whether the recipient device is RCS enabled

        -
            Whether the carrier supports RCS

        -
            Whether advanced messaging features are available


        ---

        ## Headers

        | Header | Type | Required | Description |
        | --- | --- | --- | --- |
        | Authorization | Bearer Token | true | Valid authentication token |
        | Content-Type | String | true | Must be `application/json` |

        ---

        ## Request Body

        | Field | Type | Required | Description |
        | --- | --- | --- | --- |
        | username | String | true | Tenant or onboarded RCS account username |
        | recipient | String | true | Mobile number to check RCS capability for (country code without `+`) |

        ---

        ### Validation rules

        - **`recipient`** query param must be **E.164**: regex `^\+[1-9]\d{6,14}$` (leading `+`, no spaces). Example valid: `+447700900114`.
      operationId: post_rcs_capability_query
      parameters:
      - name: recipient
        in: query
        required: false
        schema:
          type: string
        example: RCS_RECIPIENT
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
            examples:
              Query Recipient Capability:
                value: ''
      responses:
        '200':
          description: OK
  /rcs/contact/create:
    post:
      tags:
      - RCS
      summary: Create Contact
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Description

        This API is used to create a new RCS contact in the system.

        The contact can later be used for sending RCS messages.

        ---

        ---

        # Request Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | username | String | User account name |
        | phoneNumber | String | Mobile number of the contact |
        | displayName | String | Name to display for the contact |

        ---

        ---

        # Response Details

        | Field | Description |
        | --- | --- |
        | success | API request status |
        | message | Response message |
        | data.id | Unique contact ID |
        | channel | Communication channel type |
        | identity | Registered mobile number |
        | display_name | Contact display name |
        | timestamp | Response timestamp |

        ---

        # Usage

        Use this API before sending RCS messages to register a contact in the system.

        ---

        ### Validation rules

        - **`phoneNumber`** must be **E.164**: regex `^\+[1-9]\d{6,14}$` (leading `+`, no spaces). Example valid: `+447700900114`.
      operationId: post_rcs_contact_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                phoneNumber:
                  type: string
                displayName:
                  type: string
            examples:
              Create Contact:
                value:
                  username: demo-tenant
                  phoneNumber: '+447700900120'
                  displayName: RcsClient Postman Contact 1
      responses:
        '200':
          description: OK
  /rcs/contact/list:
    get:
      tags:
      - RCS
      summary: Get All Contacts
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to retrieve all RCS contacts associated with a specific user account.

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | username | String | User account name |
      operationId: get_rcs_contact_list
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDir
        in: query
        required: false
        schema:
          type: string
        example: desc
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: channelIdentity
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /rcs/contact/{RCS_CONTACT_ID}:
    get:
      tags:
      - RCS
      summary: Get Contact By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to fetch details of a specific RCS contact using the contact ID.

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | contactId | String | Unique contact ID |
        | username | String | User account name |
      operationId: get_rcs_contact_RCS_CONTACT_ID
      parameters:
      - name: RCS_CONTACT_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_CONTACT_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - RCS
      summary: Delete Contact By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to permanently delete an existing RCS contact from the system.

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | contactId | String | Unique contact ID |
        | username | String | User account name |
      operationId: delete_rcs_contact_RCS_CONTACT_ID
      parameters:
      - name: RCS_CONTACT_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_CONTACT_ID
      responses:
        '200':
          description: OK
  /rcs/message/test:
    post:
      tags:
      - RCS
      summary: Send Test Message (Live Smoke Test)
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        Direct single RCS text send. Works once the agent has an appId; while IN_TEST only delivers to test numbers.

        ---

      operationId: post_rcs_message_test
      parameters:
      - name: to
        in: query
        required: false
        schema:
          type: string
        example: RCS_RECIPIENT
      - name: text
        in: query
        required: false
        schema:
          type: string
        example: Hello from BroadNet
      responses:
        '200':
          description: OK
  /rcs/message/typing:
    post:
      tags:
      - RCS
      summary: Send Typing Indicator
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        🔒 **Required role:** isAuthorizedAll (tenant/admin/super)
        **Caller header (`username`):** the agent username

        Shows the recipient that the agent is composing a message — the RCS provider `events:send` with `composing_event`. Recipient must be E.164. Returns `{message, eventId, to, appId}`. The composing_event shape is the RCS provider-stable.
      operationId: post_rcs_message_typing
      parameters:
      - name: to
        in: query
        required: false
        schema:
          type: string
        example: '%2B40723333141'
      responses:
        '200':
          description: OK
  /rcs/message/sendbulk:
    post:
      tags:
      - RCS
      summary: Plain Schedule Text
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        REQUEST
        -------
        Sends a simple plain-text RCS message to a single recipient.
        This is the most basic message type — no media, no buttons, just text.

        Endpoint  : POST {{BASE_URL}}/message/sendbulk
        Auth      : Bearer Token (Authorization header)
        Body      : multipart/form-data

        Use Cases : OTP delivery, order notifications, account alerts, reminders.

        Limits    : Maximum 3072 characters per message.
                    0–160 chars  → Basic SMS-equivalent billing.
                    161+ chars   → Single RCS message billing.

        PARAMETERS
        ======================================================================
        Parameter              Type       Required   Description
        ----------------------------------------------------------------------
        messageType            String     Yes        Fixed value: "TEXT"
        destinationNo          String     Yes        Recipient mobile number with country code, no + sign. E.g. 447700900111
        content                String     Yes        Plain text body of the message. Max 3072 characters.
        ======================================================================

        ---


        ---

        ### Validation rules

        Bulk submissions are now validated upfront at the service boundary before any the RCS provider call — invalid requests are rejected with `400` instead of silently dropping per-destination at the RCS provider.

        **`messageType`** — must be exactly one of:
        `TEXT`, `MEDIA`, `CARD`, `CAROUSEL`, `CHOICE`, `LOCATION`, `TEMPLATE`

        **Per-type rules:**

        - **TEXT** — `content` required, **≤ 3072 chars** (the RCS provider limit)
        - **MEDIA** — `mediaUrl` required, must be **HTTPS**
        - **CARD** / **CAROUSEL** — `cardsJson` required + valid JSON; each card's `title` ≤ 200 chars, `description` ≤ 2000 chars, `mediaUrl` HTTPS; **CAROUSEL must have 2–10 cards**; each card's `choices` ≤ 10
        - **CHOICE** — `choicesJson` required + valid JSON; ≤ 10 choices; each must have a non-blank `text`
        - **LOCATION** — `latitude` ∈ [-90, 90], `longitude` ∈ [-180, 180]
        - **TEMPLATE** — `templateId` required, must be **ULID format** (26 chars, `[0-9A-HJKMNP-TV-Z]`)

        **`destinations`** — each MUST be **E.164 with leading `+`** (e.g. `+447700900114`). Numbers without `+` are now rejected at the service boundary (no more silent per-destination drop at the RCS provider).
      operationId: post_rcs_message_sendbulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                messageType:
                  type: string
                destinationNo:
                  type: string
                content:
                  type: string
                delay:
                  type: string
                scheduled:
                  type: string
                gmt:
                  type: string
                recurrence:
                  type: string
                scheduleTime:
                  type: string
                repeatCount:
                  type: string
            examples:
              Plain Schedule Text:
                value:
                  messageType: TEXT
                  destinationNo: '+447700900120'
                  content: Hello from BroadNet RCS! This is a plain text message.
                  delay: '0'
                  scheduled: 'true'
                  gmt: +05:30
                  recurrence: NONE
                  scheduleTime: '2026-09-15 16:48:00.000'
                  repeatCount: '0'
              Text Long Content (160+ chars):
                value:
                  messageType: TEXT
                  destinationNo: '+447700900120'
                  content: This is a long RCS text message exceeding 160 characters. With RCS you can send detailed information,
                    promotional content, order updates, policy notices, or any long-form notification — all in a single message
                    without splitting. Maximum limit is 3072 characters.
                  delay: '0'
                  scheduled: 'true'
                  gmt: +05:30
                  recurrence: NONE
                  scheduleTime: '2026-05-23 16:20:00.000'
                  repeatCount: '0'
              Text Multiple Destinations (Bulk):
                value:
                  messageType: TEXT
                  destinationNo: '+447700900120'
                  content: Bulk RCS message — sent to multiple recipients simultaneously.
                  delay: '0'
                  scheduled: 'true'
                  gmt: +05:30
                  recurrence: NONE
                  scheduleTime: '2026-05-23 16:20:00.000'
                  repeatCount: '0'
              Text  Unicode + Emoji:
                value:
                  messageType: TEXT
                  destinationNo: '+447700900120'
                  content: '🎉 Warm festive greetings from BroadNet! 🪔 Wishing you and your family joy, prosperity, and happiness
                    this season. Special offer: 40% OFF on all plans today only. Use code: FEST2025 🎊'
                  delay: '0'
                  scheduled: 'true'
                  gmt: +05:30
                  recurrence: NONE
                  scheduleTime: '2027-05-23 16:20:00.000'
                  repeatCount: '0'
              Image JPEG / PNG:
                value:
                  messageType: MEDIA
                  destinationNo: '+447700900120'
                  'mediaUrl ': https://example.com/
                  repeatCount: '0'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  recurrence: NONE
                  gmt: +05:30
                  scheduled: 'true'
                  delay: '0'
              Image With Caption:
                value:
                  messageType: MEDIA
                  destinationNo: '+447700900120'
                  'mediaUrl ': https://example.com/
                  caption: Check out our featured product — order now and get 20% off!
                  repeatCount: '0'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  recurrence: NONE
                  gmt: +05:30
                  scheduled: 'true'
                  delay: '0'
              Video MP4:
                value:
                  messageType: MEDIA
                  destinationNo: '+447700900120'
                  'mediaUrl ': https://cdn.example.com/media/mov_bbb.mp4
                  repeatCount: '0'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  recurrence: NONE
                  gmt: +05:30
                  scheduled: 'true'
                  delay: '0'
              Video  With Caption:
                value:
                  messageType: MEDIA
                  destinationNo: '+447700900120'
                  mediaUrl: https://cdn.example.com/media/mov_bbb.mp4
                  caption: Watch our latest product demo — available now at 30% off!
                  delay: '0'
                  scheduled: 'true'
                  gmt: +05:30
                  recurrence: NONE
                  scheduleTime: '2026-10-23 16:20:00.000'
                  repeatCount: '0'
              Audio MP3:
                value:
                  messageType: MEDIA
                  destinationNo: 447700900121,447700900108
                  'mediaUrl ': https://cdn.example.com/media/SoundHelix-Song-1.mp3
                  delay: '0'
                  scheduled: 'true'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: +05:30
              Document PDF:
                value:
                  messageType: MEDIA
                  destinationNo: '+447700900120'
                  mediaUrl: https://cdn.example.com/media/file-sample_150kB.pdf
                  delay: '0'
                  scheduled: 'true'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: +05:30
              Document  PDF with Custom Filename:
                value:
                  messageType: MEDIA
                  destinationNo: 447700900121,447700900108
                  mediaUrl: https://www.w3.org/WAI/WCAG21/wcag21.pdf
                  fileName: BroadNet_Invoice.pdf
                  gmt: +05:30
                  scheduled: 'true'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  repeatCount: '0'
                  recurrence: NONE
                  delay: '0'
              Rich Card Image + Title (No Buttons):
                value:
                  messageType: CARD
                  destinationNo: '+447700900120'
                  cardsJson: '{"title":"Special Announcement!","description":"Our new service is now live.","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"TALL"}'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Rich Card Image + Title + URL Button:
                value:
                  messageType: CARD
                  destinationNo: '+447700900120'
                  cardsJson: '{"title":"Shop Now!","description":"Visit our website for exclusive offers.","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"TALL","choices":[{"text":"Visit
                    Website","url":"https://www.broadnet.me","postbackData":"VISIT_WEB"}]}'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Rich Card Image + Title + Call Button:
                value:
                  messageType: CARD
                  destinationNo: '+447700900120'
                  cardsJson: '{"title":"Need Help?","description":"Call us directly.","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Call
                    Support","phoneNumber":"+447700900121","postbackData":"CALL_SUPPORT"}]}'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Rich Card Image + 2 Buttons (URL + Quick Reply):
                value:
                  messageType: CARD
                  destinationNo: '+447700900120'
                  cardsJson: '{"title":"New Product Launch!","description":"Pre-order now or remind me later.","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"TALL","choices":[{"text":"Shop
                    Now","url":"https://www.broadnet.me","postbackData":"SHOP_NOW"},{"text":"Remind Me Later","postbackData":"REMIND_LATER"}]}'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Rich Card Image + 3 Buttons (URL + Call + Reply):
                value:
                  messageType: CARD
                  destinationNo: '+447700900120'
                  cardsJson: '{"title":"Contact Us!","description":"Reach us your way.","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Visit
                    Website","url":"https://www.broadnet.me","postbackData":"VISIT_WEB"},{"text":"Call Us","phoneNumber":"+447700900121","postbackData":"CALL_US"},{"text":"Not
                    Interested","postbackData":"OPT_OUT"}]}'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Quick Reply 2 Options (Yes / No):
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: Would you like to continue your subscription?
                  choicesJson: '[{"text":"Yes, Continue","postbackData":"YES"},{"text":"No, Cancel","postbackData":"NO"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Quick Reply 3 Options (Rating):
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: How was your experience with our service?
                  choicesJson: '[{"text":"Excellent","postbackData":"EXCELLENT"},{"text":"Good","postbackData":"GOOD"},{"text":"Poor","postbackData":"POOR"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              View Location (Static Map Pin):
                value:
                  messageType: LOCATION
                  destinationNo: '+447700900120'
                  latitude: '23.1815'
                  longitude: '79.9864'
                  locationName: Head office
                  locationAddress: Dubai Internet City, Dubai
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Location Share Request:
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: 'Share your location:'
                  choicesJson: '[{"text":"Share Location","latitude":"23.1815","longitude":"79.9864","postbackData":"SHARE_LOC"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Carousel  2 Cards (Minimum):
                value:
                  messageType: CAROUSEL
                  destinationNo: '+447700900120'
                  cardsJson: '[{"title":"Product A","description":"Best seller - Rs 499","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Buy
                    Now","url":"https://www.broadnet.me","postbackData":"BUY_A"}]},{"title":"Product B","description":"New
                    arrival - Rs 799","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Buy
                    Now","url":"https://www.broadnet.me","postbackData":"BUY_B"}]}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Carousel 3 Cards (Product Catalog):
                value:
                  messageType: CAROUSEL
                  destinationNo: '+447700900120'
                  cardsJson: '[{"title":"Product A","description":"Best seller - Rs 499","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Buy
                    Now","url":"https://www.broadnet.me","postbackData":"BUY_A"}]},{"title":"Product B","description":"New
                    arrival - Rs 799","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Buy
                    Now","url":"https://www.broadnet.me","postbackData":"BUY_B"}]},{"title":"Product C","description":"Limited
                    edition - Rs 1299","mediaUrl":"https://cdn.example.com/media/Camponotus_flavomarginatus_ant.jpg","height":"MEDIUM","choices":[{"text":"Buy
                    Now","url":"https://www.broadnet.me","postbackData":"BUY_C"}]}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Calender Event Add to Calendar:
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: Save our upcoming sale event to your calendar!
                  choicesJson: '[{"text":"Add to Calendar","url":"https://example.com/","postbackData":"ADD_CALENDAR"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Url Action Open Link Button:
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: 'Visit our website for exclusive offers:'
                  choicesJson: '[{"text":"Open Website","url":"https://www.broadnet.me","postbackData":"OPEN_LINK"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Combined Call Button + URL Button:
                value:
                  messageType: CHOICE
                  destinationNo: '+447700900120'
                  content: 'Contact us your preferred way:'
                  choicesJson: '[{"text":"Call Us","phoneNumber":"+447700900121","postbackData":"CALL_US"},{"text":"Visit
                    Website","url":"https://www.broadnet.me","postbackData":"OPEN_LINK"}]'
                  delay: '0'
                  scheduled: 'false'
                  scheduleTime: ''
                  recurrence: NONE
                  repeatCount: '0'
                  gmt: ''
              Send Template With Placeholders:
                value:
                  messageType: TEMPLATE
                  templateId: RCS_TEMPLATE_ID
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex","otp":"123456"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: template_placeholder_test
              Send Template Text:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex","otp":"123456"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_text
              Send Template Media:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_media
              Send Template Card:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex","otp":"123456"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_card
              Send Template Carousel:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex","otp":"123456"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_carousel
              Send Template Choice:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_choice
              Send Template Location:
                value:
                  messageType: TEMPLATE
                  templateId: 01ARZ3NDEKTSV4RRFFQ69G5FAV
                  templateVersion: '1'
                  templateLanguage: en
                  parametersJson: '{"name":"Alex"}'
                  destinationNo: RCS_RECIPIENT
                  recipientType: PHONE
                  campaignName: send_location
              Send Bulk — Inline TEXT:
                value:
                  batchId: '0'
                  destinationNo: '+447700900120'
                  campaignName: SCHEDULED_RCS_TEST
                  allowDuplicate: 'false'
                  messageType: TEXT
                  recipientType: PHONE
                  content: Hello from scheduled RCS campaign
                  delay: '10'
                  scheduled: 'true'
                  scheduleTime: '2026-05-23 16:20:00.000'
                  gmt: +05:30
                  recurrence: NONE
                  repeatCount: '0'
              Send Bulk — File Upload + MEDIA:
                value:
                  destinationFiles: gLYn6uGSh/+447700900120.txt
                  messageType: MEDIA
                  recipientType: PHONE
                  mediaUrl: https://cdn.example.com/media/1.jpg
                  campaignName: POSTMAN_BULK_MEDIA
                  allowDuplicate: 'false'
                  delay: '0'
                  scheduled: 'false'
              Send Bulk — Scheduled CARD:
                value:
                  destinationNo: RCS_RECIPIENT
                  messageType: CARD
                  cardsJson: '{"title":"Scheduled card","description":"Sent later","mediaUrl":"RCS_IMAGE_URL"}'
                  campaignName: POSTMAN_BULK_SCHEDULED
                  scheduled: 'true'
                  scheduleTime: '2026-12-31 23:30:00.000'
                  gmt: +05:30
                  recurrence: DAILY
                  repeatCount: '7'
      responses:
        '200':
          description: OK
  /rcs/template/create:
    post:
      tags:
      - RCS
      summary: Create Text Template
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This template is used to send simple text-based RCS messages with dynamic variables.

        ### Request Fields

        | Field | Type | Description |
        | --- | --- | --- |
        | username | String | User account name |
        | template.description | String | Template name/description |
        | template.default_translation | String | Default language code |
        | translations.language_code | String | Template language |
        | text_message.text | String | Text message content |
        | ${NAME} | Variable | Dynamic parameter replaced during send |

        ---

        ### Validation rules

        - **`template.translations`** must be a **non-empty array**
        - Each translation must have a **non-blank `languageCode`** and a **non-null `message`** (the channel-typed payload object, e.g. `text_message`, `media_message`, etc.)
        - If **`defaultTranslation`** (a.k.a. `default_translation`) is set, it MUST match one of the `languageCode` values present in `translations` — mismatches are rejected with `400` before reaching the RCS provider.
      operationId: post_rcs_template_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                template:
                  type: object
                  properties:
                    description:
                      type: string
                    default_translation:
                      type: string
                    translations:
                      type: array
                      items:
                        type: object
                        properties:
                          language_code:
                            type: string
                          text_message:
                            type: object
                            properties:
                              text:
                                type: string
                templateName:
                  type: string
                category:
                  type: string
                language:
                  type: string
                description:
                  type: string
            examples:
              Create Text Template:
                value:
                  template:
                    description: TEXT template test
                    default_translation: en
                    translations:
                    - language_code: en
                      text_message:
                        text: Hi ${name}, your OTP is ${otp}. Thanks for choosing BroadNet RCS!
                  templateName: test_type_text
                  category: MARKETING
                  language: en
                  description: TEXT placeholder test
              Create Quick Reply Template:
                value:
                  template:
                    description: CHOICE template test
                    default_translation: en
                    translations:
                    - language_code: en
                      choice_message:
                        text_message:
                          text: Hi ${name}, how can we help you today?
                        choices:
                        - text_message:
                            text: Get started
                          postback_data: GET_STARTED
                        - url_message:
                            title: Visit website
                            url: https://www.broadnet.me
                        - call_message:
                            title: Call us
                            phone_number: '+447700900122'
                  templateName: test_type_choice
                  category: MARKETING
                  language: en
                  description: CHOICE placeholder test
              Create Carousel Template:
                value:
                  template:
                    description: CAROUSEL template test
                    default_translation: en
                    translations:
                    - language_code: en
                      carousel_message:
                        cards:
                        - title: 'Hi ${name}, deal #1'
                          description: Your code is ${otp}. Tap to explore our first offer.
                          media_message:
                            url: https://cdn.example.com/media/1.jpg
                          height: MEDIUM
                          choices:
                          - text_message:
                              text: View deal 1
                            postback_data: card1_view
                          - url_message:
                              title: Open site
                              url: https://www.broadnet.me
                        - title: 'And ${name}, deal #2'
                          description: A second great offer just for you.
                          media_message:
                            url: https://cdn.example.com/media/2.jpg
                          height: MEDIUM
                          choices:
                          - text_message:
                              text: View deal 2
                            postback_data: card2_view
                        choices:
                        - text_message:
                            text: See all deals
                          postback_data: carousel_see_all
                  templateName: test_type_carousel
                  category: MARKETING
                  language: en
                  description: CAROUSEL placeholder test
              Create Image Template:
                value:
                  template:
                    description: MEDIA template test
                    default_translation: en
                    translations:
                    - language_code: en
                      media_message:
                        url: https://www.broadnet.me/assets/sample-image.jpg
                        thumbnail_url: https://www.broadnet.me/assets/sample-thumb.jpg
                  templateName: test_type_media
                  category: MARKETING
                  language: en
                  description: MEDIA placeholder test
              Create Video Template:
                value:
                  template:
                    description: VIDEO template test
                    default_translation: en
                    translations:
                    - language_code: en
                      media_message:
                        url: https://cdn.example.com/media/mov_bbb.mp4
                        thumbnail_url: https://cdn.example.com/media/1.jpg
                  templateName: test_type_video
                  category: MARKETING
                  language: en
                  description: VIDEO media template
              Create Order Confirmation Template:
                value:
                  username: '{{USERNAME}}'
                  template:
                    description: Order Confirmation Template
                    default_translation: en-US
                    translations:
                    - language_code: en-US
                      text_message:
                        text: Hello ${NAME}, your order ${ORDER_ID} worth Rs.${AMOUNT} has been confirmed.
              Create Button Template:
                value:
                  template:
                    description: CARD template test
                    default_translation: en
                    translations:
                    - language_code: en
                      card_message:
                        title: Hi ${name}, your order is confirmed
                        description: Use code ${otp} to track your delivery. Tap below for options.
                        media_message:
                          url: https://cdn.example.com/media/1.jpg
                        height: MEDIUM
                        choices:
                        - text_message:
                            text: Track order
                          postback_data: TRACK_ORDER
                        - url_message:
                            title: Open website
                            url: https://www.broadnet.me
                        - call_message:
                            title: Call support
                            phone_number: '+447700900123'
                  templateName: test_type_card
                  category: MARKETING
                  language: en
                  description: CARD placeholder test
              Create Location Template:
                value:
                  template:
                    description: LOCATION template test
                    default_translation: en
                    translations:
                    - language_code: en
                      location_message:
                        title: Hello ${name}, here is our store
                        label: BroadNet HQ
                        coordinates:
                          latitude: 25.276987
                          longitude: 55.296249
                  templateName: test_type_location
                  category: MARKETING
                  language: en
                  description: LOCATION placeholder test
      responses:
        '200':
          description: OK
  /rcs/template/{RCS_TEMPLATE_ID}:
    put:
      tags:
      - RCS
      summary: Update Template
      description: |
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to update an existing RCS template including message text, translations, media, buttons, or other template content.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | templateId | String | Unique template ID |
        | username | String | User account name |
        | template.description | String | Updated template description |
        | template.default_translation | String | Default template language |
        | template.translations | Array | List of template translations |

        ---

        ### Validation rules

        - **`template.translations`** must be a **non-empty array**
        - Each translation must have a **non-blank `languageCode`** and a **non-null `message`** (the channel-typed payload object, e.g. `text_message`, `media_message`, etc.)
        - If **`defaultTranslation`** (a.k.a. `default_translation`) is set, it MUST match one of the `languageCode` values present in `translations` — mismatches are rejected with `400` before reaching the RCS provider.
      operationId: put_rcs_template_RCS_TEMPLATE_ID
      parameters:
      - name: RCS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_TEMPLATE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                template:
                  type: object
                  properties:
                    description:
                      type: string
                    default_translation:
                      type: string
                    translations:
                      type: array
                      items:
                        type: object
                        properties:
                          language_code:
                            type: string
                          text_message:
                            type: object
                            properties:
                              text:
                                type: string
            examples:
              Update Template:
                value:
                  username: '{{USERNAME}}'
                  template:
                    description: RcsClient Postman live template - Updated
                    default_translation: en-US
                    translations:
                    - language_code: en-US
                      text_message:
                        text: Hello ${NAME}, your template has been updated successfully.
      responses:
        '200':
          description: OK
    get:
      tags:
      - RCS
      summary: Get Template By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to fetch details of a specific RCS template using the template ID.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | templateId | String | Unique template ID |
        | username | String | User account name |
      operationId: get_rcs_template_RCS_TEMPLATE_ID
      parameters:
      - name: RCS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_TEMPLATE_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - RCS
      summary: Delete Template By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Description

        This API is used to permanently delete an RCS template from the system.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | templateId | String | Unique template ID |
        | username | String | User account name |
      operationId: delete_rcs_template_RCS_TEMPLATE_ID
      parameters:
      - name: RCS_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: RCS_TEMPLATE_ID
      responses:
        '200':
          description: OK
  /rcs/template/name:
    get:
      tags:
      - RCS
      summary: Get Template By Name
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        Fetch a template by its **name** (not ID). Template names aren't unique per user — each create mints a new the RCS provider `templateId` — so this returns the **most recently created** match. Previously this returned `500` (`NonUniqueResultException`) when 2+ templates shared a name; fixed 2026-06-02 to return the latest (`findFirstBy…OrderByCreatedAtDesc`). `username` is injected by the gateway from the JWT; `name` is the query param.
      operationId: get_rcs_template_name
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: RCS_TEMPLATE_NAME
      responses:
        '200':
          description: OK
  /rcs/template/grouped:
    get:
      tags:
      - RCS
      summary: Get Templates Grouped By Category
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        List the tenant's templates **grouped by category** — returns `{ "<CATEGORY>": [ { templateId, templateName, messageText, mediaUrl }, ... ] }`. Templates with no category fall under `GENERAL`. `username` and `ipAddress` are headers; the gateway injects `username` from the JWT.
      operationId: get_rcs_template_grouped
      responses:
        '200':
          description: OK
  /rcs/template/list:
    post:
      tags:
      - RCS
      summary: Get All Templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        List omnichannel templates with pagination, searching and filtering. Date fields use 'yyyy-MM-dd HH:mm:ss' format (space separator, no T, no Z). Do NOT send ISO-8601 with trailing 'Z' (e.g. '2026-05-25T18:30:00.000Z') — backend uses LocalDateTime + this @JsonFormat pattern and the request will 400.
      operationId: post_rcs_template_list
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              Get All Templates:
                value: |-
                  {
                    "page": 0,
                    "size": 10,
                    "search": "",
                  //   "language": "en-US",
                    "sortBy": "createdAt",
                    "sortDir": "desc",
                    "fromDate": "2025-05-01 00:00:00.000",
                    "toDate": "2027-05-31 23:59:59.000",
                    "toGmt": "GMT+05:30"
                  }
      responses:
        '200':
          description: OK
  /rcs/message/batches:
    post:
      tags:
      - RCS
      summary: Get All Batches
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## List the tenant's bulk campaigns

        Optional filter body supports `status`, `campaignType`, `messageType`, `active`, `scheduled`, date ranges.

        **Status filter accepts** any of: `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED`, `FAILED`.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)

        ---

      operationId: post_rcs_message_batches
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                page:
                  type: integer
                size:
                  type: integer
                sortBy:
                  type: string
                sortDir:
                  type: string
                search:
                  type: string
                status:
                  type: string
                campaignType:
                  type: string
                messageType:
                  type: string
                campaignName:
                  type: string
                active: {}
                scheduled: {}
                toGmt:
                  type: string
                createdFrom:
                  type: string
                createdTo:
                  type: string
                updatedFrom: {}
                updatedTo: {}
                scheduleTimeFrom: {}
                scheduleTimeTo: {}
                recurrenceEndTimeFrom: {}
                recurrenceEndTimeTo: {}
            examples:
              Get All Batches:
                value:
                  page: 0
                  size: 20
                  sortBy: batchId
                  sortDir: DESC
                  search: ''
                  status: ''
                  campaignType: ''
                  messageType: ''
                  campaignName: ''
                  active: null
                  scheduled: null
                  toGmt: GMT+05:30
                  createdFrom: '2025-05-01 00:00:00.000'
                  createdTo: '2027-05-31 23:59:59.000'
                  updatedFrom: null
                  updatedTo: null
                  scheduleTimeFrom: null
                  scheduleTimeTo: null
                  recurrenceEndTimeFrom: null
                  recurrenceEndTimeTo: null
      responses:
        '200':
          description: OK
  /rcs/message/pause:
    get:
      tags:
      - RCS
      summary: Pause Batch
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Pause an in-flight batch

        - **Allowed initial status**: `PENDING`, `INPROGRESS`
        - Returns `400` if status is `PAUSED`, `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED`

        ---

      operationId: get_rcs_message_pause
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: RCS_BATCH_ID
      responses:
        '200':
          description: OK
  /rcs/message/resume:
    get:
      tags:
      - RCS
      summary: Resume Batch
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Resume a paused batch

        - **Allowed initial status**: `PAUSED` only
        - Returns `400` if status is `PENDING`, `INPROGRESS`, `DONE`, `ABORTED`, `FAILED` (prevents DONE/ABORTED re-fire)
        - On success: status → `INPROGRESS`

        ---

      operationId: get_rcs_message_resume
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: RCS_BATCH_ID
      responses:
        '200':
          description: OK
  /rcs/message/abort:
    delete:
      tags:
      - RCS
      summary: Abort Batch
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists

        ---

      operationId: delete_rcs_message_abort
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: RCS_BATCH_ID
      responses:
        '200':
          description: OK
  /rcs/message/edit:
    get:
      tags:
      - RCS
      summary: Edit Batch
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Load a batch for editing (pauses if live)

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED` (if was INPROGRESS), record returned

        ---

      operationId: get_rcs_message_edit
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: RCS_BATCH_ID
      responses:
        '200':
          description: OK
  /rcs/message/about:
    get:
      tags:
      - RCS
      summary: Get Batch Details
      description: |+
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Get batch status / progress

        Returns total / sent / pending counts and the current status.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)

        ---

      operationId: get_rcs_message_about
      parameters:
      - name: batchId
        in: query
        required: false
        schema:
          type: string
        example: RCS_BATCH_ID
      responses:
        '200':
          description: OK
  /rcs/rcs-pricing:
    post:
      tags:
      - RCS
      summary: '[operator] Create Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Description

        This API is used to create or update RCS pricing configuration for a specific country.

        It stores message pricing details such as basic message rate, single message rate, and conversation rate.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | countryCode | String | Country dialing code |
        | countryName | String | Country name |
        | basicMessageRate | Decimal | Pricing rate for basic RCS messages |
        | singleMessageRate | Decimal | Pricing rate for single messages |
        | conversationRate | Decimal | Pricing rate for conversation-based billing |

        ---

        ### Headers

        | Header | Description |
        | --- | --- |
        | Authorization | {{SUPER_TOKEN}} token |
        | username | User account name |
        | Content-Type | Request content type (`application/json`) |

        ---

        ### Usage

        Use this API to:

        -
            Configure country-wise RCS pricing

        -
            Set billing rates for RCS services

        -
            Manage conversation and message costs

        -
            Update pricing information dynamically


        ---

        ### Response Explanation

        | Field | Description |
        | --- | --- |
        | countryCode | Country dialing code |
        | countryName | Country name |
        | basicMessageRate | Configured basic message rate |
        | singleMessageRate | Configured single message rate |
        | conversationRate | Configured conversation billing rate |
      operationId: post_rcs_rcs_pricing
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                countryCode:
                  type: string
                countryName:
                  type: string
                basicMessageRate:
                  type: number
                singleMessageRate:
                  type: number
                conversationRate:
                  type: number
            examples:
              '[operator] Create Pricing':
                value:
                  countryCode: '91'
                  countryName: India
                  basicMessageRate: 0.006
                  singleMessageRate: 0.0026
                  conversationRate: 0.016
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/rcs-pricing/list:
    post:
      tags:
      - RCS
      summary: '[operator] Get All Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Description

        This API is used to retrieve all configured RCS pricing records.

        It returns country-wise pricing information including message and conversation billing rates.

        ---

        ### Parameters

        This API does not require any request body parameters.

        ---

        ### Headers

        | Header | Description |
        | --- | --- |
        | Authorization | {{SUPER_TOKEN}} token |
        | username | User account name |
      operationId: post_rcs_rcs_pricing_list
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                page:
                  type: integer
                size:
                  type: integer
                search:
                  type: string
                sortBy:
                  type: string
                sortDir:
                  type: string
            examples:
              '[operator] Get All Pricing':
                value:
                  page: 0
                  size: 10
                  search: ''
                  sortBy: createdAt
                  sortDir: desc
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /rcs/rcs-pricing/{RCS_COUNTRY_CODE}:
    get:
      tags:
      - RCS
      summary: '[operator] Get Pricing By Country'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Description

        This API is used to retrieve RCS pricing configuration details for a specific country using the country code.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | countryCode | String | Country dialing code |

        ---

        ### Headers

        | Header | Description |
        | --- | --- |
        | Authorization | {{SUPER_TOKEN}} token |
        | username | User account name |
      operationId: get_rcs_rcs_pricing_RCS_COUNTRY_CODE
      parameters:
      - name: RCS_COUNTRY_CODE
        in: path
        required: true
        schema:
          type: string
        example: RCS_COUNTRY_CODE
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    put:
      tags:
      - RCS
      summary: '[operator] Update Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Description

        This API is used to update the existing RCS pricing configuration for a specific country using the country code.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | countryCode | String | Country dialing code |
        | countryName | String | Country name |
        | basicMessageRate | Decimal | Updated pricing rate for basic RCS messages |
        | singleMessageRate | Decimal | Updated pricing rate for single messages |
        | conversationRate | Decimal | Updated conversation billing rate |

        ---

        ### Headers

        | Header | Description |
        | --- | --- |
        | Authorization | {{SUPER_TOKEN}} token |
        | username | User account name |
        | Content-Type | Request content type (`application/json`) |
      operationId: put_rcs_rcs_pricing_RCS_COUNTRY_CODE
      parameters:
      - name: RCS_COUNTRY_CODE
        in: path
        required: true
        schema:
          type: string
        example: RCS_COUNTRY_CODE
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                countryCode:
                  type: string
                countryName:
                  type: string
                basicMessageRate:
                  type: number
                singleMessageRate:
                  type: number
                conversationRate:
                  type: number
            examples:
              '[operator] Update Pricing':
                value:
                  countryCode: '91'
                  countryName: India
                  basicMessageRate: 0.0065
                  singleMessageRate: 0.003
                  conversationRate: 0.016
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    delete:
      tags:
      - RCS
      summary: '[operator] Delete Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Description

        This API is used to delete an existing RCS pricing configuration for a specific country using the country code.

        ---

        ### Parameters

        | Parameter | Type | Description |
        | --- | --- | --- |
        | countryCode | String | Country dialing code |

        ---

        ### Headers

        | Header | Description |
        | --- | --- |
        | Authorization | {{SUPER_TOKEN}} token |
        | username | User account name |
      operationId: delete_rcs_rcs_pricing_RCS_COUNTRY_CODE
      parameters:
      - name: RCS_COUNTRY_CODE
        in: path
        required: true
        schema:
          type: string
        example: RCS_COUNTRY_CODE
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard/all:
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get All Clients (Paginated)'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get all business clients with pagination and filters

        Returns a paginated, filterable list of onboarded business clients across all tenants. Supports status, quality-rating, free-text search, and a GMT-aware startDate–endDate range. Requires super-admin / system role.

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `GET /clients-onboard/all`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |
        | `startDate` | query | no | ISO date-time |
        | `endDate` | query | no | ISO date-time |
        | `status` | query | no | Filter by status |
        | `qualityRating` | query | no |  |
        | `search` | query | no | Free-text search |
        | `toGmt` | query | no | Offset `±HH:mm` for the date filters |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Successfully retrieved |
        | 401 | Unauthorized |
        | 500 | Server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_clients_onboard_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: qualityRating
        in: query
        required: false
        schema:
          type: string
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard/{WA_APP_ID}:
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get Client by ID'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get business client by ID

        Retrieves a specific onboarded business client by its ID. Requires ADMIN role authorization.

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `GET /clients-onboard/{id}`

        **Headers** `Authorization: Bearer` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        | --- | --- | --- | --- |
        | `id` | path | yes | Business client ID to retrieve |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Successfully retrieved business client |
        | 401 | Unauthorized - invalid or missing username in header |
        | 404 | Business client not found with given ID |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `OnboardedBusinessClientResponse`

        | Field | Type |
        | --- | --- |
        | `appId` | `UUID` |
        | `appName` | `String` |
        | `partnerAppId` | `String` |
        | `accessToken` | `String` |
        | `description` | `String` |
        | `businessId` | `String` |
        | `username` | `String` |
        | `wabaId` | `String` |
        | `phoneNumberId` | `String` |
        | `displayPhoneNumber` | `String` |
        | `verifiedName` | `String` |
        | `qualityRating` | `String` |
        | `webhookUrl` | `String` |
        | `lastOnboardedTime` | `Long` |
        | `status` | `String` |
        | `disableInfo` | `String` |
        | `banInfo` | `String` |
        | `restrictionInfo` | `String` |
        | `currentLimit` | `String` |
        | `verificationReason` | `String` |
        | `verificationRejection` | `String` |
        | `sandbox` | `boolean` |
        | `tokenGeneratedAt` | `LocalDateTime` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `rateLimit` | `Integer` |
        | `createdAt` | `LocalDateTime` |
        | `updatedAt` | `LocalDateTime` |
        | `webhookToken` | `String` |
      operationId: get_whatsapp_clients_onboard_WA_APP_ID
      parameters:
      - name: WA_APP_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard/me:
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get My Client'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get business client by username

        Retrieves the onboarded business client associated with a specific username. Returns only the data for the requested username. Requires ADMIN role authorization.

        **Endpoint** `GET /clients-onboard/me`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Successfully retrieved business client for the username |
        | 401 | Unauthorized - invalid or missing username in header |
        | 404 | Business client not found for the given username |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `OnboardedBusinessClientResponse`

        | Field | Type |
        |---|---|
        | `appId` | `UUID` |
        | `appName` | `String` |
        | `partnerAppId` | `String` |
        | `accessToken` | `String` |
        | `description` | `String` |
        | `businessId` | `String` |
        | `username` | `String` |
        | `wabaId` | `String` |
        | `phoneNumberId` | `String` |
        | `displayPhoneNumber` | `String` |
        | `verifiedName` | `String` |
        | `qualityRating` | `String` |
        | `webhookUrl` | `String` |
        | `lastOnboardedTime` | `Long` |
        | `status` | `String` |
        | `disableInfo` | `String` |
        | `banInfo` | `String` |
        | `restrictionInfo` | `String` |
        | `currentLimit` | `String` |
        | `verificationReason` | `String` |
        | `verificationRejection` | `String` |
        | `sandbox` | `boolean` |
        | `tokenGeneratedAt` | `LocalDateTime` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `rateLimit` | `Integer` |
        | `createdAt` | `LocalDateTime` |
        | `updatedAt` | `LocalDateTime` |
        | `webhookToken` | `String` |
      operationId: get_whatsapp_clients_onboard_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard:
    post:
      tags:
      - WhatsApp
      summary: '[operator] Create Client'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Create a new business client

        Creates a new onboarded business client with WhatsApp Business Account details. Requires ADMIN role authorization.

        **Notes for this request**

        Creates a tenant. Body fields are documented in this folder's description (matches `OnboardedBusinessClientRequest`). Requires `{{SUPER_TOKEN}}`.

        **Endpoint** `POST /clients-onboard/`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Request body** `application/json` — `OnboardedBusinessClientRequest`

        | Field | Type |
        |---|---|
        | `username` | `String` |
        | `appName` | `String` |
        | `businessId` | `String` |
        | `partnerAppId` | `String` |
        | `wabaId` | `String` |
        | `accessToken` | `String` |
        | `phoneNumberId` | `String` |
        | `webhookUrl` | `String` |
        | `description` | `String` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `webhookToken` | `String` |
        | `rateLimit` | `Integer` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 201 | Business client created successfully |
        | 400 | Invalid request data or duplicate business/WABA ID |
        | 401 | Unauthorized - invalid or missing username in header |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `OnboardedBusinessClientResponse`

        | Field | Type |
        |---|---|
        | `appId` | `UUID` |
        | `appName` | `String` |
        | `partnerAppId` | `String` |
        | `accessToken` | `String` |
        | `description` | `String` |
        | `businessId` | `String` |
        | `username` | `String` |
        | `wabaId` | `String` |
        | `phoneNumberId` | `String` |
        | `displayPhoneNumber` | `String` |
        | `verifiedName` | `String` |
        | `qualityRating` | `String` |
        | `webhookUrl` | `String` |
        | `lastOnboardedTime` | `Long` |
        | `status` | `String` |
        | `disableInfo` | `String` |
        | `banInfo` | `String` |
        | `restrictionInfo` | `String` |
        | `currentLimit` | `String` |
        | `verificationReason` | `String` |
        | `verificationRejection` | `String` |
        | `sandbox` | `boolean` |
        | `tokenGeneratedAt` | `LocalDateTime` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `rateLimit` | `Integer` |
        | `createdAt` | `LocalDateTime` |
        | `updatedAt` | `LocalDateTime` |
        | `webhookToken` | `String` |
      operationId: post_whatsapp_clients_onboard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                appName:
                  type: string
                businessId:
                  type: string
                partnerAppId:
                  type: string
                wabaId:
                  type: string
                accessToken:
                  type: string
                phoneNumberId:
                  type: string
                webhookUrl:
                  type: string
                webhookToken:
                  type: string
                description:
                  type: string
                tierId:
                  type: integer
                isPassthroughFee:
                  type: boolean
                applyToIncoming:
                  type: boolean
                rateLimit:
                  type: integer
            examples:
              '[operator] Create Client':
                value:
                  username: acme_wa
                  appName: Acme Retail
                  businessId: '{{WA_WABA_ID}}'
                  partnerAppId: '{{WA_META_APP_ID}}'
                  wabaId: '{{WA_WABA_ID}}'
                  accessToken: <long-lived-or-system-user-token>
                  phoneNumberId: '{{WA_PHONE_NUMBER_ID}}'
                  webhookUrl: https://example.com/webhooks/whatsapp
                  webhookToken: <bearer-token-we-send-to-your-webhook>
                  description: Live onboarding of Acme Retail
                  tierId: 1
                  isPassthroughFee: true
                  applyToIncoming: false
                  rateLimit: 60
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard/update/{WA_APP_ID}:
    put:
      tags:
      - WhatsApp
      summary: '[operator] Update Client'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update an existing business client

        Updates an existing onboarded business client by ID. Requires ADMIN role authorization.

        **Notes for this request**

        Updates an existing tenant by id (`{{WA_APP_ID}}`). `username` and `appName` are mandatory on update as well; omitted optional fields are left unchanged.

        **Endpoint** `PUT /clients-onboard/update/{id}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `id` | path | yes | Business client ID to update |

        **Request body** `application/json` — `OnboardedBusinessClientRequest`

        | Field | Type |
        |---|---|
        | `username` | `String` |
        | `appName` | `String` |
        | `businessId` | `String` |
        | `partnerAppId` | `String` |
        | `wabaId` | `String` |
        | `accessToken` | `String` |
        | `phoneNumberId` | `String` |
        | `webhookUrl` | `String` |
        | `description` | `String` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `webhookToken` | `String` |
        | `rateLimit` | `Integer` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Business client updated successfully |
        | 400 | Invalid request data or duplicate business/WABA ID |
        | 401 | Unauthorized - invalid or missing username in header |
        | 404 | Business client not found with given ID |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `OnboardedBusinessClientResponse`

        | Field | Type |
        |---|---|
        | `appId` | `UUID` |
        | `appName` | `String` |
        | `partnerAppId` | `String` |
        | `accessToken` | `String` |
        | `description` | `String` |
        | `businessId` | `String` |
        | `username` | `String` |
        | `wabaId` | `String` |
        | `phoneNumberId` | `String` |
        | `displayPhoneNumber` | `String` |
        | `verifiedName` | `String` |
        | `qualityRating` | `String` |
        | `webhookUrl` | `String` |
        | `lastOnboardedTime` | `Long` |
        | `status` | `String` |
        | `disableInfo` | `String` |
        | `banInfo` | `String` |
        | `restrictionInfo` | `String` |
        | `currentLimit` | `String` |
        | `verificationReason` | `String` |
        | `verificationRejection` | `String` |
        | `sandbox` | `boolean` |
        | `tokenGeneratedAt` | `LocalDateTime` |
        | `tierId` | `Long` |
        | `isPassthroughFee` | `Boolean` |
        | `applyToIncoming` | `Boolean` |
        | `rateLimit` | `Integer` |
        | `createdAt` | `LocalDateTime` |
        | `updatedAt` | `LocalDateTime` |
        | `webhookToken` | `String` |
      operationId: put_whatsapp_clients_onboard_update_WA_APP_ID
      parameters:
      - name: WA_APP_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_APP_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                appName:
                  type: string
                wabaId:
                  type: string
                phoneNumberId:
                  type: string
                webhookUrl:
                  type: string
                webhookToken:
                  type: string
                description:
                  type: string
                isPassthroughFee:
                  type: boolean
                applyToIncoming:
                  type: boolean
                rateLimit:
                  type: integer
            examples:
              '[operator] Update Client':
                value:
                  username: acme_wa
                  appName: Acme Retail
                  wabaId: '{{WA_WABA_ID}}'
                  phoneNumberId: '{{WA_PHONE_NUMBER_ID}}'
                  webhookUrl: https://example.com/webhooks/whatsapp/v2
                  webhookToken: <rotated-token>
                  description: Webhook moved to v2
                  isPassthroughFee: true
                  applyToIncoming: false
                  rateLimit: 80
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/clients-onboard/delete/{WA_APP_ID}:
    delete:
      tags:
      - WhatsApp
      summary: '[operator] Delete Client'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete a business client

        Deletes an onboarded business client by ID. Requires ADMIN role authorization.

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `DELETE /clients-onboard/delete/{id}`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `id` | path | yes | Business client ID to delete |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 204 | Business client deleted successfully |
        | 401 | Unauthorized - invalid or missing username in header |
        | 404 | Business client not found with given ID |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: delete_whatsapp_clients_onboard_delete_WA_APP_ID
      parameters:
      - name: WA_APP_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_APP_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/generate-link:
    post:
      tags:
      - WhatsApp
      summary: Generate Onboarding Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Generate Encrypted Onboarding Link

        Generates a secure encrypted WhatsApp Embedded Signup onboarding link.

        **Notes for this request**

        Generates the encrypted Embedded Signup onboarding link for the calling tenant. No body: identity comes from the `username`, `ipAddress` and `Authorization` headers. Returns 201 with the link.

        **Endpoint** `POST /generate-link`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 201 | Encrypted onboarding link generated successfully |
        | 400 | Invalid request |
        | 401 | Unauthorized |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_generate_link
      responses:
        '200':
          description: OK
  /whatsapp/message/sendbulk:
    post:
      tags:
      - WhatsApp
      summary: Reply with Image
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Send a message of any type to one or many recipients

        Unified send endpoint (multipart/form-data). `messageType` selects the payload:
        TEXT, IMAGE, VIDEO, AUDIO, DOCUMENT, STICKER, LOCATION, CONTACTS, TEMPLATE, INTERACTIVE, REACTION, FLOW.
        Recipients come from `destinationNo` (comma / semicolon / newline separated) and/or `destinationFiles` (txt, csv, xlsx).
        The call creates (batchId=0) or appends to a batch and returns immediately with the batchId and per-file acceptance counts;
        per-recipient delivery status (SUBMITTED -> SENT -> DELIVERED -> READ, or FAILED / REJECTED with the reason) is pushed to the
        tenant webhook and available from /message/bulk-insights. Supports quoted replies (`replyToMessageId`), throttling (`delay`)
        and scheduled / recurring delivery (`scheduled`, `scheduleTime`, `gmt`, `recurrence`, `repeatCount`, `recurrenceEndTime`).

        **Endpoint** `POST /message/sendbulk`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `multipart/form-data` — every field is documented in **6.0 Field Reference — Message Object**; which ones are mandatory depends on `messageType`.

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Batch accepted. Body carries per-file counts, batchId, and any invalidNumbers. |
        | 400 | Validation error — missing/invalid type-specific field, invalid destination, unsupported messageType, personalized param-count mismatch, or oversized / non-HTTPS media. Body: ExceptionResponse. |
        | 404 | Template or sender not found for this user. Body: ExceptionResponse. |
        | 413 | Uploaded destination/media file exceeds the configured size limit. Body: ExceptionResponse. |
        | 500 | Internal server or WhatsApp API error. Body: ExceptionResponse. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_message_sendbulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                batchId:
                  type: string
                destinationNo:
                  type: string
                allowDuplicate:
                  type: string
                campaignName:
                  type: string
                replyToMessageId:
                  type: string
                messageType:
                  type: string
                mediaUrl:
                  type: string
                content:
                  type: string
            examples:
              Reply with Image:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: IMAGE
                  mediaUrl: https://example.com/
                  content: Here is the picture you asked for
              Reply with Document:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: DOCUMENT
                  mediaFile: 3kGYHtX8O/invoice-1001.pdf
                  content: invoice-1001.pdf
              Reply with Sticker:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: STICKER
                  mediaFile: ''
              Reply with Locations:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: LOCATION
                  latitude: '28.6139'
                  longitude: '77.2090'
                  locationName: Connaught Place
                  locationAddress: New Delhi, India
              Reply with Contacts:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: CONTACTS
                  contactsPayload: '[{"name": {"formatted_name": "Alex Morgan", "first_name": "Alex", "last_name": "Morgan"},
                    "phones": [{"phone": "+447700900124", "type": "CELL", "wa_id": "447700900124"}]}]'
              Reply with Interactive list:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: INTERACTIVE
                  interactivePayload: '{"type": "list", "header": {"type": "text", "text": "Payment mode"}, "body": {"text":
                    "How would you like to pay?"}, "action": {"button": "Choose", "sections": [{"title": "Options", "rows":
                    [{"id": "upi", "title": "UPI"}, {"id": "card", "title": "Card"}, {"id": "cod", "title": "Cash on delivery"}]}]}}'
              Reply with Template:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: TEMPLATE
                  templateName: payment_confirmation_v580
                  templateLanguage: en_US
                  bodyTemplateVariables: INV-400
              Reply with Video(GIF as mp4):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  campaignName: COMMON
                  replyToMessageId: WA_WAMID
                  messageType: VIDEO
                  mediaFile: umR8hkA3m/sample-5s-360p.mp4
                  content: 😀
              Text Simple:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: Hello World
              Text with Emoji:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: Hello! 👋 Welcome to BroadNet WhatsApp CPaaS 🚀 Let's get started! ✅
              Text Long (4096 chars max):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: This is a long text message that tests the WhatsApp 4096 character limit for text messages. WhatsApp
                    Business API allows text messages up to 4096 characters in length. This test verifies that the system
                    properly handles messages approaching this maximum length. Lorem ipsum dolor sit amet, consectetur adipiscing
                    elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
                    nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
                    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
                    cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
              Image By File Upload:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  campaignName: COMMON
                  mediaFile: /path/to/image.jpg
              Image With Caption:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  campaignName: COMMON
                  content: Check out our new product lineup!
                  mediaFile: /path/to/image.jpg
              Image By URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: IMAGE
                  campaignName: COMMON
                  mediaUrl: https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png
                  content: Image sent via URL
              Video By URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  campaignName: COMMON
                  mediaUrl: https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.mp4
              Audio By URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  campaignName: COMMON
                  mediaUrl: https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.mp3
              Video By File Upload:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  campaignName: COMMON
                  content: Product demo video
                  mediaFile: /path/to/video.mp4
              Audio By File Upload:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  campaignName: COMMON
                  mediaFile: /path/to/audio.ogg
              Document By File Upload:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: DOCUMENT
                  campaignName: COMMON
                  content: Invoice for Q1 2026
                  mediaFile: /path/to/document.pdf
              Sticker By File Upload:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: STICKER
                  campaignName: COMMON
                  mediaFile: /path/to/sticker.webp
              Location:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: LOCATION
                  campaignName: COMMON
                  latitude: '37.4847'
                  longitude: '-122.1477'
                  locationName: Meta HQ
                  locationAddress: 1 Hacker Way, Menlo Park, CA 94025
              Contacts:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: CONTACTS
                  campaignName: COMMON
                  contactsPayload: '[{"name":{"formatted_name":"Jane Doe","first_name":"Jane","last_name":"Doe"},"phones":[{"phone":"+447700900125","type":"CELL","wa_id":"447700900125"}]}]'
              Contacts Full vCard (contactsPayload):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: CONTACTS
                  campaignName: COMMON
                  contactsPayload: '[{"name":{"formatted_name":"Jane Doe","first_name":"Jane","last_name":"Doe"},"phones":[{"phone":"+447700900125","type":"CELL","wa_id":"447700900125"},{"phone":"+447700900126","type":"WORK"}],"emails":[{"email":"jane@example.com","type":"WORK"}],"addresses":[{"street":"1
                    Market St","city":"San Francisco","state":"CA","zip":"94105","country":"United States","country_code":"US","type":"WORK"}],"org":{"company":"Acme
                    Corp","department":"Engineering","title":"Senior Engineer"},"urls":[{"url":"https://example.com","type":"WORK"}],"birthday":"1990-01-15"}]'
              Template Simple Text:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: test_112
                  templateLanguage: en_US
              Template With Variables:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: broadnet_omni_channel
                  templateLanguage: en_US
                  bodyTemplateVariables: John Doe
              Template With Header Media:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: appointment_cancellation9001
                  templateLanguage: en_US
                  mediaUrl: https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png
                  bodyTemplateVariables: '15:00'
              Template Bulk to Contact File (same vars for all):
                value:
                  batchId: '0'
                  messageType: TEMPLATE
                  templateName: broadnet_omni_channel
                  templateLanguage: en_US
                  campaignName: same_for_all_test
                  allowDuplicate: 'false'
                  destinationFiles: /path/to/contacts.csv
                  bodyTemplateVariables: John Doe
              Template Bulk Personalized File (per-row vars):
                value:
                  batchId: '0'
                  messageType: TEMPLATE
                  templateName: broadnet_omni_channel
                  templateLanguage: en_US
                  campaignName: personalized_test
                  allowDuplicate: 'false'
                  destinationFiles: /path/to/personalized.csv
              Template With Dynamic URL Button (buttonsTemplateVariable):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: broadnet_omni_channel
                  templateLanguage: en_US
                  bodyTemplateVariables: John Doe
                  buttonsTemplateVariable: summer2026
              Template Carousel Send (reuse template images):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: carousel_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  carouselSendCards[0].bodyVariables[0]: John
                  carouselSendCards[0].buttonVariables[0]: '{"sub_type":"quick_reply","value":"prod1"}'
                  carouselSendCards[1].bodyVariables[0]: John
              Template Limited-Time-Offer Send (limitedTimeOfferExpirationMs):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: lto_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  limitedTimeOfferExpirationMs: '1799999999000'
                  buttonsTemplateVariable: DEAL50
              Template  COPY_CODE Coupon Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: coupon_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  buttonsTemplateVariable: SAVE20
              Template Multi / Quick-Reply Buttons (explicit):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: multi_button_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  buttonsTemplateVariable: '[{"index":0,"sub_type":"copy_code","value":"SAVE20"},{"index":2,"sub_type":"quick_reply","value":"OPTED_IN"}]'
              Template Header Media Override:
                value:
                  batchId: '0'
                  destinationNo: |
                    WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: promo_image_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: 50%
                  mediaUrl: https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png
                  buttonsTemplateVariable: ORD123
              Template Flow Button Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: tuesday_flow_signup_v1
                  campaignName: COMMON
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  buttonsTemplateVariable: '[{"index":0,"sub_type":"flow","value":"{\"flow_token\":\"FLOW_TOKEN_123\",\"flow_action_data\":{\"product_id\":\"SKU42\"}}"}]'
              Template Catalog Button Send (thumbnail product):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: catalog_v1
                  campaignName: COMMON
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  buttonsTemplateVariable: BESTSELLER_SKU_01
              Template Catalog Button Send (no variable, auto button):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: catalog_promo_vl218827
                  campaignName: COMMON
                  templateLanguage: en
                  bodyTemplateVariables: kjhonnnuser
              Template  SPM (Single-Product) Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: hello111
                  campaignName: COMMON
                  templateLanguage: en
                  bodyTemplateVariables: John
                  headerTemplateVariables: '{"catalog_id":"WA_CATALOG_ID","product_retailer_id":"WA_PRODUCT_RETAILER_ID"}'
              Template  MPM (Multi-Product) Button Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: mpm_v1
                  campaignName: COMMON
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  buttonsTemplateVariable: '[{"index":0,"sub_type":"mpm","value":"{\"thumbnail_product_retailer_id\":\"SKU_HERO\",\"sections\":[{\"title\":\"Best
                    Sellers\",\"product_items\":[{\"product_retailer_id\":\"SKU1\"},{\"product_retailer_id\":\"SKU2\"}]}]}"}]'
              Template Currency Body Param:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: order_total_v1
                  campaignName: COMMON
                  templateLanguage: en_US
                  bodyTemplateVariables: '{"type":"currency","currency":{"fallback_value":"$100.00","code":"USD","amount_1000":100000}}'
              Template Date-Time Body Param:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  templateName: order_confirmation_v533
                  campaignName: COMMON
                  templateLanguage: en
                  bodyTemplateVariables: '{"type":"date_time","date_time":{"fallback_value":"February 25, 2026 at 3:30 PM","calendar":"GREGORIAN","year":2026,"month":2,"day_of_month":25,"hour":15,"minute":30}}'
              Template Carousel Send (per-card image override):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: carousel_v1
                  templateLanguage: en_US
                  bodyTemplateVariables: John
                  carouselSendCards[0].headerMediaId: WA_MEDIA_ID
                  carouselSendCards[0].headerType: image
                  carouselSendCards[0].bodyVariables[0]: John
                  carouselSendCards[1].headerMediaId: https://your-cdn/card2.png
                  carouselSendCards[1].headerType: image
                  carouselSendCards[1].bodyVariables[0]: John
              Interactive Reply Buttons (3):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"button","header":{"type":"text","text":"Choose an option"},"body":{"text":"How
                    would you like to proceed with your order?"},"footer":{"text":"Reply by tapping a button"},"action":{"buttons":[{"type":"reply","reply":{"id":"btn_confirm","title":"Confirm"}},{"type":"reply","reply":{"id":"btn_modify","title":"Modify
                    Order"}},{"type":"reply","reply":{"id":"btn_cancel","title":"Cancel"}}]}}'
              Interactive List Menu:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"list","header":{"type":"text","text":"Our Plans"},"body":{"text":"Choose the
                    plan that works best for you:"},"footer":{"text":"Tap to view options"},"action":{"button":"View Plans","sections":[{"title":"Monthly
                    Plans","rows":[{"id":"row_basic","title":"Basic","description":"$9.99/mo - 1000 messages"},{"id":"row_pro","title":"Professional","description":"$29.99/mo
                    - 10000 messages"},{"id":"row_enterprise","title":"Enterprise","description":"$99.99/mo - Unlimited"}]},{"title":"Annual
                    Plans","rows":[{"id":"row_basic_annual","title":"Basic Annual","description":"$99/yr - Save 17%"},{"id":"row_pro_annual","title":"Pro
                    Annual","description":"$299/yr - Save 17%"}]}]}}'
              Interactive CTA URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"cta_url","header":{"type":"text","text":"Visit Our Store"},"body":{"text":"Shop
                    our latest collection with exclusive discounts for WhatsApp customers."},"footer":{"text":"Free shipping
                    on orders over $50"},"action":{"name":"cta_url","parameters":{"display_text":"Shop Now","url":"https://example.com/shop?ref=whatsapp"}}}'
              Interactive Location Request:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"location_request_message","body":{"text":"Please share your delivery location
                    so we can estimate shipping time."},"action":{"name":"send_location"}}'
              Interactive Catalog Message:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"catalog_message","body":{"text":"Browse our full product catalog and find
                    what you need."},"action":{"name":"catalog_message","parameters":{"thumbnail_product_retailer_id":"WA_PRODUCT_RETAILER_ID"}}}'
              Interactive  Single Product:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"product","body":{"text":"Check out this amazing product!"},"footer":{"text":"Limited
                    time offer"},"action":{"catalog_id":"WA_CATALOG_ID","product_retailer_id":"WA_PRODUCT_RETAILER_ID"}}'
              Interactive Multi Product:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"product_list","header":{"type":"text","text":"Our Top Products"},"body":{"text":"Here
                    are our best sellers this week:"},"footer":{"text":"Prices subject to change"},"action":{"catalog_id":"WA_CATALOG_ID","sections":[{"title":"Electronics","product_items":[{"product_retailer_id":"WA_PRODUCT_RETAILER_ID"},{"product_retailer_id":"SKU_002"}]},{"title":"Accessories","product_items":[{"product_retailer_id":"SKU_003"},{"product_retailer_id":"SKU_004"}]}]}}'
              Interactive  Flow:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type": "flow", "header": {"type": "text", "text": "Book Appointment"}, "body": {"text":
                    "Schedule your appointment by filling out the form below."}, "footer": {"text": "Powered by BroadNet"},
                    "action": {"name": "flow", "parameters": {"flow_message_version": "3", "flow_token": "WA_FLOW_TOKEN",
                    "flow_id": "WA_FLOW_ID", "flow_cta": "Book Now", "flow_action": "navigate", "flow_action_payload": {"screen":
                    "WELCOME_SCREEN"}}}}'
              Interactive Flow (Bulk to Contact File):
                value:
                  batchId: '0'
                  destinationFiles: ''
                  allowDuplicate: 'false'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type": "flow", "header": {"type": "text", "text": "Book Appointment"}, "body": {"text":
                    "Schedule your appointment by filling out the form below."}, "footer": {"text": "Powered by BroadNet"},
                    "action": {"name": "flow", "parameters": {"flow_message_version": "3", "flow_token": "WA_FLOW_TOKEN",
                    "flow_id": "WA_FLOW_ID", "flow_cta": "Book Now", "flow_action": "navigate", "flow_action_payload": {"screen":
                    "WELCOME_SCREEN"}}}}'
              Interactive  Flow (data_exchange):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type": "flow", "header": {"type": "text", "text": "Book Appointment"}, "body": {"text":
                    "Schedule your appointment by filling out the form below."}, "footer": {"text": "Powered by BroadNet"},
                    "action": {"name": "flow", "parameters": {"flow_message_version": "3", "flow_token": "WA_FLOW_TOKEN",
                    "flow_id": "WA_FLOW_ID", "flow_cta": "Book Now", "flow_action": "navigate", "flow_action_payload": {"screen":
                    "WELCOME_SCREEN"}}}}'
              Interactive Flow (first-class fields — unified send):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Schedule your appointment by filling out the form below.
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Book Now
                  flowAction: navigate
                  flowScreen: APPOINTMENT_SCREEN
                  flowData: '{}'
                  flowMode: published
                  flowHeaderText: Book your appointment
                  flowFooterText: Powered by BroadNet
              Interactive Flow (first-class fields, data_exchange):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Start your application — the form loads dynamically.
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Start
                  flowAction: navigate
                  flowScreen: WELCOME_SCREEN
              Reaction Send Emoji:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: REACTION
                  campaignName: COMMON
                  replyToMessageId: wamid.HBgLMTY1MDU1NTEyMzQVAgASGCA0
                  emoji: ❤️
              Reaction Remove:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: REACTION
                  campaignName: COMMON
                  replyToMessageId: wamid.HBgLMTY1MDU1NTEyMzQVAgASGCA0
                  emoji: ''
              Bulk Multiple Recipients:
                value:
                  batchId: '0'
                  destinationNo: +447700900127,+447700900128,+447700900101
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: Bulk broadcast message to multiple recipients
              Scheduled Message (one-time):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: This is a scheduled message
                  scheduled: 'true'
                  scheduleTime: '2027-06-05 10:00:00.000'
                  gmt: +05:30
              Scheduled Recurring (DAILY):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: Daily recurring reminder message
                  scheduled: 'true'
                  scheduleTime: '2027-06-05 10:00:00.000'
                  gmt: +05:30
                  recurrence: DAILY
                  repeatCount: '3'
                  recurrenceEndTime: '2027-06-08 10:00:00.000'
              Reply to a Message (replyToMessageId):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: Thanks — replying to your message!
                  replyToMessageId: wamid.HBgMOTE...REPLACE_WITH_INBOUND_WAMID
              GIF (sent as VIDEO):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  campaignName: COMMON
                  mediaFile: /path/to/animation.gif
                  content: Check this out!
              Poll (Interactive List):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"list","header":{"type":"text","text":"Poll"},"body":{"text":"Preferred payment
                    mode?"},"action":{"button":"Choose","sections":[{"title":"Options","rows":[{"id":"opt_1","title":"UPI"},{"id":"opt_2","title":"Card"},{"id":"opt_3","title":"Cash"}]}]}}'
              Interactive Address Message:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"address_message","body":{"text":"Please share your delivery address"},"action":{"name":"address_message","parameters":{"country":"IN","values":{"name":"John
                    Doe","phone_number":"+447700900129"}}}}'
              Interactive Order Details (payment):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"order_details","body":{"text":"Review and pay for your order"},"action":{"name":"review_and_pay","parameters":{"reference_id":"ORD-12345","type":"digital-goods","currency":"INR","total_amount":{"value":150000,"offset":100},"order":{"status":"pending","items":[{"retailer_id":"SKU1","name":"Item
                    1","amount":{"value":150000,"offset":100},"quantity":1}],"subtotal":{"value":150000,"offset":100}},"payment_settings":[{"type":"payment_gateway","payment_gateway":{"type":"razorpay","configuration_name":"my_config"}}]}}}'
              Interactive Order Status:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"order_status","body":{"text":"Your order status update"},"action":{"name":"review_order","parameters":{"reference_id":"ORD-12345","order":{"status":"shipped"}}}}'
              Interactive Call Permission Request (Business Calling):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"call_permission_request","body":{"text":"Can we call you about your order?"},"action":{"name":"call_permission_request"}}'
              Text With URL (link preview):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEXT
                  campaignName: COMMON
                  content: 'Check out our platform: https://www.broadnet.me'
              Document By URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: DOCUMENT
                  campaignName: COMMON
                  content: Your invoice (PDF)
                  mediaUrl: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf
              Sticker By URL:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: STICKER
                  campaignName: COMMON
                  mediaUrl: https://cdn.example.com/media/sample.webp
              Contacts Multiple:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: CONTACTS
                  campaignName: COMMON
                  contactsPayload: '[{"name":{"formatted_name":"John Doe","first_name":"John"},"phones":[{"phone":"+447700900130","type":"CELL"}]},{"name":{"formatted_name":"Jane
                    Smith","first_name":"Jane"},"phones":[{"phone":"+447700900131","type":"WORK"}]}]'
              Template Header Text Variable:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: hello111
                  templateLanguage: en
                  headerTemplateVariables: BroadNet
                  bodyTemplateVariables: John Doe
              Template Named Parameters ({{WA_NAME}}):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: hello111
                  templateLanguage: en
                  bodyTemplateVariables: '{"parameter_name":"order_id","text":"ORD-12345"}'
              Template Authentication / OTP Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: auth_login_otp
                  templateLanguage: en_US
                  bodyTemplateVariables: '123456'
                  buttonsTemplateVariable: '123456'
              Template Location Header Send:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: TEMPLATE
                  campaignName: COMMON
                  templateName: hello111
                  templateLanguage: en
                  bodyTemplateVariables: John
                  latitude: '37.4847'
                  longitude: '-122.1477'
                  locationName: Meta HQ
                  locationAddress: 1 Hacker Way, Menlo Park
              Intractive Reply Buttons + Image Header:
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type":"button","header":{"type":"image","image":{"link":"https://cdn.example.com/media/00000000-0000-4000-8000-000000000000.png"}},"body":{"text":"Confirm
                    your order?"},"footer":{"text":"BroadNet"},"action":{"buttons":[{"type":"reply","reply":{"id":"yes","title":"Yes"}},{"type":"reply","reply":{"id":"no","title":"No"}}]}}'
              11.21.4 Send Flow — SIGN_UP (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Create your account in just a few steps!
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Sign Up Now
                  flowAction: navigate
                  flowScreen: REGISTER
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Powered by our platform
              11.22.4 Send Flow — SIGN_IN (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Sign in to your account quickly and securely.
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Sign In
                  flowAction: navigate
                  flowScreen: LOGIN
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Secure Login
              11.23.4 Send Flow — APPOINTMENT_BOOKING (image header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type": "flow", "header": {"type": "image", "image": {"link": "https://cdn.example.com/media/app.jfif"}},
                    "body": {"text": "Book your appointment quickly and easily."}, "footer": {"text": "Our Clinic"}, "action":
                    {"name": "flow", "parameters": {"flow_message_version": "3", "flow_token": "WA_FLOW_TOKEN", "flow_id":
                    "WA_FLOW_ID", "flow_cta": "Book Now", "flow_action": "navigate", "flow_action_payload": {"screen": "SELECT_SERVICE",
                    "data": {}}}}}'
              11.24.5 Send Flow — LEAD_GENERATION (video header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: INTERACTIVE
                  campaignName: COMMON
                  interactivePayload: '{"type": "flow", "header": {"type": "video", "video": {"link": "https://cdn.example.com/media/4.mp4"}},
                    "body": {"text": "You have a pre-approved loan offer waiting! Check your personalised offer now."}, "footer":
                    {"text": "Our Bank"}, "action": {"name": "flow", "parameters": {"flow_message_version": "3", "flow_token":
                    "WA_FLOW_TOKEN", "flow_id": "WA_FLOW_ID", "flow_cta": "Check Offer", "flow_action": "navigate", "flow_action_payload":
                    {"screen": "PERSONAL_INFO", "data": {}}}}}'
              11.25.5 Send Flow — SHOPPING (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Shop our latest collection and get it delivered to your door!
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Shop Now
                  flowAction: navigate
                  flowScreen: CATEGORY_SELECT
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Our Store
              11.26.4 Send Flow — CONTACT_US (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Have a question? Our team is ready to help. Send us a message now!
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Contact Us
                  flowAction: navigate
                  flowScreen: CONTACT_FORM
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Support Team
              11.27.5 Send Flow — CUSTOMER_SUPPORT (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Need help? Raise a support ticket and we will get back to you fast.
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Get Help
                  flowAction: navigate
                  flowScreen: ISSUE_TYPE
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Support Team
              11.28.4 Send Flow — SURVEY (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: How was your recent experience with us? Share your feedback — it only takes 2 minutes!
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Share Feedback
                  flowAction: navigate
                  flowScreen: SURVEY_RATINGS
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: Our Team
              11.29.5 Send Flow — INSURANCE_QUOTE (text header):
                value:
                  batchId: '0'
                  destinationNo: WA_DESTINATION_NO
                  allowDuplicate: 'true'
                  messageType: FLOW
                  campaignName: COMMON
                  content: Get a personalised health insurance quote in under 2 minutes. No paperwork needed!
                  flowId: WA_FLOW_ID
                  flowToken: YOUR_TOKEN
                  flowCta: Get Quote
                  flowAction: navigate
                  flowScreen: PROFILE_INFO
                  flowData: '{}'
                  flowMode: published
                  flowFooterText: CS Mutual Insurance
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                totalFiles: 1
                totalSuccess: 1
                totalFailed: 0
                totalDuplicates: 0
                batchId: '2609091405000000001'
                fileResults:
                - fileName: direct
                  totalRecords: 1
                  successCount: 1
                  failedRecipients: []
                  duplicateRecipients: []
                message: Messages queued for delivery
  /whatsapp/message/read:
    post:
      tags:
      - WhatsApp
      summary: Mark Message as Read
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Mark WhatsApp message as read

        Marks an incoming WhatsApp message as READ and optionally
        shows a typing indicator while the system prepares a reply.
        ✅ Supports:
        - Read only
        - Read + typing indicator
        📌 Typing indicator is automatically removed when a reply is sent
        or after 25 seconds.

        **Notes for this request**

        Needs a REAL inbound wamid → set {{WA_WAMID}} (message the business number, copy the wamid from the webhook).

        **Endpoint** `POST /message/read`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Message marked as read successfully. |
        | 400 | Invalid or missing messageId. Body: ExceptionResponse. |
        | 401 | Unauthorized or invalid access token. Body: ExceptionResponse. |
        | 500 | WhatsApp API or internal server error. Body: ExceptionResponse. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_message_read
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                messageId:
                  type: string
            examples:
              Mark Message as Read:
                value:
                  messageId: '{{WA_WAMID}}'
              Mark Message as Read + Typing:
                value:
                  messageId: '{{WA_WAMID}}'
                  typing: true
      responses:
        '200':
          description: OK
  /whatsapp/template:
    post:
      tags:
      - WhatsApp
      summary: Create Marketing Calling Permission Image Header
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create WhatsApp Template

        Creates a WhatsApp template using multipart/form-data input. Supports header file upload, header/body/footer text, body examples, and button text list.

        **Endpoint** `POST /template`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `multipart/form-data` — every field is documented in **7.0 Field Reference — Template Object**.

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Template created successfully. |
        | 400 | Invalid input data. |
        | 500 | Internal server error. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_template
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                languageType:
                  type: string
                category:
                  type: string
                templateType:
                  type: string
                headerFormat:
                  type: string
                headerFile:
                  type: string
                  format: binary
                bodyText:
                  type: string
                bodyExample:
                  type: string
                footerText:
                  type: string
                buttonRequest:
                  type: string
            examples:
              Create Marketing Calling Permission Image Header:
                value:
                  name: calling_permission_img_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CALLING_PERMISSION
                  headerFormat: IMAGE
                  headerFile: ''
                  bodyText: Hi WA_1, may we call you about offers from WA_2? Tap Allow to let us call you.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Reply YES to allow the call
                  buttonRequest: QUICK_REPLY:Allow
              Create Marketing Calling Permission Video Header:
                value:
                  name: calling_permission_vid_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CALLING_PERMISSION
                  headerFormat: VIDEO
                  headerFile: ''
                  bodyText: Hi WA_1, may we call you about offers from WA_2? Tap Allow to let us call you.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Reply YES to allow the call
                  buttonRequest: QUICK_REPLY:Allow
              Create Marketing Calling Permission Document Header:
                value:
                  name: calling_permission_doc_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CALLING_PERMISSION
                  headerFormat: DOCUMENT
                  headerFile: ''
                  bodyText: Hi WA_1, may we call you about offers from WA_2? Tap Allow to let us call you.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Reply YES to allow the call
                  buttonRequest: QUICK_REPLY:Allow
              Create Utility Default Image Header With TTL:
                value:
                  name: appointment_cancelled_img_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: IMAGE
                  headerFile: ''
                  bodyText: Hello WA_1, your appointment with WA_2 on WA_3 at WA_4 has been cancelled. Reply to rebook.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Thank you!
                  buttonRequest: QUICK_REPLY:Rebook
                  timeToLive: '1800'
              Create Utility Default Video Header With TTL:
                value:
                  name: appointment_cancelled_vid_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: VIDEO
                  headerFile: ''
                  bodyText: Hello WA_1, your appointment with WA_2 on WA_3 at WA_4 has been cancelled. Reply to rebook.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Thank you!
                  buttonRequest: QUICK_REPLY:Rebook
                  timeToLive: '1800'
              Create Utility Default Text Header With TTL:
                value:
                  name: appointment_cancelled_txt_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: TEXT
                  headerText: Booking update for WA_1
                  headerExample: '["Deluxe Room"]'
                  bodyText: Hello WA_1, your appointment with WA_2 on WA_3 at WA_4 has been cancelled. Reply to rebook.
                  bodyExample: '[["John","Acme Clinic","31 Dec 2026","1:00 PM"]]'
                  footerText: Thank you!
                  buttonRequest: QUICK_REPLY:Rebook
                  timeToLive: '1800'
              Create Utility Text Header With Quick Reply:
                value:
                  name: order_status_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: TEXT
                  headerText: Order WA_1
                  headerExample: ORD-12345
                  bodyText: Hi WA_1, thank you for shopping with us. Your order has been confirmed and is now being prepared
                    for delivery. We will keep you posted.
                  bodyExample: '[["John"]]'
                  footerText: Thank you for shopping with us!
                  buttonRequest: QUICK_REPLY:Contact Support
              Create Utility No Header Multi Variable Body:
                value:
                  name: appointment_reminder_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, thank you for your order. Your order number WA_2 has been confirmed and our team is preparing
                    it for shipment. We will notify you once it is on the way.
                  bodyExample: '[["John","ORD-12345"]]'
                  footerText: Reply STOP to opt out
              Create Marketing Image Header With URL Buttons:
                value:
                  name: promo_image_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: IMAGE
                  headerFile: /path/to/banner.jpg
                  bodyText: Hi WA_1, enjoy WA_2 off this week!
                  bodyExample: '[["John","50%"]]'
                  footerText: Limited period offer
                  buttonRequest: URL:Track|https://example.com/track/WA_1|ORD123
              Create Marketing Video Header:
                value:
                  name: promo_video_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: VIDEO
                  headerFile: /path/to/promo.mp4
                  bodyText: Hi WA_1, watch our latest product launch above and explore the exciting new features and offers
                    we have prepared for you this season.
                  bodyExample: '[["John"]]'
                  buttonRequest: QUICK_REPLY:Interested
              Create Utility Document Header:
                value:
                  name: invoice_doc_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: DOCUMENT
                  headerFile: /path/to/invoice.pdf
                  bodyText: Hi WA_1, your invoice WA_2 is attached.
                  bodyExample: '[["John","INV-9001"]]'
              Create Utility Location Header:
                value:
                  name: store_location_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: LOCATION
                  bodyText: Hi WA_1, here is your nearest store.
                  bodyExample: '[["John"]]'
              Create Marketing Phone And URL Buttons:
                value:
                  name: cta_call_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, need help choosing? Call us or visit the store.
                  bodyExample: '[["John"]]'
                  buttonRequest: URL:Visit Store|https://example.com
              Create Marketing Copy Code Coupon:
                value:
                  name: coupon_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, here's your exclusive coupon.
                  bodyExample: '[["John"]]'
                  buttonRequest: COPY_CODE:Copy Code|SAVE20
              Create Marketing Catalog Button:
                value:
                  name: catalog_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CATALOG
                  headerFormat: NONE
                  bodyText: Hi WA_1, browse our full catalog.
                  bodyExample: '[["John"]]'
                  buttonRequest: CATALOG:View Catalog
              Create Marketing Multi Product Button:
                value:
                  name: mpm_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: TEXT
                  bodyText: Hi WA_1, browse our top products for this week and place your order easily using the button below.
                  bodyExample: '[["John"]]'
                  buttonRequest: MPM:View Products
                  headerText: Our Products
              Create Marketing Flow Button:
                value:
                  name: flow_signup_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, create your demo-tenant account in a few taps.
                  bodyExample: '[["John"]]'
                  buttonRequest: FLOW:Sign up|2160292237929090|navigate|WELCOME_SCREEN
              Create Utility Voice Call Button:
                value:
                  name: voice_call_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, tap to start a voice call with support.
                  bodyExample: '[["John"]]'
                  buttonRequest: VOICE_CALL:Call Support
              Create Utility Named Parameters:
                value:
                  name: named_params_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_NAME, your order WA_ORDER_ID ships on WA_DATE.
                  bodyExample: '[{"param_name":"name","example":"John"},{"param_name":"order_id","example":"ORD-12345"},{"param_name":"date","example":"12
                    Aug"}]'
              Create Authentication One Tap OTP:
                value:
                  name: otp_login_onetap_v1
                  languageType: en_US
                  category: AUTHENTICATION
                  templateType: OTP
                  headerFormat: NONE
                  deliveryMode: ONE_TAP
                  bodyExample: '[["123456"]]'
                  codeExpirationMinutes: '10'
                  addSecurityRecommendation: 'true'
                  showExpiryTime: 'true'
                  otpAutofillText: Autofill code
                  otpCopyText: Copy code
                  supportedApps: com.example.app|X1Y2Z3A4B5C
              Create Marketing Carousel:
                value:
                  name: carousel_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, check out our brand new collection now available with special launch offers just for
                    you.
                  bodyExample: '[["John"]]'
                  carouselCards[0].headerFormat: IMAGE
                  carouselCards[0].bodyText: Hi WA_1, these limited edition sneakers are now available at a special launch
                    price.
                  carouselCards[0].bodyExample[0]: John
                  carouselCards[0].buttonRequest[0]: QUICK_REPLY:Buy now
                  carouselCards[1].headerFormat: IMAGE
                  carouselCards[1].bodyText: Hi WA_1, complete your look with our matching premium accessories today.
                  carouselCards[1].bodyExample[0]: John
                  carouselCards[1].buttonRequest[0]: QUICK_REPLY:Buy now
                  carouselCards[0].headerFile: /path/to/card1.jpg
                  carouselCards[1].headerFile: /path/to/card2.jpg
              Create Marketing Limited Time Offer:
                value:
                  name: lto_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: IMAGE
                  headerFile: download.jpeg
                  bodyText: Hi WA_1, grab this deal before it ends!
                  bodyExample: '[["John"]]'
                  limitedTimeOfferText: Expiring soon!
                  limitedTimeOfferHasExpiration: 'true'
                  buttonRequest: URL:Shop Now|https://example.com/
              Create Marketing Catalog Template:
                value:
                  name: catalog_promo_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CATALOG
                  headerFormat: NONE
                  bodyText: Hi WA_1, browse our full catalog and order in a tap.
                  bodyExample: '[["John"]]'
                  footerText: Powered by BroadNet
                  buttonRequest: CATALOG:View Catalog
              Create Marketing Single Product Template:
                value:
                  name: spm_promo_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: PRODUCT
                  bodyText: Hi WA_1, take a look at this product and order in a tap.
                  bodyExample: '[["John"]]'
                  footerText: Powered by BroadNet
                  buttonRequest: SPM:View
              Create Marketing Calling Permission:
                value:
                  name: calling_permission_mkt_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: CALLING_PERMISSION
                  headerFormat: TEXT
                  headerText: Special offer for WA_1
                  headerExample: Deluxe Room
                  bodyText: Hi WA_1, our team from WA_2 would like to call you to share exclusive updates and offers. May
                    we reach you at WA_3 sometime today?
                  bodyExample: '[["John","BroadNet","+447700900125"]]'
                  footerText: Reply YES to allow the call
                  buttonRequest: QUICK_REPLY:OK
              Create Utility Calling Permission:
                value:
                  name: calling_permission_util_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_CALLING_PERMISSION
                  headerFormat: NONE
                  bodyText: Hi WA_1, our support team would like to call you regarding your recent order WA_2 to assist you
                    better. Would that be okay with you?
                  bodyExample: '[["John","ORD-12345"]]'
                  buttonRequest: QUICK_REPLY:Allow
              Create Authentication Zero Tap:
                value:
                  name: otp_login_zerotap_v1
                  languageType: en_US
                  category: AUTHENTICATION
                  templateType: OTP
                  headerFormat: NONE
                  deliveryMode: ZERO_TAP
                  bodyExample: '[["123456"]]'
                  codeExpirationMinutes: '10'
                  addSecurityRecommendation: 'true'
                  showExpiryTime: 'true'
                  otpAutofillText: Autofill code
                  supportedApps: com.acme.app|K8a/AINcGX7
              Create Authentication Copy Code:
                value:
                  name: otp_login_copycode_v1
                  languageType: en_US
                  category: AUTHENTICATION
                  templateType: OTP
                  headerFormat: NONE
                  deliveryMode: COPY_CODE
                  bodyExample: '[["123456"]]'
                  codeExpirationMinutes: '10'
                  addSecurityRecommendation: 'true'
                  showExpiryTime: 'true'
                  otpCopyText: Copy code
              Create Marketing Copy Code And Quick Reply:
                value:
                  name: multi_button_v1
                  languageType: en_US
                  category: MARKETING
                  templateType: DEFAULT
                  headerFormat: NONE
                  bodyText: Hi WA_1, thanks for shopping with us!
                  bodyExample: '[["John"]]'
                  buttonRequest: QUICK_REPLY:Opt In
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                id: '4040025016134845'
                name: catalog_promo_vl218827
                language: en
                category: MARKETING
                status: PENDING
                qualityRating: null
                templateType: CATALOG
                timeToLive: 0
                headerContentJson: null
                bodyText: Hi {{WA_1}}, browse our full catalog and order in a tap.
                footerText: null
                bodyExampleJson: '[["John"]]'
                buttonsJson: '[{"label":"View catalog","type":"CATALOG"}]'
                username: demo-tenant
                createdAt: '2026-09-09 14:05:00'
                updatedAt: '2026-09-09 14:05:00'
    get:
      tags:
      - WhatsApp
      summary: Get Template Details
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get WhatsApp Template Details

        Retrieve detailed information for a specific WhatsApp template by name.

        **Notes for this request**

        Full details for one template by name.

        **Endpoint** `GET /template`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `name` | query | yes | Name (unique per tenant) |

        **Request body** `multipart/form-data` — every field is documented in **7.0 Field Reference — Template Object**.

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_template
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: broadnet_omni_channel
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Delete Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete WhatsApp Template

        Permanently deletes a WhatsApp template using its name.

        **Notes for this request**

        Permanently delete a template by name.

        ⚠️ Destructive — set `name` to a template YOU created (e.g. from 5.01/5.02), not a production one.

        **Endpoint** `DELETE /template`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `name` | query | yes | Name (unique per tenant) |

        **Request body** `multipart/form-data` — every field is documented in **7.0 Field Reference — Template Object**.

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_template
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: order_status_v1
      responses:
        '200':
          description: OK
  /whatsapp/template/list:
    get:
      tags:
      - WhatsApp
      summary: Get Template List
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get WhatsApp Template List

        Fetches all templates belonging to the logged-in user.

        **Notes for this request**

        Lists the tenant's templates. Optional filters (enable in Params): `name` (contains), `status` (APPROVED/PENDING/REJECTED/PAUSED), `language`, `category`, `createdFrom`/`createdTo` (ISO local date-time) interpreted in `toGmt`; sorting via `sortBy`/`sortDirection`.

        **Endpoint** `GET /template/list`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `sortBy` | query | no | sortBy field |
        | `sortDirection` | query | no | sortBy direction |

        **Request fields** (form / query, `TemplateFilterRequest`)

        | Field | Type |
        |---|---|
        | `name` | `String` |
        | `status` | `String` |
        | `language` | `String` |
        | `category` | `Category` |
        | `category.value` | `String` |
        | `createdFrom` | `LocalDateTime` |
        | `createdTo` | `LocalDateTime` |
        | `toGmt` | `String` |
        | `page` | `Integer` |
        | `size` | `Integer` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_template_list
      parameters:
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: name
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: ascending
      - name: name
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
        example: APPROVED
      - name: language
        in: query
        required: false
        schema:
          type: string
        example: en_US
      - name: category
        in: query
        required: false
        schema:
          type: string
        example: MARKETING
      - name: createdFrom
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-01T00:00:00'
      - name: createdTo
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-30T23:59:59'
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
        example: '%2B05:30'
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '200'
      responses:
        '200':
          description: OK
  /whatsapp/template/grouped-by-category:
    get:
      tags:
      - WhatsApp
      summary: Get Templates Grouped By Category
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get Approved Templates Grouped by Category

        Returns lightweight template data (id and name only) grouped by category (MARKETING, UTILITY, AUTHENTICATION). Only APPROVED templates are returned. Optimized for dropdown selection with minimal data transfer.

        **Notes for this request**

        Approved templates (id+name) grouped by MARKETING / UTILITY / AUTHENTICATION — for dropdowns.

        **Endpoint** `GET /template/grouped-by-category`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Approved templates grouped successfully. |
        | 404 | No approved templates found. |
        | 500 | Internal server error. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_template_grouped_by_category
      responses:
        '200':
          description: OK
  /whatsapp/template/update/{WA_TEMPLATE_ID}:
    put:
      tags:
      - WhatsApp
      summary: Update Template
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update WhatsApp Template

        Updates an existing WhatsApp template using multipart/form-data. Supports header media upload, header/body/footer text, examples, and button list updates.

        **Notes for this request**

        ### Update an existing template (PUT /template/update/{templateId}, multipart). Meta permits editing body/header/buttons/footer of an APPROVED template; category/name are fixed.

        **Endpoint** `PUT /template/update/{templateId}`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `multipart/form-data` — every field is documented in **7.0 Field Reference — Template Object**.

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Template updated successfully. |
        | 400 | Invalid input data. |
        | 404 | Template not found. |
        | 500 | Internal server error. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: put_whatsapp_template_update_WA_TEMPLATE_ID
      parameters:
      - name: WA_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_TEMPLATE_ID
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                languageType:
                  type: string
                category:
                  type: string
                templateType:
                  type: string
                headerFormat:
                  type: string
                bodyText:
                  type: string
                bodyExample:
                  type: string
                footerText:
                  type: string
                buttonRequest:
                  type: string
            examples:
              Update Template:
                value:
                  name: order_status_v1
                  languageType: en_US
                  category: UTILITY
                  templateType: UTILITY_DEFAULT
                  headerFormat: NONE
                  bodyText: 'Hi WA_1, your order WA_2 status: WA_3. Track anytime.'
                  bodyExample: '[["John","ORD-12345","out for delivery"]]'
                  footerText: Thank you for your business!
                  buttonRequest: QUICK_REPLY:Track Order
      responses:
        '200':
          description: OK
  /whatsapp/template/compare:
    get:
      tags:
      - WhatsApp
      summary: Compare Templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Compare template performance

        Compares delivery and read performance of exactly two templates (base templateId versus one templateIds value) over an optional start–end range; ids or names are accepted.

        **Notes for this request**

        Compare performance of two templates over a time window.

        **Endpoint** `GET /template/compare`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `templateId` | query | yes | Local template id / Meta hsm id |
        | `templateIds` | query | yes | Template id(s)/name(s) to compare with |
        | `start` | query | no | Unix seconds |
        | `end` | query | no | Unix seconds |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_template_compare
      parameters:
      - name: templateId
        in: query
        required: false
        schema:
          type: string
        example: WA_TEMPLATE_ID
      - name: templateIds
        in: query
        required: false
        schema:
          type: string
        example: <other_template_id>
      - name: start
        in: query
        required: false
        schema:
          type: string
        example: <unix_ts>
      - name: end
        in: query
        required: false
        schema:
          type: string
        example: <unix_ts>
      responses:
        '200':
          description: OK
  /whatsapp/template/migrate:
    post:
      tags:
      - WhatsApp
      summary: Migrate Templates
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Migrate templates from another WABA

        Copies message templates from a source WABA into the caller's WhatsApp Business Account, one optional page at a time.

        **Notes for this request**

        Copy approved templates from another WABA into this one.

        **Endpoint** `POST /template/migrate`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `sourceWabaId` | query | yes | WABA to copy from |
        | `pageNumber` | query | no | Meta migration page |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_template_migrate
      parameters:
      - name: sourceWabaId
        in: query
        required: false
        schema:
          type: string
        example: <source_waba_id>
      - name: pageNumber
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
  /whatsapp/template/library:
    post:
      tags:
      - WhatsApp
      summary: Create Template From Library
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a template from Meta's Template Library

        Creates a template from one of Meta's prebuilt Template Library entries, skipping manual authoring for supported use cases.

        **Notes for this request**

        Create a template from Meta's pre-approved Template Library (library_template_name).

        **Endpoint** `POST /template/library`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_template_library
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                category:
                  type: string
                language:
                  type: string
                library_template_name:
                  type: string
                library_template_button_inputs:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      url:
                        type: object
                        properties:
                          base_url:
                            type: string
                          url_suffix_example:
                            type: string
            examples:
              Create Template From Library:
                value:
                  name: order_confirmation_2
                  category: UTILITY
                  language: en_US
                  library_template_name: order_confirmation
                  library_template_button_inputs:
                  - type: URL
                    url:
                      base_url: https://www.example.com/order/{{WA_1}}
                      url_suffix_example: https://www.example.com/order/12345
      responses:
        '200':
          description: OK
  /whatsapp/template/refresh:
    post:
      tags:
      - WhatsApp
      summary: Refresh Template Status
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Refresh a template's status/category from Meta

        Force a live re-sync of status and category from Meta (use when a status webhook may have been missed).

        **Notes for this request**

        Force a live re-sync of a template's status/category from Meta (use when a status webhook may have been missed).

        **Endpoint** `POST /template/refresh`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `name` | query | yes | Name (unique per tenant) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_template_refresh
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: broadnet_omni_channel
      responses:
        '200':
          description: OK
  /whatsapp/template/by-id/{WA_TEMPLATE_ID}:
    get:
      tags:
      - WhatsApp
      summary: Get Template By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a single template by its id

        Retrieves one template live from Meta by its numeric template id (hsm_id), bypassing the local database mirror.

        **Endpoint** `GET /template/by-id/{templateId}`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `templateId` | path | yes | Local template id / Meta hsm id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_template_by_id_WA_TEMPLATE_ID
      parameters:
      - name: WA_TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_TEMPLATE_ID
      responses:
        '200':
          description: OK
  /whatsapp/template/by-id:
    delete:
      tags:
      - WhatsApp
      summary: Delete Template By Id
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a template by id (hsm_id) — not every language of a name

        Deletes only the single language variant identified by hsm_id, instead of removing every language that shares a template name.

        **Endpoint** `DELETE /template/by-id`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `hsmId` | query | yes | Meta template id (hsm_id) |
        | `name` | query | no | Name (unique per tenant) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_template_by_id
      parameters:
      - name: hsmId
        in: query
        required: false
        schema:
          type: string
        example: WA_TEMPLATE_ID
      - name: name
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/template/namespace:
    get:
      tags:
      - WhatsApp
      summary: Get Template Namespace
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get the WABA's message-template namespace

        Returns the message-template namespace of the caller's WhatsApp Business Account, used when sending templates through the raw Cloud API.

        **Endpoint** `GET /template/namespace`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_template_namespace
      responses:
        '200':
          description: OK
  /whatsapp/message/all-bulk:
    post:
      tags:
      - WhatsApp
      summary: Get All Bulk Messages
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get All Bulk Messages

        **Notes for this request**

        Paginated batch list. Optional filters (enable as needed): `search`, `status`, `campaignType`, `campaignName`, `messageType`, `active`, `scheduled`, date ranges `createdFrom/To`, `updatedFrom/To`, `scheduleTimeFrom/To`, `recurrenceEndTimeFrom/To` (ISO local date-time) interpreted in `toGmt`, plus `page`, `size`, `sortBy`, `sortDir`.

        **Endpoint** `POST /message/all-bulk`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Request fields** (form / query, `BatchProcessFilterRequest`)

        | Field | Type |
        |---|---|
        | `page` | `int` |
        | `size` | `int` |
        | `sortBy` | `String` |
        | `sortDir` | `String` |
        | `search` | `String` |
        | `status` | `String` |
        | `campaignType` | `String` |
        | `campaignName` | `String` |
        | `messageType` | `MessageType` |
        | `messageType.value` | `String` |
        | `active` | `Boolean` |
        | `scheduled` | `Boolean` |
        | `createdFrom` | `LocalDateTime` |
        | `createdTo` | `LocalDateTime` |
        | `updatedFrom` | `LocalDateTime` |
        | `updatedTo` | `LocalDateTime` |
        | `scheduleTimeFrom` | `LocalDateTime` |
        | `scheduleTimeTo` | `LocalDateTime` |
        | `recurrenceEndTimeFrom` | `LocalDateTime` |
        | `recurrenceEndTimeTo` | `LocalDateTime` |
        | `toGmt` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_message_all_bulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                page:
                  type: string
                size:
                  type: string
                search:
                  type: string
                status:
                  type: string
                campaignType:
                  type: string
                campaignName:
                  type: string
                messageType:
                  type: string
                active:
                  type: string
                scheduled:
                  type: string
                createdFrom:
                  type: string
                createdTo:
                  type: string
                updatedFrom:
                  type: string
                updatedTo:
                  type: string
                scheduleTimeFrom:
                  type: string
                scheduleTimeTo:
                  type: string
                recurrenceEndTimeFrom:
                  type: string
                recurrenceEndTimeTo:
                  type: string
                toGmt:
                  type: string
                sortBy:
                  type: string
                sortDir:
                  type: string
            examples:
              Get All Bulk Messages:
                value:
                  page: '0'
                  size: '10'
                  search: ''
                  status: ACTIVE
                  campaignType: ''
                  campaignName: COMMON
                  messageType: TEMPLATE
                  active: 'true'
                  scheduled: 'false'
                  createdFrom: '2026-09-01T00:00:00'
                  createdTo: '2026-09-30T23:59:59'
                  updatedFrom: ''
                  updatedTo: ''
                  scheduleTimeFrom: ''
                  scheduleTimeTo: ''
                  recurrenceEndTimeFrom: ''
                  recurrenceEndTimeTo: ''
                  toGmt: +05:30
                  sortBy: batchId
                  sortDir: DESC
      responses:
        '200':
          description: OK
  /whatsapp/message/edit:
    get:
      tags:
      - WhatsApp
      summary: Get Batch Details
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Edit a Batch Entry

        Retrieve details of an existing batch entry for editing or inspection.
        🔹 **Usage Example**
        `GET /whatsapp-sms/edit?batch_Id=123`

        **Notes for this request**

        Needs a real batchId (from a prior send response) in the URL — {{WA_BATCH_ID}}=0 returns 404.

        **Endpoint** `GET /message/edit`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `batch_Id` | query | yes | Batch id returned by a send |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Batch entry retrieved successfully |
        | 400 | Invalid batch ID or username |
        | 404 | Batch not found for this user. Body: ExceptionResponse. |
        | 500 | Internal server error |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_message_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_BATCH_ID
      responses:
        '200':
          description: OK
  /whatsapp/message/pause:
    get:
      tags:
      - WhatsApp
      summary: Pause Batch
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Pause Batch Processing

        Temporarily pause processing of a batch entry.
        🔹 **Usage Example**
        `GET /whatsapp-sms/pause?batch_Id=123`

        **Notes for this request**

        Needs a real batchId — {{WA_BATCH_ID}}=0 returns 404.

        **Endpoint** `GET /message/pause`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `batch_Id` | query | yes | Batch id returned by a send |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Batch paused successfully |
        | 400 | Invalid batch ID or already paused |
        | 404 | Batch not found for this user. Body: ExceptionResponse. |
        | 500 | Internal server error |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_message_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_BATCH_ID
      responses:
        '200':
          description: OK
  /whatsapp/message/resume:
    get:
      tags:
      - WhatsApp
      summary: Resume Batch
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Resume Paused Batch Entry

        Resume processing of a previously paused batch entry.
        🔹 **Usage Example**
        `GET /whatsapp-sms/resume?batch_Id=123`

        **Notes for this request**

        Needs a real batchId — {{WA_BATCH_ID}}=0 returns 404.

        **Endpoint** `GET /message/resume`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `batch_Id` | query | yes | Batch id returned by a send |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Batch resumed successfully |
        | 400 | Invalid batch ID or batch not paused |
        | 404 | Batch not found for this user. Body: ExceptionResponse. |
        | 500 | Internal server error |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_message_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_BATCH_ID
      responses:
        '200':
          description: OK
  /whatsapp/message/abort:
    delete:
      tags:
      - WhatsApp
      summary: Abort Batch
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Abort Batch Entry

        Permanently stop processing of a batch entry. This action cannot be undone.
        🔹 **Usage Example**
        `DELETE /whatsapp-sms/abort?batch_Id=123`

        **Notes for this request**

        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists

        **Endpoint** `DELETE /message/abort`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `batch_Id` | query | yes | Batch id returned by a send |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Batch aborted successfully |
        | 400 | Invalid batch ID or already completed |
        | 404 | Batch not found for this user. Body: ExceptionResponse. |
        | 500 | Internal server error |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: delete_whatsapp_message_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_BATCH_ID
      responses:
        '200':
          description: OK
  /whatsapp/message/bulk-insights:
    get:
      tags:
      - WhatsApp
      summary: Bulk Insights (per batch)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Retrieve Bulk Message Insights

        Fetch detailed delivery and response insights for a specific WhatsApp bulk batch.

        **Notes for this request**

        Delivery/response breakdown for one bulk batch: per-destination status with optional `search`, `destination`, `status` (SENT/DELIVERED/READ/FAILED) filters.

        **Endpoint** `GET /message/bulk-insights`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `batch_Id` | query | yes | Batch id returned by a send |
        | `search` | query | no | Free-text search |
        | `destination` | query | no |  |
        | `status` | query | no | Filter by status |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Bulk insights retrieved successfully. |
        | 400 | Invalid batch ID or request parameters. |
        | 404 | Bulk batch not found. |
        | 500 | Internal server error. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_message_bulk_insights
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_BATCH_ID
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: destination
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/pricing:
    post:
      tags:
      - WhatsApp
      summary: '[operator]  Create Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Create Pricing

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `POST /pricing`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `application/json` — `PricingRequest`

        | Field | Type |
        |---|---|
        | `countryCode` | `String` |
        | `countryName` | `String` |
        | `marketingRate` | `BigDecimal` |
        | `utilityRate` | `BigDecimal` |
        | `authenticationRate` | `BigDecimal` |
        | `serviceRate` | `BigDecimal` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_pricing
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                countryCode:
                  type: string
                countryName:
                  type: string
                currency:
                  type: string
                marketingRate:
                  type: number
                utilityRate:
                  type: number
                authenticationRate:
                  type: number
                serviceRate:
                  type: number
                userInitiatedRate:
                  type: number
            examples:
              '[operator]  Create Pricing':
                value:
                  countryCode: '1'
                  countryName: United States
                  currency: USD
                  marketingRate: 0.026
                  utilityRate: 0.015
                  authenticationRate: 0.012
                  serviceRate: 0.008
                  userInitiatedRate: 0.005
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get All Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get All Pricing

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `GET /pricing`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `search` | query | no | Search keyword (matches countryCode or countryName) |
        | `page` | query | no | Page number (0-based) (default `0`) |
        | `size` | query | no | Page size (default `10`) |
        | `sortBy` | query | no | Sort field (default `countryName`) |
        | `sortDir` | query | no | Sort direction: asc or desc (default `asc`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_pricing
      parameters:
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: countryName
      - name: sortDir
        in: query
        required: false
        schema:
          type: string
        example: asc
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    put:
      tags:
      - WhatsApp
      summary: '[operator] Update Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update Pricing

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `PUT /pricing`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `countryCode` | query | yes | Dial country code (e.g. 1, 91, 272) |

        **Request body** `application/json` — `PricingRequest`

        | Field | Type |
        |---|---|
        | `countryCode` | `String` |
        | `countryName` | `String` |
        | `marketingRate` | `BigDecimal` |
        | `utilityRate` | `BigDecimal` |
        | `authenticationRate` | `BigDecimal` |
        | `serviceRate` | `BigDecimal` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: put_whatsapp_pricing
      parameters:
      - name: countryCode
        in: query
        required: false
        schema:
          type: string
        example: '1'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                countryCode:
                  type: string
                countryName:
                  type: string
                marketingRate:
                  type: number
                utilityRate:
                  type: number
                authenticationRate:
                  type: number
            examples:
              '[operator] Update Pricing':
                value:
                  countryCode: '1'
                  countryName: United States
                  marketingRate: 0.03
                  utilityRate: 0.018
                  authenticationRate: 0.015
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    delete:
      tags:
      - WhatsApp
      summary: '[operator] Delete Pricing'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete Pricing

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `DELETE /pricing`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `countryCode` | query | yes | Dial country code (e.g. 1, 91, 272) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_pricing
      parameters:
      - name: countryCode
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/pricing/country:
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get Pricing by Country'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get Pricing by Country

        **Notes for this request**

        ⚠️ ADMIN endpoint — requires the super/admin token ({{SUPER_TOKEN}}). A business-user token (demo-tenant) returns 401.

        **Endpoint** `GET /pricing/country`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `countryCode` | query | yes | Dial country code (e.g. 1, 91, 272) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_pricing_country
      parameters:
      - name: countryCode
        in: query
        required: false
        schema:
          type: string
        example: '1'
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/qr-links:
    post:
      tags:
      - WhatsApp
      summary: Create QR Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create QR Link

        **Notes for this request**

        `qrName` is a query parameter (unique per tenant). Body keys are snake_case as in Meta's API: `prefilled_message` (≤512) and optional `generate_qr_image` = `PNG` | `SVG`.

        **Endpoint** `POST /qr-links`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `qrName` | query | yes | Unique QR name per tenant |

        **Request body** `application/json` — `CreateQrRequest`

        | Field | Type |
        |---|---|
        | `prefilled_message` | `String` |
        | `generate_qr_image` | `QrImageFormat` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: post_whatsapp_qr_links
      parameters:
      - name: qrName
        in: query
        required: false
        schema:
          type: string
        example: My Link
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                prefilled_message:
                  type: string
                generate_qr_image:
                  type: string
            examples:
              Create QR Link:
                value:
                  prefilled_message: Hi, I would like more information.
                  generate_qr_image: PNG
      responses:
        '200':
          description: OK
    get:
      tags:
      - WhatsApp
      summary: Get All QR Links
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get All QR Links

        **Endpoint** `GET /qr-links`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `code` | query | no | Meta-generated QR code / verification code |
        | `displayNumber` | query | no | Display phone number filter |
        | `prefilledMessage` | query | no | Prefilled message filter |
        | `startDate` | query | no | ISO date-time |
        | `endDate` | query | no | ISO date-time |
        | `toGmt` | query | no | Offset `±HH:mm` for the date filters |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `20`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_qr_links
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: code
        in: query
        required: false
        schema:
          type: string
      - name: displayNumber
        in: query
        required: false
        schema:
          type: string
      - name: prefilledMessage
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
      - name: endDate
        in: query
        required: false
        schema:
          type: string
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
    put:
      tags:
      - WhatsApp
      summary: Update QR Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update QR Link

        **Endpoint** `PUT /qr-links`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Request body** `application/json` — `UpdateQrRequest`

        | Field | Type |
        |---|---|
        | `prefilled_message` | `String` |
        | `code` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: put_whatsapp_qr_links
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                prefilled_message:
                  type: string
            examples:
              Update QR Link:
                value:
                  code: L64EB45CVAUKO1
                  prefilled_message: Updated prefilled message for QR scan
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Delete QR Link
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete QR Link

        **Endpoint** `DELETE /qr-links`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `code` | query | yes | Meta-generated QR code / verification code |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_qr_links
      parameters:
      - name: code
        in: query
        required: false
        schema:
          type: string
        example: L64EB45CVAUKO1
      responses:
        '200':
          description: OK
  /whatsapp/qr-links/bycode:
    get:
      tags:
      - WhatsApp
      summary: Get QR by Code
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get QR by Code

        **Notes for this request**

        Needs a real QR code from a prior create (8.1) — placeholder returns 404.

        **Endpoint** `GET /qr-links/bycode`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `code` | query | yes | Meta-generated QR code / verification code |
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_qr_links_bycode
      parameters:
      - name: code
        in: query
        required: false
        schema:
          type: string
        example: L64EB45CVAUKO1
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
  /whatsapp/flow/create:
    post:
      tags:
      - WhatsApp
      summary: 11.21.1 Create Flow — SIGN_UP
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a new flow on Meta

        Creates a flow under the tenant's WABA. Optionally uploads the flow JSON and publishes it in the same call. Refuses if the account is currently blocked by compliance.

        **Notes for this request**

        Step 1 — creates a DRAFT flow in category `SIGN_UP`. The returned `flowId` is stored in `{{WA_FLOW_ID}}` by the collection test script.

        **Endpoint** `POST /flow/create`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Request body** `application/json` — `CreateFlowRequest`

        | Field | Type |
        |---|---|
        | `name` | `String` |
        | `categories` | `List<String>` |
        | `endpointUri` | `String` |
        | `cloneFlowId` | `String` |
        | `flowJson` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 201 | Flow created (may include uploaded/published flags). |
        | 400 | Bad request or compliance block in effect. |
        | 404 | Account not onboarded. |
        | 500 | Meta API call failed. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_flow_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                categories:
                  type: array
                  items:
                    type: string
            examples:
              11.21.1 Create Flow — SIGN_UP:
                value:
                  name: Student Registration
                  categories:
                  - SIGN_UP
              11.22.1 Create Flow — SIGN_IN:
                value:
                  name: User Login
                  categories:
                  - SIGN_IN
              11.23.1 Create Flow — APPOINTMENT_BOOKING:
                value:
                  name: Appointment Booking
                  categories:
                  - APPOINTMENT_BOOKING
              11.24.1 Create Flow — LEAD_GENERATION:
                value:
                  name: Pre-Approved Loan Lead
                  categories:
                  - LEAD_GENERATION
              11.25.1 Create Flow — SHOPPING:
                value:
                  name: Product Shopping Flow
                  categories:
                  - SHOPPING
              11.26.1 Create Flow — CONTACT_US:
                value:
                  name: Contact Us Form
                  categories:
                  - CONTACT_US
              11.27.1 Create Flow — CUSTOMER_SUPPORT:
                value:
                  name: Customer Support Triage
                  categories:
                  - CUSTOMER_SUPPORT
              11.28.1 Create Flow — SURVEY:
                value:
                  name: Customer Feedback Survey
                  categories:
                  - SURVEY
              11.29.1 Create Flow — INSURANCE_QUOTE:
                value:
                  name: Health Insurance Quote
                  categories:
                  - OTHER
              Create Flow:
                value:
                  name: Appointment Booking Flow
                  categories:
                  - APPOINTMENT_BOOKING
                  endpointUri: https://api.broadnet.me/whatsapp/flow/endpoint
                  cloneFlowId: ''
                  flowJson: ''
              Create Flow (inline flowJson — create + upload in one call):
                value:
                  name: Sign-Up Flow (one-shot)
                  categories:
                  - SIGN_UP
                  endpointUri: '{{WA_FLOW_ENDPOINT_URI}}'
                  flowJson: '{"version": "7.2", "data_api_version": "3.0", "routing_model": {"WELCOME": ["DONE"], "DONE":
                    []}, "screens": [{"id": "WELCOME", "title": "Welcome", "layout": {"type": "SingleColumnLayout", "children":
                    [{"type": "TextHeading", "text": "Create your account"}, {"type": "Form", "name": "f", "children": [{"type":
                    "TextInput", "name": "full_name", "label": "Full name", "required": true}, {"type": "Footer", "label":
                    "Continue", "on-click-action": {"name": "navigate", "next": {"type": "screen", "name": "DONE"}, "payload":
                    {"full_name": "${form.full_name}"}}}]}]}}, {"id": "DONE", "title": "Done", "terminal": true, "layout":
                    {"type": "SingleColumnLayout", "children": [{"type": "TextHeading", "text": "Thanks!"}, {"type": "Footer",
                    "label": "Finish", "on-click-action": {"name": "complete", "payload": {}}}]}}]}'
              Create Flow (clone an existing flow):
                value:
                  name: Appointment Booking Flow v2
                  categories:
                  - APPOINTMENT_BOOKING
                  cloneFlowId: '{{WA_FLOW_ID}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                flowId: '1234567890123456'
                username: demo-tenant
                name: User Registration
                status: DRAFT
                categories: '["SIGN_UP"]'
                wabaId: '1232158482181795'
                jsonVersion: null
                dataApiVersion: '3.0'
                endpointUri: null
                validationErrorsJson: '[]'
                createdAt: '2026-09-09 14:05:00'
  /whatsapp/flow/{WA_FLOW_ID}/upload:
    post:
      tags:
      - WhatsApp
      summary: 11.21.2 Upload Flow JSON
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Upload (or replace) the flow JSON definition

        Body is the raw Flow JSON in Meta's flow definition format. Stays in DRAFT until publish. Refuses if the account is blocked by compliance.

        **Notes for this request**

        WITHOUT ENDPOINT — Static SIGN_UP flow. 3 screens: Register → OTP Verify → Success

        Flow JSON version 7.2. Screens: REGISTER, OTP_VERIFY, SUCCESS. First screen `REGISTER` is the `flowScreen` used by the Send step.

        **Endpoint** `POST /flow/{flowId}/upload`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Request body** raw JSON (forwarded as-is).

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Flow JSON uploaded successfully. |
        | 400 | Invalid JSON or compliance block. |
        | 404 | Flow / account not found. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_flow_WA_FLOW_ID_upload
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                version:
                  type: string
                routing_model:
                  type: object
                  properties:
                    REGISTER:
                      type: array
                      items:
                        type: string
                    OTP_VERIFY:
                      type: array
                      items:
                        type: string
                    SUCCESS:
                      type: array
                      items: {}
                screens:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      title:
                        type: string
                      data:
                        type: object
                      layout:
                        type: object
                        properties:
                          type:
                            type: string
                          children:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                src:
                                  type: string
                                width:
                                  type: integer
                                height:
                                  type: integer
                                scale-type:
                                  type: string
                                aspect-ratio:
                                  type: number
            examples:
              11.21.2 Upload Flow JSON:
                value:
                  version: '7.2'
                  routing_model:
                    REGISTER:
                    - OTP_VERIFY
                    OTP_VERIFY:
                    - SUCCESS
                    SUCCESS: []
                  screens:
                  - id: REGISTER
                    title: Create Account
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: /9j/4AAQSkZJRgABAQAAAQABAAD/2wC<meta-token-redacted>/AABEIAKgBLAMBEQACEQEDEQH/xAAbAAACAgMBAAAAAAAAAAAAAAACBAMFAAEGB//EAFEQAAIABAMDBwYKBwYDCAMAAAECAAMRIQQSMQVBURMiYXGBkaEGMkKxwdEUI1JicoKSorLwBxVTc8LS4TNDk6Pi8SRjgzRUpLO0w9PUJWR0/8QAGgEAAgMBAQAAAAAAAAAAAAAAAQIAAwQFBv/EAEERAAEDAQQHBwIEBQMDBQ<meta-token-redacted>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
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Create your account
                      - type: TextBody
                        text: Fill in your details to get started.
                      - type: Form
                        name: register_form
                        children:
                        - type: TextInput
                          name: full_name
                          label: Full name
                          input-type: text
                          required: true
                          helper-text: Enter your full name
                        - type: TextInput
                          name: email
                          label: Email address
                          input-type: email
                          required: true
                          helper-text: e.g. you@email.com
                        - type: TextInput
                          name: phone
                          label: Phone number
                          input-type: phone
                          required: true
                        - type: TextInput
                          name: password
                          label: Password
                          input-type: password
                          required: true
                          helper-text: Min 8 characters
                        - type: OptIn
                          name: terms_agreed
                          label: I agree to the Terms & Conditions
                          required: true
                        - type: Footer
                          label: Create Account
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: OTP_VERIFY
                            payload:
                              full_name: ${form.full_name}
                              email: ${form.email}
                              phone: ${form.phone}
                  - id: OTP_VERIFY
                    title: Verify OTP
                    data:
                      full_name:
                        type: string
                        __example__: John Doe
                      email:
                        type: string
                        __example__: john@email.com
                      phone:
                        type: string
                        __example__: '9876543210'
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Verify your number
                      - type: TextBody
                        text: Enter the 6-digit OTP sent to your phone.
                      - type: Form
                        name: otp_form
                        children:
                        - type: TextInput
                          name: otp_code
                          label: OTP Code
                          input-type: passcode
                          required: true
                          helper-text: Enter 6-digit OTP
                        - type: Footer
                          label: Verify & Continue
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: SUCCESS
                            payload:
                              full_name: ${data.full_name}
                              email: ${data.email}
                  - id: SUCCESS
                    title: Welcome!
                    terminal: true
                    data:
                      full_name:
                        type: string
                        __example__: John Doe
                      email:
                        type: string
                        __example__: john@email.com
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Account Created!
                      - type: TextBody
                        text: Welcome! Your account has been created successfully.
                      - type: TextCaption
                        text: Name
                      - type: TextBody
                        text: John Doe
                      - type: Footer
                        label: Get Started
                        on-click-action:
                          name: complete
                          payload:
                            full_name: ${data.full_name}
                            email: ${data.email}
              11.22.2 Upload Flow JSON:
                value:
                  version: '7.2'
                  routing_model:
                    LOGIN:
                    - LOGIN_SUCCESS
                    LOGIN_SUCCESS: []
                  screens:
                  - id: LOGIN
                    title: Sign In
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: iVBORw0KGgoAAAANSUhEUgAAAj<meta-token-redacted>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
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Welcome back!
                      - type: TextBody
                        text: Sign in to your account to continue.
                      - type: Form
                        name: login_form
                        children:
                        - type: TextInput
                          name: email
                          label: Email address
                          input-type: email
                          required: true
                        - type: TextInput
                          name: password
                          label: Password
                          input-type: password
                          required: true
                        - type: Footer
                          label: Sign In
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: LOGIN_SUCCESS
                            payload:
                              email: ${form.email}
                  - id: LOGIN_SUCCESS
                    title: Signed In
                    terminal: true
                    data:
                      email:
                        type: string
                        __example__: user@email.com
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: You are signed in!
                      - type: TextBody
                        text: Welcome back. You have successfully logged in to your account.
                      - type: Footer
                        label: Continue
                        on-click-action:
                          name: complete
                          payload:
                            email: ${data.email}
              11.23.2 Upload Flow JSON:
                value:
                  version: '7.2'
                  routing_model:
                    SELECT_SERVICE:
                    - SELECT_SLOT
                    SELECT_SLOT:
                    - BOOKING_CONFIRM
                    BOOKING_CONFIRM: []
                  screens:
                  - id: SELECT_SERVICE
                    title: Book Appointment
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: /9j/4AAQSkZJRgABAQEBLAEsAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAO8BRQDASIAAhEBAxEB/8QAHAAAAgMBAQEBAAAAAAAAAAAAAAIBAwQFBgcI/8QAWBAAAgEDAQMGCgUHCQUHAwQDAAECAwQRBRIhMQYTQVFhcQcUIjJScoGRscEzQpKh0RUWI1NigtIXJDRDVHOTorI1RIPC4SU2Y3R1s/AmN/EIRUdkhsSj/8QAGgEBAQEBAQEBAAAAAAAAAAAAAAECAwQFBv/EADARAQ<meta-token-redacted>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<meta-token-redacted>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<meta-token-redacted>+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
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Book an Appointment
                      - type: TextBody
                        text: Choose a service and we will find the best available slot for you.
                      - type: Form
                        name: service_form
                        children:
                        - type: RadioButtonsGroup
                          name: service_type
                          label: Select a service
                          required: true
                          data-source:
                          - id: consultation
                            title: General Consultation
                            description: 30 min · ₹ 500
                          - id: followup
                            title: Follow-up Visit
                            description: 20 min · ₹ 300
                          - id: specialist
                            title: Specialist Consult
                            description: 45 min · ₹ 1200
                        - type: TextInput
                          name: patient_name
                          label: Patient name
                          input-type: text
                          required: true
                        - type: TextInput
                          name: contact_number
                          label: Contact number
                          input-type: phone
                          required: true
                        - type: Footer
                          label: Choose Date & Time
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: SELECT_SLOT
                            payload:
                              service_type: ${form.service_type}
                              patient_name: ${form.patient_name}
                              contact_number: ${form.contact_number}
                  - id: SELECT_SLOT
                    title: Select Date & Time
                    data:
                      service_type:
                        type: string
                        __example__: consultation
                      patient_name:
                        type: string
                        __example__: Jane Doe
                      contact_number:
                        type: string
                        __example__: '9876543210'
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Choose your slot
                      - type: Form
                        name: slot_form
                        children:
                        - type: DatePicker
                          name: appointment_date
                          label: Appointment date
                          required: true
                        - type: RadioButtonsGroup
                          name: time_slot
                          label: Available time slots
                          required: true
                          data-source:
                          - id: slot_nine
                            title: 9:00 AM
                          - id: slot_eleven
                            title: 11:00 AM
                          - id: slot_two
                            title: 2:00 PM
                          - id: slot_four
                            title: 4:00 PM
                        - type: Footer
                          label: Confirm Booking
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: BOOKING_CONFIRM
                            payload:
                              service_type: ${data.service_type}
                              patient_name: ${data.patient_name}
                              contact_number: ${data.contact_number}
                              appointment_date: ${form.appointment_date}
                              time_slot: ${form.time_slot}
                  - id: BOOKING_CONFIRM
                    title: Booking Confirmed
                    terminal: true
                    data:
                      service_type:
                        type: string
                        __example__: consultation
                      patient_name:
                        type: string
                        __example__: Jane Doe
                      contact_number:
                        type: string
                        __example__: '9876543210'
                      appointment_date:
                        type: string
                        __example__: '2025-06-15'
                      time_slot:
                        type: string
                        __example__: slot_nine
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Booking Confirmed!
                      - type: TextCaption
                        text: Patient
                      - type: TextBody
                        text: Jane Doe
                      - type: TextCaption
                        text: Service
                      - type: TextBody
                        text: General Consultation
                      - type: TextCaption
                        text: Date
                      - type: TextBody
                        text: June 15, 2025
                      - type: TextCaption
                        text: Time
                      - type: TextBody
                        text: 9:00 AM
                      - type: TextBody
                        text: We will send a reminder 1 hour before your appointment.
                      - type: Footer
                        label: Done
                        on-click-action:
                          name: complete
                          payload:
                            service_type: ${data.service_type}
                            patient_name: ${data.patient_name}
                            appointment_date: ${data.appointment_date}
                            time_slot: ${data.time_slot}
              11.24.3 Upload Flow JSON:
                value:
                  version: '7.2'
                  data_api_version: '3.0'
                  routing_model:
                    PERSONAL_INFO:
                    - LOAN_OFFER
                    LOAN_OFFER:
                    - LEAD_SUCCESS
                    LEAD_SUCCESS: []
                  screens:
                  - id: PERSONAL_INFO
                    title: Check Your Offer
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: data:image/png;base64,YOUR_BASE64_HERE
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Check your pre-approved offer
                      - type: TextBody
                        text: Fill in your details and we will show you your personalised loan offer instantly.
                      - type: Form
                        name: info_form
                        children:
                        - type: TextInput
                          name: full_name
                          label: Full name
                          input-type: text
                          required: true
                        - type: TextInput
                          name: pan_number
                          label: PAN number
                          input-type: text
                          required: true
                          helper-text: e.g. ABCDE1234F
                        - type: TextInput
                          name: monthly_income
                          label: Monthly income (₹)
                          input-type: text
                          required: true
                        - type: Dropdown
                          name: employment_type
                          label: Employment type
                          required: true
                          data-source:
                          - id: salaried
                            title: Salaried
                          - id: selfemployed
                            title: Self Employed
                          - id: business
                            title: Business Owner
                        - type: Footer
                          label: Check My Offer
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: LOAN_OFFER
                            payload:
                              full_name: ${form.full_name}
                              pan_number: ${form.pan_number}
                              monthly_income: ${form.monthly_income}
                              employment_type: ${form.employment_type}
                  - id: LOAN_OFFER
                    title: Your Offer
                    data:
                      full_name:
                        type: string
                        __example__: Sam Lee
                      pan_number:
                        type: string
                        __example__: ABCDE1234F
                      monthly_income:
                        type: string
                        __example__: '75000'
                      employment_type:
                        type: string
                        __example__: salaried
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Your pre-approved offer
                      - type: TextCaption
                        text: Loan amount
                      - type: TextBody
                        text: Up to ₹ 10,00,000
                      - type: TextCaption
                        text: Interest rate
                      - type: TextBody
                        text: Starting at 10.5% p.a.
                      - type: TextCaption
                        text: Tenure
                      - type: TextBody
                        text: Up to 60 months
                      - type: Form
                        name: offer_form
                        children:
                        - type: Dropdown
                          name: desired_amount
                          label: How much do you need?
                          required: true
                          data-source:
                          - id: two_lakh
                            title: ₹ 2,00,000
                          - id: five_lakh
                            title: ₹ 5,00,000
                          - id: ten_lakh
                            title: ₹ 10,00,000
                        - type: Footer
                          label: Apply Now
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: LEAD_SUCCESS
                            payload:
                              full_name: ${data.full_name}
                              desired_amount: ${form.desired_amount}
                  - id: LEAD_SUCCESS
                    title: Application Submitted
                    terminal: true
                    data:
                      full_name:
                        type: string
                        __example__: Sam Lee
                      desired_amount:
                        type: string
                        __example__: five_lakh
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Application Submitted!
                      - type: TextBody
                        text: Thank you! Our team will call you within 24 hours to complete the process.
                      - type: Footer
                        label: Done
                        on-click-action:
                          name: complete
                          payload:
                            full_name: ${data.full_name}
                            desired_amount: ${data.desired_amount}
              11.25.3 Upload Flow JSON:
                value:
                  version: '7.2'
                  data_api_version: '3.0'
                  routing_model:
                    CATEGORY_SELECT:
                    - PRODUCT_LIST
                    PRODUCT_LIST:
                    - CHECKOUT
                    CHECKOUT:
                    - ORDER_PLACED
                    ORDER_PLACED: []
                  screens:
                  - id: CATEGORY_SELECT
                    title: Shop
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: data:image/png;base64,YOUR_BASE64_HERE
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: What are you looking for?
                      - type: Form
                        name: category_form
                        children:
                        - type: RadioButtonsGroup
                          name: category
                          label: Browse by category
                          required: true
                          data-source:
                          - id: phones
                            title: Mobile Phones
                          - id: laptops
                            title: Laptops
                          - id: accessories
                            title: Accessories
                          - id: tablets
                            title: Tablets
                        - type: Footer
                          label: Browse Products
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: PRODUCT_LIST
                            payload:
                              category: ${form.category}
                  - id: PRODUCT_LIST
                    title: Products
                    data:
                      category:
                        type: string
                        __example__: phones
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Top picks for you
                      - type: Form
                        name: product_form
                        children:
                        - type: RadioButtonsGroup
                          name: selected_product
                          label: Select a product
                          required: true
                          data-source:
                          - id: prod_alpha
                            title: Alpha Pro X
                            description: ₹ 32,999 · In stock
                          - id: prod_beta
                            title: Beta Ultra S
                            description: ₹ 45,499 · In stock
                          - id: prod_gamma
                            title: Gamma Lite Max
                            description: ₹ 18,999 · Limited stock
                        - type: Footer
                          label: Add to Cart
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: CHECKOUT
                            payload:
                              category: ${data.category}
                              selected_product: ${form.selected_product}
                  - id: CHECKOUT
                    title: Checkout
                    data:
                      category:
                        type: string
                        __example__: phones
                      selected_product:
                        type: string
                        __example__: prod_alpha
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Complete your order
                      - type: Form
                        name: checkout_form
                        children:
                        - type: TextInput
                          name: delivery_address
                          label: Delivery address
                          input-type: text
                          required: true
                        - type: RadioButtonsGroup
                          name: payment_method
                          label: Payment method
                          required: true
                          data-source:
                          - id: upi
                            title: UPI
                          - id: cod
                            title: Cash on Delivery
                          - id: card
                            title: Credit / Debit Card
                        - type: Footer
                          label: Place Order
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: ORDER_PLACED
                            payload:
                              selected_product: ${data.selected_product}
                              delivery_address: ${form.delivery_address}
                              payment_method: ${form.payment_method}
                  - id: ORDER_PLACED
                    title: Order Confirmed
                    terminal: true
                    data:
                      selected_product:
                        type: string
                        __example__: prod_alpha
                      delivery_address:
                        type: string
                        __example__: 123 Main St
                      payment_method:
                        type: string
                        __example__: upi
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Order Placed!
                      - type: TextBody
                        text: Your order has been placed successfully. You will receive a confirmation shortly.
                      - type: TextCaption
                        text: Estimated delivery
                      - type: TextBody
                        text: 3-5 business days
                      - type: Footer
                        label: Track Order
                        on-click-action:
                          name: complete
                          payload:
                            selected_product: ${data.selected_product}
                            payment_method: ${data.payment_method}
              11.26.2 Upload Flow JSON:
                value:
                  version: '7.2'
                  routing_model:
                    CONTACT_FORM:
                    - CONTACT_THANKS
                    CONTACT_THANKS: []
                  screens:
                  - id: CONTACT_FORM
                    title: Contact Us
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: /9j/4AAQSkZJRgABAQEBLAEsAAD/4QCJRXhpZgAASUkqAAgAAAADAA4BAgA/AAAAMgAAABoBBQABAAAAcQAAABsBBQABAAAAeQAAAAAAAABDb250YWN0IHVzIGJ1dHRvbiB3aXRoIGN1cnNvci4gUG9pbnRlciBjbGljay4gVmVjdG9yIHdlYiBidXR0b24sAQAAAQAAACwBAAABAAAA/+EFr2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyI+Cgk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgoJCTxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6SXB0YzR4bXBDb3JlPSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wQ29yZS8xLjAveG1sbnMvIiAgIHhtbG5zOkdldHR5SW1hZ2VzR0lGVD0iaHR0cDovL3htcC5nZXR0eWltYWdlcy5jb20vZ2lmdC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBsdXM9Imh0dHA6Ly9ucy51c2VwbHVzLm9yZy9sZGYveG1wLzEuMC8iICB4bWxuczppcHRjRXh0PSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wRXh0LzIwMDgtMDItMjkvIiB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9yaWdodHMvIiBwaG90b3Nob3A6Q3JlZGl0PSJHZXR0eSBJbWFnZXMiIEdldHR5SW1hZ2VzR0lGVDpBc3NldElEPSIxNDUyNzcxNTUxIiB4bXBSaWdodHM6V2ViU3RhdGVtZW50PSJodHRwczovL3d3dy5pc3RvY2twaG90by5jb20vbGVnYWwvbGljZW5zZS1hZ3JlZW1lbnQ/dXRtX21lZGl1bT1vcmdhbmljJmFtcDt1dG1fc291cmNlPWdvb2dsZSZhbXA7dXRtX2NhbXBhaWduPWlwdGN1cmwiIHBsdXM6RGF0YU1pbmluZz0iaHR0cDovL25zLnVzZXBsdXMub3JnL2xkZi92b2NhYi9ETUktUFJPSElCSVRFRC1FWENFUFRTRUFSQ0hFTkdJTkVJTkRFWElORyIgPgo8ZGM6Y3JlYXRvcj48cmRmOlNlcT48cmRmOmxpPlZlY3RvclVwPC9yZGY6bGk+PC9yZGY6U2VxPjwvZGM6Y3JlYXRvcj48ZGM6ZGVzY3JpcHRpb24+PHJkZjpBbHQ+PHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Db250YWN0IHVzIGJ1dHRvbiB3aXRoIGN1cnNvci4gUG9pbnRlciBjbGljay4gVmVjdG9yIHdlYiBidXR0b248L3JkZjpsaT48L3JkZjpBbHQ+PC9kYzpkZXNjcmlwdGlvbj4KPHBsdXM6TGljZW5zb3I+PHJkZjpTZXE+PHJkZjpsaSByZGY6cGFyc2VUeXBlPSdSZXNvdXJjZSc+PHBsdXM6TGljZW5zb3JVUkw+aHR0cHM6Ly93d3cuaXN0b2NrcGhvdG8uY29tL3Bob3RvL2xpY2Vuc2UtZ20xNDUyNzcxNTUxLT91dG1fbWVkaXVtPW9yZ2FuaWMmYW1wO3V0bV9zb3VyY2U9Z29vZ2xlJmFtcDt1dG1fY2FtcGFpZ249aXB0Y3VybDwvcGx1czpMaWNlbnNvclVSTD48L3JkZjpsaT48L3JkZjpTZXE+PC9wbHVzOkxpY2Vuc29yPgoJCTwvcmRmOkRlc2NyaXB0aW9uPgoJPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0idyI/Pgr/7QCGUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAGocAVoAAxslRxwCUAAIVmVjdG9yVXAcAngAP0NvbnRhY3QgdXMgYnV0dG9uIHdpdGggY3Vyc29yLiBQb2ludGVyIGNsaWNrLiBWZWN0b3Igd2ViIGJ1dHRvbhwCbgAMR2V0dHkgSW1hZ2Vz/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8IAEQgBlAJkAwERAAIRAQMRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAFBgIDBAH/xAAaAQEAAgMBAAAAAAAAAAAAAAAABAUBAgMG/9oADAMBAAIQAxAAAAG5gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcZmRpNg4yPPQAAAAAAAAAAAAAAAAAAAAAeAmDYAAAAAAAAAAACHOk7CCO0kwatuejpxxzgMjA8AAAAPGAAGQAA8DAAAA8AyBgBjOzTpH8pHTjaVAAAAAAAAAABFHhJEAWEyI+RCiZtby9Y7IAAAAAAAAAAAAAAAAAAAAAZa7ZxpvdBtJ3XoAAAAAAAAAABXiwHmdYGxp4+TCAAAAAAAAAAAAAAAAAAAAAAAA5+Pex1l5K69AAAAAAAAAAIs6DrYr1nS8MiGAAAAAAAAAAAAAAAAAAAAAAAABwxZt1h2XTykAAAAAAAAACCJ0i5dfB2FQAN3PrJxJ4jJcDT05dseV3R5mnpyi5df5nEhGm567RkqB18ZOzXfHON+nUDh7xB3cJenfnwyIYz12k4lht16R8iFv59smQIuVXspCLNx214ZETvjTPDhkw+vhJkI83TtyjJcDHbUDm5duvn2ttbdesgAAAAAAAAQZNsVa389p6cgNmnS0VPoPcZxzrHyYXFIi2Gsu9e3PZrvwSYdfsqWzVN/1cpFatKGQjTenn35uvCQizduvTR04wVhUdXGRNQbXVtzqlx5wWWrvurjI1b89e2g38+3pp351i28/5nFnqPQaunOu2dHZqm/w21hJ9TZ6m/0dOOWNq3aUWnpyAHBHlXGHZd3CWAAAAAAAABBkl1j1m2oABLwrKYg2lXtvP6t+bOLDWXe/n2q1v56Zg2krDsqrcecsNZd9XKRGSoGG2nVykVu0opSHYTkC3qVz5vDbSxVd5njbr4yavbee2a9LJV3sDYU8bKgbNd9e+lirLzPTetW1ABZ6j0GrpzrtnR2apv8ADbWOkwZ6vuKtb+e078vM4AA4I8qx8+05AtwAAAAAAAAIM65MGAsqYAT9bc9fGTVbjzoFqp/RcvWPX7Ol7o0yxVt3XLOimYNrljO3TrHSoPRz7Vu0opSHYTkC3qVz5vHOtspvSQs+pm6+3hLCp9wnIFvVLjzmrfmBYqy8z03rVtQAWeo9Bq6c67Z0dmqb/DbWDsKizVN/jnWGn1UbKggAcEeVOM2OsvAAAAAAAAAII65UGBsaYATtdcd8eXU7nzgFpqPQ6N+VdtKOQizbBXXVatKGbgW3H3jSMaaw0deNbtKKUh2E5At6lc+b38+tmqr+AsaaYg2nL2j8XeJPV9xVrfz2jpxAsVZeZ6b1q2oALPUeg1b867aUdmqb/DbWuWlFv59ZmBbcEeZDWNNukwss4GrTpq13l9OljrLwAAAAAAAACCJDtGrlrQgCSizp6uuYKwqNO/HT05y8KykI02u2dJLQrLs4yancecslXe8feL5nEvCs+PvFrdpRSkOwnIFvUrnzcnEnzMG1w20yxnDOtbtKK0VPoYyXXxkuvz134+8WxVl5npvWragAsdXe7+fWvWVLY6y84u8SDsKjq4yWM76270WNLC76Y4yY3b8+npxlIlhOQLcAAAAAAAADWQjHDc+cw20A9xmxVl328JYi5dfEzK2y1V9t16eMQk+pi5lfZqm/5O8aKl11pqPQ8neNW7SilIdhOQLepXPm5+tudmu9ZtqCUh2E5At6tbeekos6Xh2Y5usesWtBYq28z03rVtQAd8aZYK269ZxzrXLSj6uMibgWwru/POZWyEWw4+8TkkRIvOurXafhWdg4yQAAAAAAAABGkLOq9c2sADDr4yWXJ1jMstduvjI09OWjpyGzTfzOMNtdunTxjXvplrtnjbVtz269PM417aZYznrvhtpjnHRy77Nd+XtGxzjZpuNe+gA3c+u/n25uvDXvzHTy7567w+M9+/OxVd8BjnWM7xso0ydxn0AAAAAAAAAEXnWtWFR0yoIAAAAAAAAAAAAAAAAAAAAAA8xni4ybZBtd/PsOU4GZlj06tdgAAAAAAAAAObOtRm1nP14b9+W3fn6DwAAAA8DIADAeAABkAeAAAYDxkADDG2OM4a72Hl3k4dngcxxszLHRrnJkAAAAAAAAAAY51iJtbCyIXPjbwAA9AAADHoGQAA9ADAAA9GQABgegGWddu2nFxkyWUpWXkZjO7LuY5tcz7IAAAAAAAAAAAGOdePtG5+vHzOoAYAyAPQAAAGfQMAAAB6GQAAAPcAZ2c+sLxk9OUrnHOzH4d+ccmuZ9kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTnGvOOjXbQQmcd+ca9dpkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgPQc5CZxL5x0YzsxkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeGnOM8NjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8QALRAAAQQBAgQGAgIDAQAAAAAAAwABAgQUEhMQERU0BSAhMjNAIzEiUCVgoDX/2gAIAQEAAQUC/wCSWyQgggOOyKx/6vA9oFZs2wZbXiU1h2lhWFhWFg2Fg2FgnWCdYJ1gnWCZYBlgGWAZYBVgFWAVYBV08i6eRdPIunkXT5rp810+a6dNdOkunSXTpLpzrpzrpzrprrpq6aumrpq6aumrprLpjLpjLpjLp5IrR4kJN4ltvGcSR+xKpMdolfXclJoRyLF1wUAAfhIkIp7QWWWFZgVmBWYFZgVmBWYFZgVmBWYFZgVmBWYFZglmCWYJZglmCWaJZolmiWaJZolmiWaJZolmiWaJZolmiWaJZolmiWaJZolmiWcJZwlnCWcNZw1miWSCbSpaHrXdyf1i1TEIKoeBJziOEIT8TkzMzItuEFOyWf8AXNJ4uWTWIUbrzl9ef+Rt/pO7RY9pyf2RR62o3WtC+rfO4K1Wu1aurJ92X9m7vXtAKxofUl+fxdXC6Y+QYpldqLJ6DIgpidCqzKsGKnRkydnZ1CpIkMGfJBryMxKkhwFWkWGDNYM1gzRRuKYxuWeDNEqyHDhGLzeFF09GKLXmJNSm7YM1gzWDPjCnKcC1ZCgoVJEgSrIcEKtMqwYqdF1KLxfjYhrBSscm+p4d/MqLPcJxHByThBhxlKMWiSE1cK2mqHdmnJCLq0HXBVu3VmGg1H2Wu3qEhEMSQnw3hK1JpGox9USOsfCuFhQ58kxRyc5WEOJxaWk0md2i2+JP+0D4Lnbqt29vtwD3S/pTOOD7sNBSOWfkqekKk9Yfp+E9pYlpB5KMfVGK5SRk8Xd3k9SOkBZ7Y3d3ekTnwLHQWt26uw5joe2126o+9T96qR0gMTSRHjoNVjqOrhXkRSnKfCn29nt+IPguduq3b2+3o/KjReJefmr/ACUZfk+n4X6Du/B5KXwl9A8RfFc+BU+4VvuK3bznoJJtUabaVa7dUfep+/8AbxbTG5P87Pza9HkSj8iL6l40+3s9vxB8Fzt1W7e324SbRIyaTTHEjHqPBvLV9VU7j6YPw+K3fh8lF/xEbUPiF+Ybbc66pNzOrT87Fbt73ow57g2jyna7dUfep++tHUdGAaZg82FdjzDRf8qM2k3Gn29nt+IPgt9uq3b2+3QzTE4rcZqN6yWM7It1nZ+JZ6BVo6AVO4+n4izilY5EreSlPSRWKsmmOqSciicU6U+YpM0ozqljKsHahJ9MZPqlW7e/7aM+Frt1R96n76MfVa4JnZ0SOsYZ7ZVaruRRrlk567h4U+3s9vxqy51yw3B45dUI6IXZcgxi85FqkGgAlMnhbvEV1mmd6sOfKzBZTRT7diCox/J9OcWnClJwznHRPi3o4LDFbhcnDQIjinAkSR4WrGvhW7e97BT2yq126o+9T99SOkFmWkCoy/mjx0Gq2W5cDzhEap9vZ7fjVPtS/fB3aLWDb06TjZ+Bp4filaWoshxkpVIqVYjKdUbvtHgvDzu0vqXKuRBzb/mayaKeyaXGMni+WZTMQnFiTZnnKXDcInJN2TSeK3ScNybJ5zlwZ3i+6RO7ydQOWCe2Z07vJ005szkm7eSBZjWWZSJOfGNgsE9ozq5qkMBP5cXi0lZauCFSBJn+rcpRstrmGf8AXO3Nqr8oClqFwsWIVhgrzKRN+/qnAOwMtM9SWTpUbApLVFamWqK1RWqK1RWqK1xWuK1xWuK1xWuC1wWuC1wW5BbkFuQW5BbkFuQW5Bbg1ujW6Nbo1ujW6Nbo1ujW6Nbo1vDW8JbwlvCW8JbwlvCW8Jbwk9kLKNmM5P8AjuVJcHnGL2a8LI69mcCM3NM3L67s0mLSRK8eeKBYgFiAWKBYoFigWKBYoFigWKBYoFigWKFYoVjBWMFYwVjBWMFYwVjBWMFYwVjhWOFY4VjhWOFY4VjhWOFY4VjhWwFbAVsBWwJbAlsCWwJbAlsCTDg3C034q8+c7NmFaDUXssCxMRLFeFkdWzMRPsuzSaVQUk9GKwFgLAWAywGWAywGWAywGWAywGWAywGWAywGWBFYEVgRWBFYMVgxWDFYMVgxWDFYMVgxWDBYMFgwWDBYMFgwWDBYMFgwWDBYMFgwWCNYI1gjWGHlXsSoir1Z7iNXhaGIxKxTghYHXtTAT/R5pm5pm5I4B2RDKSoWwMRQ+FlmSn/pRgjsCfw0jpm0tF+f+mPFRjy/4Pv/xAAzEQABAwIEBQQBAwQCAwAAAAABAAIDBBQQERJREyExM1IgMkBBIiNQYRVCYnFDoHKBof/aAAgBAwEBPwH/AKvTpGN6lGrhH2ryHdXkO6vId1eQq8iV5EryJXkSvYlexK9iV7Er2JXsSvYlexK9iV7Er2JXsSvYlexK9iV7Er2JX0SvolfRK+iV9Er6JX0SvolfRK+iV9Gr6NX0avo1fRq+jV9Gm1cR+0HB3T50tYxnIc1JUyP+/wBuDi3mFFWuHv5pkjZBm35RIaMyp6oycm9P3KCYxOzQeCcvk1NRxDkOn7pE4ujyHVvMKCYStz+PWzaRoH36Y4nyHJqbQD7KdQD6KkidGcnYRUr5Of0rBu6fQuHtKIIORwjo3PbqBRoX74Q07pRmFJSOjbqJUVK6VuoFWD91YP3Vg/dSxmN2kqKMyO0hWD91LSOjbqxa0uOQTKA/3FGgb9FS0z4uf0hQvP2rB+6sH7qwfviyjc9odmpaV0bdROEdG57dQKkpHRt1E4Q0z5ef0hQN3T6A/wBpTmlpyPogfokBTXW852+PK/W8u9EbC92kJjAxukJzmt5lNkY/2lVsoy0Klh4jsz0GDpGNOROFXDrbqHUYU3aGFVHokKoPaVV9kqklY2PIlNkY72nDjx+Sq3B0mYVA3mXYSN1MIxp4RE3+UTl1QmjccgVUSiNnNNnjy9ya4OGYRIAzK48Xkj1wp+01VnZOFN2QqvslQR8SQBdE+eNhycVxWadWfJTSmR2o+mq5uDtwqR+qP/Xxal2mIn00DOZdhNKZH5pri05hElxzKpG6YgpX6GFyJJOZVDJnmw4St0PIVN2hhXR5s1bKg9pVX2ThQe44P9xwo26YlNJpewYTt0yEKlZqlGFbKS7Rtg97n+7Cj7IVV2T6KftNVZ2ThTdkKr7JVD3DhM0tkOaz9VR7Wf6VA78iPi1x/S9ND21Mco3eiLthVvawou7hV94qm7QT5NL2jdObqGRVE3TqBVX2ThQe44P9xQGaa3S0BVr/ANUfwgcxmq5uTw5UHvOEpzefRR9kKq7J9FP2mqs7JwpuyFV9kqGThvDk1wcMwnxteMnBT0hZ+TenqqeWkfwqPvD4td2/TQn9MhSDUwj0QHONqrBnEcKIZy54VRzmKpu0FX8g1RP1sDkGZOJ3VX2ThQe44P8AcVTN1SjCaCV8hOShBEYDlWtzjz2VCf1CMJxpkI9FH2Qqrsn0U/aaqzsnCm7IVX2ThHM+P2qCqbLyPXCaleHEtHJEEdcY263hqqHapSVR94fFqm5xH00Uml+nfCopXB2piipZHnmMlNEYnZFUT82adk5ocMin0sjTkAqWDhN59U4hozKc7Uc1TdoKv9oVDJ1ZhV9k4UHuOD/cVQN5l2Gtm6BB6KRuphChfw5AcKunL/yam08rjlkp6Yxc8KPshVXZPopHZxBSs4jC1W0ueWSY3Q0NVc7KPJMaXu0hS0j2dOapoXmQHLCreeN+KFS/o7ms4H9RkrYn2HNDiQuzywoG/mT8UjMZJ7dLi0+gHLmqeoEoyPXGtezTp+1FKYnago5GyDNuNXU6vwbhTdoKv9oUL+G8Owq+ycKD3HB/uKo26YlUu0xHCgd+RbhO3TIQqWpGWh+M72NZ+eFH2Qqrsn0Us/DOR6IHPBzg0ZlVE3Fd/CojGDz64yP0NLlRu1SEnqnxMf7gn0LT7SnUkrUJ5Wcj/wDVxIX+5uX+lTRtYz8fv41dF/yD1NqpW/adVSu+8WuLTmFdzbp80j/ccRI8cgUXud1OHFfujI88icA4t6FcWTywErx9ovc7qcASOYXFk8kSTzODKiRnQo1cx+0XFxzOAkeOQKMjzyJ9LJXs9pV5NunyPf7ji2olb0KNXMftU785MnfaiPCl5+hzQ7qnUcZ6fHIDhkVPSOZzZ0/bwcuaqRm4PH2oH64wfmOGYUwaD+qP/YVvq7bs0YJW9QtLtlpK0laStJ2Wl2y0u2Wl2y0O2Wh2y0O2Wh2y0O2Wh2y0O2Wh2y0O2XDfsuG/ZcN+y4b9lw37Lhv2XDfsuG/ZcN+y4b9lwn7LhP2XCfsuE/ZcKTZcKTZcKTZcKTxXCk8VwpPFcGTxXBk8VwZPFcGTxXBk8UKeU/2p1O5ozcUPzg/8VQv6t+a5ocMipaH7jWqWPlmQrmbdXU26upt1dTbq6m3VzNurmbdXMu6uZd1cy7q5l8lcy+SuZfJXMvkrmXyVzL5K4l8lcS+SuJfJXEvkriXyVxL5K4l8lcS+SuJfJXEvkriXyXHl8lx5fJceXyXHl8lx5fJceXyXHl8lx5fJceXyXHk8lxpPJcaTyXGk8lxpPJcaTyRkeepwpj+ek/ahzZN88tDuqdRxFGgb9Ff0/wDyX9P/AMl/Tx5KwHkrAeSsB5KwHkrAeSsB5KwHkrAeSsB5KwG6sBurAbqwburBu6sG7qwburBu6sG7qwburBu6sG7qwburBu6sG7qwburBm6sGbqwZurBm6sGbqwZurBm6sGbqwZurBm6sGbqwZurBm6sY902kibzyWQH/AFLf/8QALh<meta-token-redacted>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<meta-token-redacted>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<meta-token-redacted>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<meta-token-redacted>/wC0AJLSW9tlKO3YWAAAAAAAAAAAQybbSktt2ybJAE3/APoACWkvtw6XgAAAAAAAAAAAA6Ekv7bJEm2wBJL/APYAEltbu2YRYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlwRwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAELoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8QAKx<meta-token-redacted>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<meta-token-redacted>/aAAgBAgEBPxD/AJes5GJ34FryWvJa8lryWvJa8lryWPJY8lhblhblhblhbnQ3OjudHc6O50dzonTOmdM6Z0zpnTOmdM6Z0y+i6vvYur72Lq+9i6vvYuL72Li+9i4vvYuL72Li+9i4vvYfMX3sc0DWEj52I4EZapd/05LCSY9gfgiz8pjwYmsvp+pIj10Ek9uj+RmL1B4/VFhlovroMj00+PyIXvhQS4+QfIIJejLUx6aDrhIEJLYUe3TwE1xDo6SSZEVU8SDzLwvC8Fx1SNeCyqamswIQlON4WuhgqwfIaHEi8LwvBOVR5dPAjtOjm6eAuKnjTBXi+Q58EGnEROiVwgLU9Y8jUfFWIlfBS99B7zhzCSZxIYlwS8j4czopljRkPl5PgkNzWB4x7XolzGoFExUTFKYjSQzzGlkHR4D7ayEm3CEcsgWIwS1JrEPYSGMaEll2LKnnmV3rPa9EymY225YhyBhWWLEqXhwcq2iUayePxYd9w4cLumYtCZ6j0jAQrIRJ2wLuiEhZCE0uudLyKsnH1pva9U8yniKk+uWBYhf7/FOiBNxrhREjN+qJmlimd24Z55ld6z2vRkdf7o8uQhTPF55PyD+Ksztwth6CSi64Gll2JPa6JLdqNPc90k5Wahj1JoJjao9r1TzKeIhtJSxzm1MTOokmmStyv2PgXosKsuDO7cM88yu9Z7XomS9IxHcvAxy3xY1zmFlu3v4rYun9cMCuxYhrgiF2RF6RR5ukVCIm1fIc59BjTST2vVPMp4iJ9zwo4AdmPgzrhEiu9Jhbgzu3DPPMrvWe16oghRDDGhZTQxCSnNbAkWf2R4bt7+L1xhwx66UZV0NGNEshYttj1JmiVNwxHLIcpM2LUmlZsVJ0p7XqnmU8RGH3aXmxmCgsgyOKKdEVzAkVk/4pnduGSlyH5RpA9r6k9hDBkIX4uHcUaUt0U1hg5HNLtrM0TSXwZHA70M3SrUj5h/FYyaEpXXgaTUMmSqwfh7DU5BGkSO5jSs8Ylzke16p5lPERLrlgR7vtSfladEB8tXVVTno1pnduGO1BDTTh0awSzBnm8xQoVTV8w3LCNEBHLJhbcdTAi7o5hs/7IMsRh8bDb9uFqcxxLDiUEoothJGx/wBmY/WbEtNjIyVG9y02GEoT6UwVJLDYSgb3LTYayhUQQklhsIISKNJBI/ISwkKjSUPsMJSbcOpxa8sQ4Yq2kEHIUpLGYQ+NVK4GstAgh4jTePxmKzEaUPx+ntJqGO07ZtHAA3Alq6P40ycxiXcfwyWf8kZEgn6l4vF4vF8ul0uououououoti2LTctNy03LTctNyw3LDcsNyw3LLcstyy3Lbctty23Lbctty23LbcsNyw3LDcsdyx3LHcsdy13GvNRUS3eMB4b0Tyj1FWpE+dG5+O1khiXg9xISkmNw+if/AEAkkkkFgWBYFgWZZlmW5bluW5bluW5blmWZZlnsWexZ7FnsW+xb7FrsWuxa7FrsWuwsgm1HYebSSTnNSNwROYnoxqRz8prLQa9PUWuhL8/8Jfn/AIS/P/CX5kvzJfmS/M+ln0s+ln0M+hn2Pikm1sWxbFsWxbFsWhaFoWhaFoWhaFoWhbFsWxbFsW0PkL73E8N4DZ4Ni50YmNDUfsk3A3NExkfsxY0aj9mJjc/8H3//xAAsEA<meta-token-redacted>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
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Get in touch
                      - type: TextBody
                        text: Fill in your query and we will get back to you within 24 hours.
                      - type: Form
                        name: contact_form
                        children:
                        - type: TextInput
                          name: full_name
                          label: Your name
                          input-type: text
                          required: true
                        - type: TextInput
                          name: email
                          label: Email address
                          input-type: email
                          required: true
                        - type: RadioButtonsGroup
                          name: query_type
                          label: What is your query about?
                          required: true
                          data-source:
                          - id: billing
                            title: Billing & Payments
                          - id: technical
                            title: Technical Issue
                          - id: general
                            title: General Enquiry
                          - id: partnership
                            title: Partnership
                        - type: TextInput
                          name: message
                          label: Your message
                          input-type: text
                          required: true
                          helper-text: Describe your query briefly
                        - type: RadioButtonsGroup
                          name: callback_time
                          label: Preferred callback time
                          required: true
                          data-source:
                          - id: morning
                            title: Morning (9am – 12pm)
                          - id: afternoon
                            title: Afternoon (12pm – 4pm)
                          - id: evening
                            title: Evening (4pm – 7pm)
                        - type: Footer
                          label: Send Message
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: CONTACT_THANKS
                            payload:
                              full_name: ${form.full_name}
                              query_type: ${form.query_type}
                              callback_time: ${form.callback_time}
                  - id: CONTACT_THANKS
                    title: Message Sent
                    terminal: true
                    data:
                      full_name:
                        type: string
                        __example__: Jane Doe
                      query_type:
                        type: string
                        __example__: general
                      callback_time:
                        type: string
                        __example__: morning
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Message received!
                      - type: TextBody
                        text: Thank you for reaching out. Our team will contact you during your preferred time slot.
                      - type: TextCaption
                        text: Reference number
                      - type: TextBody
                        text: REF-2025-00123
                      - type: Footer
                        label: Close
                        on-click-action:
                          name: complete
                          payload:
                            full_name: ${data.full_name}
                            query_type: ${data.query_type}
                            callback_time: ${data.callback_time}
              11.27.3 Upload Flow JSON:
                value:
                  version: '7.2'
                  data_api_version: '3.0'
                  routing_model:
                    ISSUE_TYPE:
                    - ISSUE_DETAIL
                    ISSUE_DETAIL:
                    - TICKET_RAISED
                    TICKET_RAISED: []
                  screens:
                  - id: ISSUE_TYPE
                    title: Support
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: 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<meta-token-redacted>+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<meta-token-redacted>/2gAIAQIBAT8AbsghHviCt3mxSERzIk+SxMbIsT48LExK2RWVhDysJkUQQh6abPTRVDaHhESOZjwkNEUVwV4RICymNifgh4gRWEsTZZG+jkshIi+MzHiPRQhPFFYREj4rKw8aZFFYSJwfsNOxRFG0ONCNN5mPEHlSExZRBCw2by7FibZp2N4s0iOERRRqQpiiVRJY0yyySscRo0uxoa4wvBdkF4bRZpFUvDTI4h2JcYcbHGiiURx5I0i8LlDQ4mmuR4aExclFCRD9sUISIdljYmNDRIfeEexHrDFwWWNcCQuByRLUSI6yshqRf7YiQ2Q7wyIxskyT5ELnF0WbizcRY9RIc2zcxtliZGbRH8hoj+T8i14sU4s3L9ECK4JI01zisN4mTlyRm0xMTJsvCVjjRZyLTbPSZKFYbxQi2KckaOo2+ReVGn2R6KNNK8svGpJIlyyNkW0hMmLClSHqEWmyMFRSG6RqTtl8YRZRQj8dWxeCEsaaI9Yh3l4ZridGkrYoigTiyhIaNpBckeiTpE5Nj8FmrPx4VzhMssRZZBCxpjwx41Ipo9O2RioqhUKVCkmOMR0jbZsZCDsXRtvgf46Zq6OwVDIxs0/x7XJ/FJfjNEdJ2QVIRRWEy3iAsQ4ZeLGMmxEVZtJ8IjqckpqhshJqItS3yb4xIzTI0KiempLk/iRP4aIfjKIlQhs9xMTLyjgZAWdxY5UjdYyTJS5ITZCdrkm7RymORG2y10R5ZJ8mmxSZpyfnLosTFITylnSfk+eDoZO26R6D+SOg17kY0bbJ6bTKNND05GnHauRwk2QVIhTEXStnrQPWh8nrQ+T1ofIpxl0yiUCSaIzdkWNkWWbjeaYsMZYiXIx9nI00WWe5KJHgcWvcr7K+xK/c0PcTJv8Aqx9kYtq7pH9PlkotK07Rof6IscxuzajoT8KIRoUkbkbkPnNjH2acluNXhl4SuxxYk/cb5aeErPpGj7m5EpLazuVDSlKn0iMlKVURacnFdGh/ojciyy8LNieLLLLLLLLJ9FkJqa2yPRd/RJUyMqPUIyt0Nc2X8iddCXujc02bmKTE6lZwpNP3NOKi+XyKoJ88kXTs9RnqG9m9imxTZ6jNzNzN7xZYvKfWVrSSobbdsqzaRXI5X7Fr4LXwKVex3hPkYp8VJWf8/slV8YvwWLEyy/BCZZeGyXPZX2V9lfZX2RdLDXBT+Sn8nPyU/khLajeWc/JbLZbIyp8m9G6yyyyyxMsvxT8WrKRRRQlhlFFFCXjRRWaKKzWK8bLLLL/ZZZeL8bL/AE//xAAmEQACAgEEAQUBAQEBAAAAAAAAAQIRAxASITEEEyAwQVFhIhQy/9oACAEDAQE/AIqiZI+tJulQhIoYyWsCKKGtGuBoooorSyT+JFCkSY2KbSo9Rl2Uyyyyx6w7FoxMk+Cyy/Yx/EtFIlIvSyCsoyNI3jyG4vWAmWNikN2S0sWrH7F7ktFIb4LGxyMeRWRaoyck+GJiYnpZBlm4b5Fo0PRPWT1SNhVawSMmi4KEz60ZJlmLJcSTJKxqhC0RB0NiZITIvkkSELWWqNxd6qTQ3fsWsuh6Rk0xStDZIRGN9Di0JFU9I9k+ixPk7RKJQtZd+1fBESGifQlyKKGhOi9IohHgcSMeSfYhEhISENG0UJPohgkyXjOieKSKr2L4IiZFJk+hdiJCRQokUQok6L5HyJFElwJCi/ohhb7FgSR6URQSK0cE+yXjJkvFH48kPHJG1r4EWQkZHwXyWdiWiMcVQ4WiT5rSC5KEhxsx4f0jiSKSHmgj/oiQyqXQyr04OCkPHFmbGkuB9+9cEnQmTboWiEhGODbIwpDVInTekOtLIumLKkS8l1wSzSkbmQi5Mw41FFaNe3yJUqHz7GXrIRLoWiExV9o8dx+irMtVRKI1RijZ6THjY4vSXWmONyox4kkJa9m0cSmtPInbrRooSHoloxEhaIWmObQs7oUnMcWek5MeKUGRyzRDdJXRJxumNIkq0Utrsj5jRgz+pq2kjL5W10hecR8xMlmjt4Ju2Nll6NFLWQiS4Fqr0iIUnHoWdnjZU3yZYKUTHiblyQVGXGp5Cfj1G4kcM5k8UoOmNDRiyvG7R/3MXn8GTy3JEm27ekexLgY0UVo9EMYho2lCjbFFISFGzHHglBUZIU+DDwxO4kI0Se1WRT7MktsOTFGkeSrHFE0vfHsS4Gihr3P2UULjk7WiIzo9VVVE7kR47MU+BGaQvIgjLlU2q6I58aRkyKTtGTgdiV8I9Gf4ejP8PRn+Hoz/AAeOUVbWkZkWmSxquBooaNrFE2+xEUUiQkNsw9nAmmUUTnspmPNGSMvMbFJP6L/hf8HKuaM74Q0Y1/tCXBKSTpcs/wB/iIyTdNUzNXpsSsUToU2djVe3azazaxQYlWjQlQ0YlyZE9vBh5Wuf/wAoi2jHkbW1kVwmI6K/TMuIlMhF7kWkrE9sb+2Si4xcrJWoKX2ZucbFBlMplMVj0rSiiijaUUUUUY+9JwcHuiLMmv6RdolG6PSPTUVZF8I6Ksv6ZScUbUUhq40cuMZL6MknJcLg5m1xwhq0bEbEbEbEbEemj00emjYj017ktaMa5K0eCLdiSSpD4Nw26FGvsp/pT/Rxv7OktV0PG73R4KyfwjurlnSODj4UtEUUUUUKKMbro3fw3fw3fw3fwk7LIy/huj+G6P4bo/ha/CdMURUXH8OPw/z+H+fwkk1SNhtNptKKKKKK+KLotlstlsvRMsssv2WWWXpZZZfy1qvhooSKKNpRtNptNptNpRXv/9k=
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: How can we help you?
                      - type: TextBody
                        text: Select your issue type and we will find the best solution for you.
                      - type: Form
                        name: issue_form
                        children:
                        - type: RadioButtonsGroup
                          name: issue_type
                          label: What is your issue?
                          required: true
                          data-source:
                          - id: order
                            title: Order & Delivery
                          - id: payment
                            title: Payment & Refund
                          - id: account
                            title: Account & Login
                          - id: product
                            title: Product Issue
                          - id: other
                            title: Something else
                        - type: TextInput
                          name: order_id
                          label: Order ID (if applicable)
                          input-type: text
                          required: false
                          helper-text: e.g. ORD-2025-12345
                        - type: Footer
                          label: Continue
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: ISSUE_DETAIL
                            payload:
                              issue_type: ${form.issue_type}
                              order_id: ${form.order_id}
                  - id: ISSUE_DETAIL
                    title: Describe Issue
                    data:
                      issue_type:
                        type: string
                        __example__: order
                      order_id:
                        type: string
                        __example__: ORD-2025-12345
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Tell us more
                      - type: Form
                        name: detail_form
                        children:
                        - type: TextInput
                          name: issue_description
                          label: Describe your issue
                          input-type: text
                          required: true
                          helper-text: Please give us as much detail as possible
                        - type: RadioButtonsGroup
                          name: urgency
                          label: How urgent is this?
                          required: true
                          data-source:
                          - id: low
                            title: Low — can wait a few days
                          - id: medium
                            title: Medium — need help today
                          - id: high
                            title: High — urgent
                        - type: Footer
                          label: Raise Ticket
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: TICKET_RAISED
                            payload:
                              issue_type: ${data.issue_type}
                              order_id: ${data.order_id}
                              issue_description: ${form.issue_description}
                              urgency: ${form.urgency}
                  - id: TICKET_RAISED
                    title: Ticket Raised
                    terminal: true
                    data:
                      issue_type:
                        type: string
                        __example__: order
                      order_id:
                        type: string
                        __example__: ORD-2025-12345
                      issue_description:
                        type: string
                        __example__: My order has not arrived
                      urgency:
                        type: string
                        __example__: medium
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Ticket Raised!
                      - type: TextBody
                        text: Your support ticket has been created. Our team will respond within 4 hours.
                      - type: TextCaption
                        text: Ticket number
                      - type: TextBody
                        text: TKT-2025-98765
                      - type: TextCaption
                        text: Expected response
                      - type: TextBody
                        text: Within 4 business hours
                      - type: Footer
                        label: Done
                        on-click-action:
                          name: complete
                          payload:
                            issue_type: ${data.issue_type}
                            urgency: ${data.urgency}
              11.28.2 Upload Flow JSON:
                value:
                  version: '7.2'
                  routing_model:
                    SURVEY_RATINGS:
                    - SURVEY_FEEDBACK
                    SURVEY_FEEDBACK:
                    - SURVEY_THANKS
                    SURVEY_THANKS: []
                  screens:
                  - id: SURVEY_RATINGS
                    title: Share Feedback
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: /9j/4AAQSkZJRgABAQAAAQABAAD/2wC<meta-token-redacted>/AABEIALEBHAMBIgACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAAFAQIDBAYABwj/xABU<meta-token-redacted>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
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: How was your experience?
                      - type: TextBody
                        text: Your feedback helps us improve. It will only take 2 minutes.
                      - type: Form
                        name: rating_form
                        children:
                        - type: RadioButtonsGroup
                          name: overall_rating
                          label: Overall experience
                          required: true
                          data-source:
                          - id: five
                            title: ⭐⭐⭐⭐⭐ Excellent
                          - id: four
                            title: ⭐⭐⭐⭐ Good
                          - id: three
                            title: ⭐⭐⭐ Average
                          - id: two
                            title: ⭐⭐ Poor
                          - id: one
                            title: ⭐ Very Poor
                        - type: RadioButtonsGroup
                          name: recommend
                          label: Would you recommend us?
                          required: true
                          data-source:
                          - id: definitely
                            title: Definitely
                          - id: probably
                            title: Probably
                          - id: not_sure
                            title: Not sure
                          - id: probably_not
                            title: Probably not
                        - type: Footer
                          label: Next
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: SURVEY_FEEDBACK
                            payload:
                              overall_rating: ${form.overall_rating}
                              recommend: ${form.recommend}
                  - id: SURVEY_FEEDBACK
                    title: More Details
                    data:
                      overall_rating:
                        type: string
                        __example__: five
                      recommend:
                        type: string
                        __example__: definitely
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: A little more detail
                      - type: Form
                        name: feedback_form
                        children:
                        - type: CheckboxGroup
                          name: liked_aspects
                          label: What did you like most?
                          required: false
                          data-source:
                          - id: speed
                            title: Fast service
                          - id: quality
                            title: Product quality
                          - id: support
                            title: Customer support
                          - id: price
                            title: Value for money
                          - id: ui
                            title: Easy to use
                        - type: TextInput
                          name: open_feedback
                          label: Any other comments?
                          input-type: text
                          required: false
                          helper-text: Optional — share anything else
                        - type: Footer
                          label: Submit Feedback
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: SURVEY_THANKS
                            payload:
                              overall_rating: ${data.overall_rating}
                              recommend: ${data.recommend}
                              liked_aspects: ${form.liked_aspects}
                              open_feedback: ${form.open_feedback}
                  - id: SURVEY_THANKS
                    title: Thank You!
                    terminal: true
                    data:
                      overall_rating:
                        type: string
                        __example__: five
                      recommend:
                        type: string
                        __example__: definitely
                      liked_aspects:
                        type: array
                        items:
                          type: string
                        __example__:
                        - speed
                        - quality
                      open_feedback:
                        type: string
                        __example__: Great experience!
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Thank you for your feedback!
                      - type: TextBody
                        text: Your response has been recorded. We really appreciate you taking the time to share your thoughts.
                      - type: Footer
                        label: Close
                        on-click-action:
                          name: complete
                          payload:
                            overall_rating: ${data.overall_rating}
                            recommend: ${data.recommend}
              11.29.3 Upload Flow JSON:
                value:
                  version: '7.2'
                  data_api_version: '3.0'
                  routing_model:
                    PROFILE_INFO:
                    - COVER_CHOICE
                    COVER_CHOICE:
                    - QUOTE_SUMMARY
                    QUOTE_SUMMARY: []
                  screens:
                  - id: PROFILE_INFO
                    title: Get a Quote
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: Image
                        src: data:image/png;base64,YOUR_BASE64_HERE
                        width: 600
                        height: 250
                        scale-type: cover
                        aspect-ratio: 2.4
                      - type: TextHeading
                        text: Get your health insurance quote
                      - type: TextBody
                        text: Answer a few questions and we will give you an instant personalised quote.
                      - type: Form
                        name: profile_form
                        children:
                        - type: TextInput
                          name: full_name
                          label: Full name
                          input-type: text
                          required: true
                        - type: DatePicker
                          name: date_of_birth
                          label: Date of birth
                          required: true
                        - type: RadioButtonsGroup
                          name: gender
                          label: Gender
                          required: true
                          data-source:
                          - id: male
                            title: Male
                          - id: female
                            title: Female
                          - id: other
                            title: Other
                        - type: Dropdown
                          name: smoker_status
                          label: Smoking status
                          required: true
                          data-source:
                          - id: non_smoker
                            title: Non-smoker
                          - id: smoker
                            title: Smoker
                          - id: ex_smoker
                            title: Ex-smoker
                        - type: Footer
                          label: Continue
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: COVER_CHOICE
                            payload:
                              full_name: ${form.full_name}
                              date_of_birth: ${form.date_of_birth}
                              gender: ${form.gender}
                              smoker_status: ${form.smoker_status}
                  - id: COVER_CHOICE
                    title: Choose Cover
                    data:
                      full_name:
                        type: string
                        __example__: Dana Lee
                      date_of_birth:
                        type: string
                        __example__: '1990-05-15'
                      gender:
                        type: string
                        __example__: female
                      smoker_status:
                        type: string
                        __example__: non_smoker
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Choose your cover
                      - type: Form
                        name: cover_form
                        children:
                        - type: RadioButtonsGroup
                          name: cover_type
                          label: Coverage type
                          required: true
                          data-source:
                          - id: basic
                            title: Basic
                            description: Hospitalisation only
                          - id: standard
                            title: Standard
                            description: Hospitalisation + OPD
                          - id: comprehensive
                            title: Comprehensive
                            description: All inclusive
                        - type: Dropdown
                          name: sum_insured
                          label: Sum insured
                          required: true
                          data-source:
                          - id: three_lakh
                            title: ₹ 3,00,000
                          - id: five_lakh
                            title: ₹ 5,00,000
                          - id: ten_lakh
                            title: ₹ 10,00,000
                          - id: twenty_lakh
                            title: ₹ 20,00,000
                        - type: Footer
                          label: Get My Quote
                          on-click-action:
                            name: navigate
                            next:
                              type: screen
                              name: QUOTE_SUMMARY
                            payload:
                              full_name: ${data.full_name}
                              date_of_birth: ${data.date_of_birth}
                              gender: ${data.gender}
                              smoker_status: ${data.smoker_status}
                              cover_type: ${form.cover_type}
                              sum_insured: ${form.sum_insured}
                  - id: QUOTE_SUMMARY
                    title: Your Quote
                    terminal: true
                    data:
                      full_name:
                        type: string
                        __example__: Dana Lee
                      date_of_birth:
                        type: string
                        __example__: '1990-05-15'
                      gender:
                        type: string
                        __example__: female
                      smoker_status:
                        type: string
                        __example__: non_smoker
                      cover_type:
                        type: string
                        __example__: standard
                      sum_insured:
                        type: string
                        __example__: five_lakh
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Your personalised quote
                      - type: TextCaption
                        text: Name
                      - type: TextBody
                        text: Dana Lee
                      - type: TextCaption
                        text: Plan
                      - type: TextBody
                        text: Standard — ₹ 5,00,000 cover
                      - type: TextCaption
                        text: Annual premium
                      - type: TextBody
                        text: ₹ 12,500 per year
                      - type: TextCaption
                        text: Monthly premium
                      - type: TextBody
                        text: ₹ 1,042 per month
                      - type: TextBody
                        text: Our advisor will call you within 2 hours to complete your policy.
                      - type: Footer
                        label: Buy Now
                        on-click-action:
                          name: complete
                          payload:
                            full_name: ${data.full_name}
                            cover_type: ${data.cover_type}
                            sum_insured: ${data.sum_insured}
              Upload Flow JSON:
                value:
                  version: '7.0'
                  screens:
                  - id: APPOINTMENT_SCREEN
                    title: Book Appointment
                    terminal: true
                    data: {}
                    layout:
                      type: SingleColumnLayout
                      children:
                      - type: TextHeading
                        text: Book your appointment
                      - type: TextInput
                        name: name
                        label: Your name
                        required: true
                      - type: Footer
                        label: Submit
                        on-click-action:
                          name: complete
                          payload: {}
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                success: true
                validation_errors: []
  /whatsapp/flow/{WA_FLOW_ID}/publish:
    post:
      tags:
      - WhatsApp
      summary: 11.21.3 Publish Flow
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Publish a draft flow

        Publishes a flow on Meta so it can be sent to recipients. The flow must already have a valid uploaded JSON definition.

        **Notes for this request**

        Step — publishes the uploaded JSON. Endpoint flows must have `endpoint_uri` set and the public key registered (11.3) first.

        **Endpoint** `POST /flow/{flowId}/publish`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_flow_WA_FLOW_ID_publish
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                success: true
  /whatsapp/flow/{WA_FLOW_ID}:
    put:
      tags:
      - WhatsApp
      summary: 11.24.2 Set Endpoint URI
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update flow metadata on Meta

        Patch any subset of {endpoint_uri, name, categories}. Categories are comma-separated. Unspecified fields stay unchanged.

        **Notes for this request**

        Required before publish for WITH ENDPOINT flows. Your server must handle encrypted POST requests. Required before publish for WITH ENDPOINT flows (same endpoint as 11.10).

        **Endpoint** `PUT /flow/{flowId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Request body** `application/json` — `UpdateFlowRequest`

        | Field | Type |
        |---|---|
        | `name` | `String` |
        | `categories` | `String` |
        | `endpoint_uri` | `String` |
        | `application_id` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: put_whatsapp_flow_WA_FLOW_ID
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                endpoint_uri:
                  type: string
            examples:
              11.24.2 Set Endpoint URI:
                value:
                  endpoint_uri: '{{WA_FLOW_ENDPOINT_URI}}'
              11.25.2 Set Endpoint URI:
                value:
                  endpoint_uri: '{{WA_FLOW_ENDPOINT_URI}}'
              11.27.2 Set Endpoint URI:
                value:
                  endpoint_uri: '{{WA_FLOW_ENDPOINT_URI}}'
              11.29.2 Set Endpoint URI:
                value:
                  endpoint_uri: '{{WA_FLOW_ENDPOINT_URI}}'
              Update Flow:
                value:
                  name: Appointment Booking Flow v2
                  categories: OTHER
                  endpoint_uri: https://api.broadnet.me/whatsapp/flow/endpoint
                  application_id: '{{WA_META_APP_ID}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              example:
                success: true
    get:
      tags:
      - WhatsApp
      summary: Get Flow
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Fetch a single flow's metadata

        Returns one flow's metadata for the tenant. Serves the cached local mirror when present, otherwise reads the flow from Meta and stores it. Requires the flow to belong to the authenticated tenant's WABA and the account not to be blocked by compliance.

        **Notes for this request**

        Fetch a single flow's metadata + status.

        **Endpoint** `GET /flow/{flowId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_WA_FLOW_ID
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Delete Flow (deprecate)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Soft-delete (DEPRECATE) the flow on Meta

        Deletes the flow on Meta and removes its local mirror row. A DRAFT flow is deleted outright; a published flow that Meta refuses to delete is auto-deprecated instead so the call still succeeds. Refused if compliance has blocked the account.

        **Notes for this request**

        Soft-delete (DEPRECATE) the flow on Meta.

        **Endpoint** `DELETE /flow/{flowId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_flow_WA_FLOW_ID
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: OK
  /whatsapp/flow/endpoint:
    post:
      tags:
      - WhatsApp
      summary: Flow Data Exchange
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Handle WhatsApp Flow data-exchange request

        Receives Meta's encrypted flow-interaction payload, decrypts it, builds the next-screen response, encrypts the response and returns it as a base64 text/plain body. This is the URL configured as the flow's data exchange endpoint on Meta.

        **Notes for this request**

        Called BY Meta with an ENCRYPTED envelope — body = {encrypted_flow_data, encrypted_aes_key, initial_vector} (shown below). The service RSA-OAEP-decrypts the AES key, AES-GCM-decrypts the data into {version, action, screen, data, flow_token}, builds the next screen, and returns it AES-GCM-encrypted as base64 text/plain. A manual plaintext call returns 421 by design; plumbing is ready (public key registered VALID) and is exercised when a real flow runs.

        **Endpoint** `POST /flow/endpoint`

        **Headers** `Authorization: Bearer <JWT>`

        **Request body** `application/json` — `FlowDataExchangeRequest`

        | Field | Type |
        |---|---|
        | `encrypted_flow_data` | `String` |
        | `encrypted_aes_key` | `String` |
        | `initial_vector` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Encrypted response body returned. |
        | 421 | Decryption failed — Meta will refresh keys. |
        | 500 | Internal error while building response. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_flow_endpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                encrypted_flow_data:
                  type: string
                encrypted_aes_key:
                  type: string
                initial_vector:
                  type: string
            examples:
              Flow Data Exchange:
                value:
                  encrypted_flow_data: <base64 AES-GCM ciphertext — Meta sends this>
                  encrypted_aes_key: <base64 RSA-OAEP-encrypted AES key>
                  initial_vector: <base64 initialization vector>
      responses:
        '200':
          description: OK
  /whatsapp/flow/ping:
    post:
      tags:
      - WhatsApp
      summary: Flow Ping
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Out-of-band uptime ping

        Plaintext health check for monitors hitting the URL directly. Meta itself sends pings through /flow/endpoint with action=ping in the encrypted body.

        **Endpoint** `POST /flow/ping`

        **Headers** `Authorization: Bearer <JWT>`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Endpoint healthy. |
        | 500 | Endpoint failed. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_flow_ping
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                version:
                  type: string
                action:
                  type: string
            examples:
              Flow Ping:
                value:
                  version: '3.0'
                  action: ping
      responses:
        '200':
          description: OK
  /whatsapp/flow/register-public-key:
    post:
      tags:
      - WhatsApp
      summary: Register Public Key
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Register / replace the flow public key for the tenant's phone number

        Body is the PEM-encoded RSA-2048 public key (with BEGIN/END markers). Meta will use this key to encrypt outgoing flow callbacks to /flow/endpoint. Our matching private key must be configured via WHATSAPP_FLOW_PRIVATE_KEY_PEM. Returns Meta's signature_status — VALID means the registration is healthy.

        **Endpoint** `POST /flow/register-public-key`

        **Headers** `Authorization: Bearer <JWT>`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_flow_register_public_key
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
            examples:
              Register Public Key:
                value: '{{WA_PUBLIC_KEY_PEM}}'
      responses:
        '200':
          description: OK
  /whatsapp/flow/public-key:
    get:
      tags:
      - WhatsApp
      summary: Get Public Key
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Read the currently-registered flow public key + signature status

        Returns the flow public key currently registered on the tenant's phone number and Meta's signature status for it (VALID means the registration is healthy). Requires the account to be onboarded and not blocked by compliance.

        **Endpoint** `GET /flow/public-key`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_public_key
      responses:
        '200':
          description: OK
  /whatsapp/flow/list:
    get:
      tags:
      - WhatsApp
      summary: List Flows
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List all flows for the tenant's WABA

        DB-first. Pass refresh=true to re-sync from Meta and reconcile deletions.

        **Endpoint** `GET /flow/list`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `search` | query | no | Free-text search |
        | `name` | query | no | Name (unique per tenant) |
        | `category` | query | no | Filter by category |
        | `status` | query | no | Filter by status |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Flow list returned. |
        | 400 | Compliance block in effect. |
        | 404 | Account not onboarded. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_list
      parameters:
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: name
        in: query
        required: false
        schema:
          type: string
      - name: category
        in: query
        required: false
        schema:
          type: string
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      responses:
        '200':
          description: OK
  /whatsapp/flow/config:
    get:
      tags:
      - WhatsApp
      summary: Flow Config
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Describe environment-derived flow config

        Returns the Meta Graph base URL, API version, and the public-facing /flow/endpoint URL that should be configured on Meta's flow settings.

        **Notes for this request**

        Environment-derived flow config: Graph base URL, API version, and the public /flow/endpoint URL to set on Meta.

        **Endpoint** `GET /flow/config`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_config
      responses:
        '200':
          description: OK
  /whatsapp/flow/{WA_FLOW_ID}/preview:
    get:
      tags:
      - WhatsApp
      summary: Get Flow Preview
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a flow's webview preview URL

        Returns Meta's preview webview URL for the flow so it can be rendered in a browser for design or QA without sending it to a recipient. Requires the account to be onboarded and not blocked by compliance.

        **Notes for this request**

        Returns the flow's webview preview URL (test without sending).

        **Endpoint** `GET /flow/{flowId}/preview`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_WA_FLOW_ID_preview
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: OK
  /whatsapp/flow/{WA_FLOW_ID}/metrics:
    get:
      tags:
      - WhatsApp
      summary: Get Flow Metrics
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a flow's metrics/insights

        Returns Meta's usage metrics/insights for the flow, defaulting to daily endpoint-request counts when no field expression is supplied. Requires the account to be onboarded and not blocked by compliance.

        **Notes for this request**

        Flow insights (request counts, etc.). Omit fields for the default metric.

        **Endpoint** `GET /flow/{flowId}/metrics`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_WA_FLOW_ID_metrics
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      - name: fields
        in: query
        required: false
        schema:
          type: string
        example: metric.name(ENDPOINT_REQUEST_COUNT).granularity(DAY)
      responses:
        '200':
          description: OK
  /whatsapp/flow/{WA_FLOW_ID}/assets:
    get:
      tags:
      - WhatsApp
      summary: Get Flow Assets
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a flow's uploaded assets (current flow JSON)

        Returns Meta's asset listing for the flow, primarily the currently-attached flow JSON definition. Requires the account to be onboarded and not blocked by compliance.

        **Notes for this request**

        Read the flow's currently-uploaded JSON asset(s).

        **Endpoint** `GET /flow/{flowId}/assets`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_WA_FLOW_ID_assets
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: OK
  /whatsapp/flow/{WA_FLOW_ID}/deprecate:
    post:
      tags:
      - WhatsApp
      summary: Deprecate Flow (explicit)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Explicitly deprecate a published flow

        Deprecate a still-wanted published flow directly, without attempting a delete first.

        **Notes for this request**

        Explicitly deprecate a still-wanted published flow, without attempting a delete first.

        **Endpoint** `POST /flow/{flowId}/deprecate`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_flow_WA_FLOW_ID_deprecate
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      responses:
        '200':
          description: OK
  /whatsapp/flow/migrate:
    post:
      tags:
      - WhatsApp
      summary: Migrate Flows
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Migrate flows from another WABA

        Copies flows from a source WABA into this tenant's WABA. Optionally restrict to specific flow names (JSON array string).

        **Notes for this request**

        Migrate flows from another WABA into this tenant. `sourceFlowNames` is an optional JSON-array string to restrict which flows are copied.

        **Endpoint** `POST /flow/migrate`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `sourceWabaId` | query | yes | WABA to copy from |
        | `sourceFlowNames` | query | no | JSON array of flow names to copy |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_flow_migrate
      parameters:
      - name: sourceWabaId
        in: query
        required: false
        schema:
          type: string
        example: WA_SOURCE_WABA_ID
      - name: sourceFlowNames
        in: query
        required: false
        schema:
          type: string
        example: '["appointment_flow"]'
      responses:
        '200':
          description: OK
  /whatsapp/flow/list/published:
    get:
      tags:
      - WhatsApp
      summary: List Published Flows
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List Published Flows

        **Notes for this request**

        Only flows in PUBLISHED status (sendable). `refresh=true` re-reads from Meta.

        **Endpoint** `GET /flow/list/published`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_list_published
      parameters:
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
  /whatsapp/flow/{WA_FLOW_ID}/insights:
    get:
      tags:
      - WhatsApp
      summary: Flow Insights (completions)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Flow Insights (completions)

        **Notes for this request**

        Paginated list of completed flow submissions (nfm_reply data) for one flow. `from`/`to` are ISO date-times; `search` filters on customer number / response JSON. Returns 404 when nothing matches the window.

        **Endpoint** `GET /flow/{flowId}/insights`

        **Headers** `Authorization: Bearer <JWT>` · `username`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `flowId` | path | yes | Meta flow id |
        | `from` | query | no | Start (ISO date-time) |
        | `to` | query | no | End (ISO date-time) |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |
        | `search` | query | no | Free-text search |
        | `sortBy` | query | no | Sort field (default `completedAt`) |
        | `sortDir` | query | no | `ASC` / `DESC` (default `desc`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_flow_WA_FLOW_ID_insights
      parameters:
      - name: WA_FLOW_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_FLOW_ID
      - name: from
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-01T00:00:00'
      - name: to
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-30T23:59:59'
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: completedAt
      - name: sortDir
        in: query
        required: false
        schema:
          type: string
        example: desc
      - name: search
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/catalog:
    post:
      tags:
      - WhatsApp
      summary: Create Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a product catalog

        Creates a Meta Commerce catalog for the caller's business via the Graph API, then mirrors it into the local catalogs table. Requires the onboarded client to carry a businessId.

        **Notes for this request**

        Creates a product catalog under a Meta Business (owned_product_catalogs). Requires a token with catalog_management. By default it uses the caller's onboarded businessId; pass businessId to create under any Business you manage (MSP), and assignTo to set the owning username. Returns the new catalog id -> set {{WA_CATALOG_ID}}.

        **Endpoint** `POST /catalog`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `name` | query | yes | Name (unique per tenant) |
        | `vertical` | query | no | Catalog vertical, normally `commerce` (default `commerce`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: My First Catalog
      - name: vertical
        in: query
        required: false
        schema:
          type: string
        example: commerce
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/catalog/list:
    get:
      tags:
      - WhatsApp
      summary: List Catalogs
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### List the business's product catalogs

        DB-first. Pass refresh=true to force a full paginated re-sync from Meta and reconcile deletions.

        **Notes for this request**

        Lists catalogs owned by the tenant's Business (id, name, vertical, product_count).

        **Owner rules (2026-09-08):** catalogs created via 13.1 are recorded under the creating operator. Tenants can only touch catalogs mirrored under their username (or unowned rows on their own businessId); anything else is 404. Pass `forUser=<tenant>&refresh=true` to sync a tenant's catalogs from Meta and attribute them.

        **Endpoint** `GET /catalog/list`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |
        | `forUser` | query | no | Target tenant username (operator token required) |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |
        | `search` | query | no | Free-text search |
        | `vertical` | query | no | Catalog vertical, normally `commerce` |
        | `filterUsername` | query | no |  |
        | `businessId` | query | no | Meta business id |
        | `connectedWabaId` | query | no |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_list
      parameters:
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      - name: forUser
        in: query
        required: false
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: vertical
        in: query
        required: false
        schema:
          type: string
      - name: filterUsername
        in: query
        required: false
        schema:
          type: string
      - name: businessId
        in: query
        required: false
        schema:
          type: string
      - name: connectedWabaId
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/catalog/{WA_CATALOG_ID}/product:
    post:
      tags:
      - WhatsApp
      summary: Add Product
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Add a product (full Meta field set)

        JSON body = Meta product fields (retailer_id, name, price [minor units], currency, image_url, sale_price, brand, condition, custom_label_0…). retailer_id, name, image_url, currency required.

        **Notes for this request**

        Adds one product to the catalog. price is an INTEGER in the currency's minor units (10000 + USD = $100.00). retailerId is your SKU -> use it as {{WA_PRODUCT_RETAILER_ID}} in 4.20/4.21.

        **Endpoint** `POST /catalog/{catalogId}/product`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |

        **Request body** `application/json` — `ProductRequest`

        | Field | Type |
        |---|---|
        | `retailer_id` | `String` |
        | `name` | `String` |
        | `description` | `String` |
        | `rich_text_description` | `String` |
        | `short_description` | `String` |
        | `price` | `Long` |
        | `currency` | `String` |
        | `sale_price` | `Long` |
        | `sale_price_start_date` | `String` |
        | `sale_price_end_date` | `String` |
        | `url` | `String` |
        | `mobile_link` | `String` |
        | `checkout_url` | `String` |
        | `image_url` | `String` |
        | `additional_image_urls` | `List<String>` |
        | `availability` | `String` |
        | `condition` | `String` |
        | `visibility` | `String` |
        | `inventory` | `Integer` |
        | `quantity_to_sell_on_facebook` | `Integer` |
        | `brand` | `String` |
        | `gtin` | `String` |
        | `manufacturer_part_number` | `String` |
        | `product_type` | `String` |
        | `category` | `String` |
        | `google_product_category` | `String` |
        | `fb_product_category` | `String` |
        | `color` | `String` |
        | `size` | `String` |
        | `gender` | `String` |
        | `age_group` | `String` |
        | `material` | `String` |
        | `pattern` | `String` |
        | `retailer_product_group_id` | `String` |
        | `custom_label_0` | `String` |
        | `custom_label_1` | `String` |
        | `custom_label_2` | `String` |
        | `custom_label_3` | `String` |
        | `custom_label_4` | `String` |
        | `custom_number_0` | `Long` |
        | `custom_number_1` | `Long` |
        | `custom_number_2` | `Long` |
        | `custom_number_3` | `Long` |
        | `custom_number_4` | `Long` |
        | `origin_country` | `String` |
        | `importer_name` | `String` |
        | `importer_address` | `ImporterAddress` |
        | `importer_address.street1` | `String` |
        | `importer_address.street2` | `String` |
        | `importer_address.city` | `String` |
        | `importer_address.region` | `String` |
        | `importer_address.postal_code` | `String` |
        | `importer_address.country` | `String` |
        | `wa_compliance_category` | `String` |
        | `commerce_tax_category` | `String` |
        | `shipping_weight_value` | `Double` |
        | `shipping_weight_unit` | `String` |
        | `return_policy_days` | `Integer` |
        | `ios_url` | `String` |
        | `android_url` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_product
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                retailer_id:
                  type: string
                name:
                  type: string
                description:
                  type: string
                price:
                  type: integer
                currency:
                  type: string
                image_url:
                  type: string
                additional_image_urls:
                  type: array
                  items:
                    type: string
                url:
                  type: string
                availability:
                  type: string
                condition:
                  type: string
                brand:
                  type: string
                sale_price:
                  type: integer
                sale_price_start_date:
                  type: string
                sale_price_end_date:
                  type: string
                category:
                  type: string
                google_product_category:
                  type: string
                color:
                  type: string
                size:
                  type: string
                gender:
                  type: string
                age_group:
                  type: string
                gtin:
                  type: string
                manufacturer_part_number:
                  type: string
                custom_label_0:
                  type: string
                visibility:
                  type: string
                inventory:
                  type: integer
                quantity_to_sell_on_facebook:
                  type: integer
            examples:
              Add Product:
                value:
                  retailer_id: SKU-1001
                  name: Wireless Headphones
                  description: Over-ear Bluetooth headphones
                  price: 12999
                  currency: USD
                  image_url: https://example.com/img/headphones.jpg
                  additional_image_urls:
                  - https://example.com/img/headphones-2.jpg
                  url: https://shop.example.com/p/1001
                  availability: in stock
                  condition: new
                  brand: Acme
                  sale_price: 9999
                  sale_price_start_date: 2026-08-01T00:00-07:00
                  sale_price_end_date: 2026-08-31T23:59-07:00
                  category: Electronics > Audio
                  google_product_category: '178'
                  color: Black
                  size: One Size
                  gender: unisex
                  age_group: adult
                  gtin: 0123456789012
                  manufacturer_part_number: ACM-HP-1001
                  custom_label_0: summer-sale
                  visibility: published
                  inventory: 250
                  quantity_to_sell_on_facebook: 250
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/products:
    get:
      tags:
      - WhatsApp
      summary: List Products
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List products in a catalog

        DB-first. Pass a Meta filter rule, limit, or summary=true for a live server-side query; otherwise refresh=true forces a full re-sync.

        **Notes for this request**

        Lists products in the catalog (id, retailer_id, name, price, currency, availability).

        **Change 2026-09-09:** an empty catalog or an empty page returns `200` with an empty `data` list (previously `404`).

        **Endpoint** `GET /catalog/{catalogId}/products`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `summary` | query | no | `true` = counts only (default `false`) |
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `20`) |
        | `search` | query | no | Free-text search |
        | `availability` | query | no |  |
        | `visibility` | query | no |  |
        | `brand` | query | no |  |
        | `category` | query | no | Filter by category |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_products
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: summary
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: availability
        in: query
        required: false
        schema:
          type: string
      - name: visibility
        in: query
        required: false
        schema:
          type: string
      - name: brand
        in: query
        required: false
        schema:
          type: string
      - name: category
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}:
    get:
      tags:
      - WhatsApp
      summary: Get Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get a single catalog

        DB-first. Pass refresh=true to re-read this catalog live from Meta.

        **Notes for this request**

        Fetch a single catalog's fields.

        **Endpoint** `GET /catalog/{catalogId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    put:
      tags:
      - WhatsApp
      summary: Update Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update a catalog's name

        Renames the catalog on Meta via the Graph API and updates the local mirror. The catalog must be owned by the caller.

        **Notes for this request**

        Rename a catalog.

        **Endpoint** `PUT /catalog/{catalogId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `name` | query | yes | Name (unique per tenant) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: put_whatsapp_catalog_WA_CATALOG_ID
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: BroadNet Store (renamed)
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    delete:
      tags:
      - WhatsApp
      summary: Delete Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete a catalog

        Deletes the catalog on Meta via the Graph API, then removes the cached catalog row and all of its cached products. The catalog must be owned by the caller.

        **Notes for this request**

        Delete a catalog.

        **Endpoint** `DELETE /catalog/{catalogId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_WA_CATALOG_ID
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/catalog/{WA_CATALOG_ID}/products/batch:
    post:
      tags:
      - WhatsApp
      summary: Batch Products (create/update/delete)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Batch create/update/delete products

        Body: {"item_type":"PRODUCT_ITEM","requests":[{"method":"CREATE|UPDATE|DELETE","data":{...}}]}. Any Meta product field is accepted in data.

        **Notes for this request**

        Bulk upsert/delete products via items_batch. price is 'AMOUNT CURRENCY' string in feed format.

        **Endpoint** `POST /catalog/{catalogId}/products/batch`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |

        **Request body** `application/json` — `ProductBatchRequest`

        | Field | Type |
        |---|---|
        | `item_type` | `String` |
        | `requests` | `List<BatchOp>` |
        | `method` | `String` |
        | `retailer_id` | `String` |
        | `data` | `Object` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_products_batch
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                item_type:
                  type: string
                requests:
                  type: array
                  items:
                    type: object
                    properties:
                      method:
                        type: string
                      data:
                        type: object
                        properties:
                          retailer_id:
                            type: string
                          name:
                            type: string
                          description:
                            type: string
                          price:
                            type: integer
                          currency:
                            type: string
                          availability:
                            type: string
                          condition:
                            type: string
                          image_url:
                            type: string
                          url:
                            type: string
            examples:
              Batch Products (create/update/delete):
                value:
                  item_type: PRODUCT_ITEM
                  requests:
                  - method: CREATE
                    data:
                      retailer_id: SKU-100
                      name: New Item
                      description: A great new item
                      price: 10000
                      currency: INR
                      availability: in stock
                      condition: new
                      image_url: https://example.com/i.jpg
                      url: https://shop.example.com/p/100
                  - method: DELETE
                    data:
                      retailer_id: SKU-OLD
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/products/batch-status:
    get:
      tags:
      - WhatsApp
      summary: Check batch status
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Check items_batch status by handle(s)

        handles = comma-separated or a JSON array of handles returned by the batch call.

        **Notes for this request**

        Check the status of an async products batch (from 13.8). `handles` is the batch handle string returned by the batch upsert; pass one or more (comma-separated) to poll processing status.

        **Endpoint** `GET /catalog/{catalogId}/products/batch-status`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `handles` | query | yes | Comma-separated items_batch handles |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_products_batch_status
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: handles
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/catalog/product-item/{WA_PRODUCT_ITEM_ID}:
    get:
      tags:
      - WhatsApp
      summary: Get Product
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a single product-item

        DB-first. Pass refresh=true to re-read this product live from Meta.

        **Notes for this request**

        Get a single product-item by its Meta product id.

        **Endpoint** `GET /catalog/product-item/{productItemId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productItemId` | path | yes | Meta product item id (not the SKU) |
        | `refresh` | query | no | `true` = re-read live from Meta and update the local mirror (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_product_item_WA_PRODUCT_ITEM_ID
      parameters:
      - name: WA_PRODUCT_ITEM_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_ITEM_ID
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
    put:
      tags:
      - WhatsApp
      summary: Update Product
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update a single product-item (full Meta field set)

        JSON body = any Meta product fields to change (partial update).

        **Notes for this request**

        Update a product-item (price in minor units).

        **Endpoint** `PUT /catalog/product-item/{productItemId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productItemId` | path | yes | Meta product item id (not the SKU) |

        **Request body** `application/json` — `ProductRequest`

        | Field | Type |
        |---|---|
        | `retailer_id` | `String` |
        | `name` | `String` |
        | `description` | `String` |
        | `rich_text_description` | `String` |
        | `short_description` | `String` |
        | `price` | `Long` |
        | `currency` | `String` |
        | `sale_price` | `Long` |
        | `sale_price_start_date` | `String` |
        | `sale_price_end_date` | `String` |
        | `url` | `String` |
        | `mobile_link` | `String` |
        | `checkout_url` | `String` |
        | `image_url` | `String` |
        | `additional_image_urls` | `List<String>` |
        | `availability` | `String` |
        | `condition` | `String` |
        | `visibility` | `String` |
        | `inventory` | `Integer` |
        | `quantity_to_sell_on_facebook` | `Integer` |
        | `brand` | `String` |
        | `gtin` | `String` |
        | `manufacturer_part_number` | `String` |
        | `product_type` | `String` |
        | `category` | `String` |
        | `google_product_category` | `String` |
        | `fb_product_category` | `String` |
        | `color` | `String` |
        | `size` | `String` |
        | `gender` | `String` |
        | `age_group` | `String` |
        | `material` | `String` |
        | `pattern` | `String` |
        | `retailer_product_group_id` | `String` |
        | `custom_label_0` | `String` |
        | `custom_label_1` | `String` |
        | `custom_label_2` | `String` |
        | `custom_label_3` | `String` |
        | `custom_label_4` | `String` |
        | `custom_number_0` | `Long` |
        | `custom_number_1` | `Long` |
        | `custom_number_2` | `Long` |
        | `custom_number_3` | `Long` |
        | `custom_number_4` | `Long` |
        | `origin_country` | `String` |
        | `importer_name` | `String` |
        | `importer_address` | `ImporterAddress` |
        | `importer_address.street1` | `String` |
        | `importer_address.street2` | `String` |
        | `importer_address.city` | `String` |
        | `importer_address.region` | `String` |
        | `importer_address.postal_code` | `String` |
        | `importer_address.country` | `String` |
        | `wa_compliance_category` | `String` |
        | `commerce_tax_category` | `String` |
        | `shipping_weight_value` | `Double` |
        | `shipping_weight_unit` | `String` |
        | `return_policy_days` | `Integer` |
        | `ios_url` | `String` |
        | `android_url` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: put_whatsapp_catalog_product_item_WA_PRODUCT_ITEM_ID
      parameters:
      - name: WA_PRODUCT_ITEM_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_ITEM_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                price:
                  type: integer
                sale_price:
                  type: integer
                availability:
                  type: string
                condition:
                  type: string
            examples:
              Update Product:
                value:
                  name: Updated name
                  price: 11999
                  sale_price: 9999
                  availability: out of stock
                  condition: refurbished
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Delete Product
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a single product-item

        Deletes the product on Meta via the Graph API, then removes it from the local cache. The product must be owned by the caller.

        **Notes for this request**

        Delete a product-item.

        **Endpoint** `DELETE /catalog/product-item/{productItemId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productItemId` | path | yes | Meta product item id (not the SKU) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_product_item_WA_PRODUCT_ITEM_ID
      parameters:
      - name: WA_PRODUCT_ITEM_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_ITEM_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/connected:
    get:
      tags:
      - WhatsApp
      summary: Get Connected Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Read the catalog connected to the tenant's WABA

        Returns the cached WABA-catalog link, or queries Meta for the WABA's connected catalog and caches it. Does not require a businessId.

        **Notes for this request**

        Read the catalog connected to the tenant's WABA.

        **Endpoint** `GET /catalog/connected`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_connected
      responses:
        '200':
          description: OK
  /whatsapp/catalog/connect:
    post:
      tags:
      - WhatsApp
      summary: Connect Catalog to WABA
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Connect a catalog to a specific WABA

        Links the catalog to the given wabaId on Meta. The wabaId must belong to (owned or shared) the user who owns the catalog.

        **Notes for this request**

        Link a catalog to a tenant's WABA (one catalog per WABA; a previous link on that WABA is cleared in the mirror). Super-admin/system only. `forUser` = the onboarded tenant whose WABA receives the catalog (REQUIRED).

        **Known Meta limitation (2026-09-08):** this Graph call (`POST /{waba}/product_catalogs`) is rejected with `#100 / 2388100 Manage catalogue permission required` when the calling Meta app has only Standard access to `catalog_management` — that is the case for app Broadnet LLC (1871844863768825) until its App Review is approved. Until then connect the catalog in WhatsApp Manager > Catalogue; all other catalog endpoints work.

        **Endpoint** `POST /catalog/connect`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | query | yes | Meta catalog id |
        | `forUser` | query | no | Target tenant username (operator token required) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_connect
      parameters:
      - name: catalogId
        in: query
        required: false
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: forUser
        in: query
        required: false
        schema:
          type: string
        example: USERNAME
      responses:
        '200':
          description: OK
  /whatsapp/catalog/disconnect:
    delete:
      tags:
      - WhatsApp
      summary: Disconnect Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Disconnect a catalog from the tenant's WABA

        Removes the catalog-WABA link on Meta and clears it in the local mirror. The catalog must be owned by the caller.

        **Notes for this request**

        Unlink a catalog from a tenant's WABA. Super-admin/system only; `forUser` REQUIRED. Same Meta app-access limitation as 13.13 applies.

        **Endpoint** `DELETE /catalog/disconnect`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | query | yes | Meta catalog id |
        | `forUser` | query | no | Target tenant username (operator token required) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_disconnect
      parameters:
      - name: catalogId
        in: query
        required: false
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: forUser
        in: query
        required: false
        schema:
          type: string
        example: USERNAME
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/product-sets:
    post:
      tags:
      - WhatsApp
      summary: Create Product Set
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a product set (collection) in a catalog

        filter/metadata/publish_to_shops are optional Meta JSON strings.

        **Notes for this request**

        Create a product set (collection) in a catalog. `filter` is an optional Meta filter JSON string; omit it for a manually-curated set.

        **Endpoint** `POST /catalog/{catalogId}/product-sets`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `name` | query | yes | Name (unique per tenant) |
        | `filter` | query | no | Meta filter JSON, e.g. `{"retailer_id":{"is_any":["SKU1"]}}` |
        | `metadata` | query | no |  |
        | `retailerId` | query | no | Retailer id of the group's base product |
        | `publishToShops` | query | no |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_product_sets
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: Summer Collection
      - name: filter
        in: query
        required: false
        schema:
          type: string
        example: '{"retailer_id":{"is_any":["SKU1","SKU2"]}}'
      - name: metadata
        in: query
        required: false
        schema:
          type: string
      - name: retailerId
        in: query
        required: false
        schema:
          type: string
      - name: publishToShops
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
    get:
      tags:
      - WhatsApp
      summary: List Product Sets
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List the product sets in a catalog

        Reads every product set of the catalog live from Meta (paginated). The catalog must be owned by the caller.

        **Endpoint** `GET /catalog/{catalogId}/product-sets`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_product_sets
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      responses:
        '200':
          description: OK
  /whatsapp/catalog/product-sets/{WA_PRODUCT_SET_ID}:
    get:
      tags:
      - WhatsApp
      summary: Get Product Set
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get a single product set

        Reads the product set live from Meta. Ownership is enforced via the set's parent catalog, which must be owned by the caller.

        **Endpoint** `GET /catalog/product-sets/{productSetId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productSetId` | path | yes | Meta product set id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_product_sets_WA_PRODUCT_SET_ID
      parameters:
      - name: WA_PRODUCT_SET_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_SET_ID
      responses:
        '200':
          description: OK
    put:
      tags:
      - WhatsApp
      summary: Update Product Set
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update a product set's name, filter and/or metadata

        Updates the product set on Meta via the Graph API after confirming the caller owns its parent catalog. filter/metadata are optional Meta JSON strings.

        **Notes for this request**

        Update a product set's name and/or filter (both optional).

        **Endpoint** `PUT /catalog/product-sets/{productSetId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productSetId` | path | yes | Meta product set id |
        | `name` | query | no | Name (unique per tenant) |
        | `filter` | query | no | Meta filter JSON, e.g. `{"retailer_id":{"is_any":["SKU1"]}}` |
        | `metadata` | query | no |  |
        | `retailerId` | query | no | Retailer id of the group's base product |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: put_whatsapp_catalog_product_sets_WA_PRODUCT_SET_ID
      parameters:
      - name: WA_PRODUCT_SET_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_SET_ID
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: Summer Collection 2026
      - name: filter
        in: query
        required: false
        schema:
          type: string
        example: '{"retailer_id":{"is_any":["SKU1","SKU3"]}}'
      - name: metadata
        in: query
        required: false
        schema:
          type: string
      - name: retailerId
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Delete Product Set
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a product set

        Deletes the product set on Meta via the Graph API after confirming the caller owns its parent catalog.

        **Endpoint** `DELETE /catalog/product-sets/{productSetId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productSetId` | path | yes | Meta product set id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_product_sets_WA_PRODUCT_SET_ID
      parameters:
      - name: WA_PRODUCT_SET_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_SET_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/product-groups:
    post:
      tags:
      - WhatsApp
      summary: Create Product Group
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Create a product (variant) group in a catalog

        retailerId is required; variants is an optional Meta JSON string describing the variant attributes (e.g. color/size).

        **Endpoint** `POST /catalog/{catalogId}/product-groups`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `retailerId` | query | yes | Retailer id of the group's base product |
        | `variants` | query | no | Comma-separated variant attribute names |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_product_groups
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: retailerId
        in: query
        required: false
        schema:
          type: string
        example: WA_PRODUCT_RETAILER_ID
      - name: variants
        in: query
        required: false
        schema:
          type: string
        example: color,size
      responses:
        '200':
          description: OK
    get:
      tags:
      - WhatsApp
      summary: List Product Groups
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List the product (variant) groups in a catalog

        Listed live from Meta for this catalog.

        **Endpoint** `GET /catalog/{catalogId}/product-groups`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_product_groups
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      responses:
        '200':
          description: OK
  /whatsapp/catalog/product-groups/{WA_PRODUCT_GROUP_ID}/products:
    get:
      tags:
      - WhatsApp
      summary: Get Group Products
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List a product group's variant products

        Reads the variant products (items) that belong to the given product group live from Meta.

        **Endpoint** `GET /catalog/product-groups/{productGroupId}/products`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productGroupId` | path | yes | Meta product group id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_product_groups_WA_PRODUCT_GROUP_ID_products
      parameters:
      - name: WA_PRODUCT_GROUP_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_GROUP_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/product-groups/{WA_PRODUCT_GROUP_ID}:
    delete:
      tags:
      - WhatsApp
      summary: Delete Product Group
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Delete a product (variant) group

        Deletes the given product (variant) group from Meta by its product-group id.

        **Endpoint** `DELETE /catalog/product-groups/{productGroupId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `productGroupId` | path | yes | Meta product group id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_product_groups_WA_PRODUCT_GROUP_ID
      parameters:
      - name: WA_PRODUCT_GROUP_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_PRODUCT_GROUP_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/assigned-users:
    post:
      tags:
      - WhatsApp
      summary: Assign User to Catalog
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Assign a user to a catalog

        Grants a person/system-user access (tasks, default MANAGE) to manage the catalog. Requires business_management.

        **Notes for this request**

        Grant a Meta System/Business user access to this catalog (Meta assigned_users). 'tasks' defaults to MANAGE. Authorized for the catalog owner OR a super-admin/system operator (the operator resolves the owner businessId from the stored catalog row).

        **Endpoint** `POST /catalog/{catalogId}/assigned-users`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `user` | query | yes | Meta user / system-user id |
        | `tasks` | query | no | Comma-separated tasks, e.g. `MANAGE` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_assigned_users
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: user
        in: query
        required: false
        schema:
          type: string
        example: WA_ASSIGN_USER_ID
      - name: tasks
        in: query
        required: false
        schema:
          type: string
        example: MANAGE
      responses:
        '200':
          description: OK
    get:
      tags:
      - WhatsApp
      summary: List Catalog Assigned Users
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List catalog assigned users

        **Notes for this request**

        List the users assigned to this catalog (Meta assigned_users; fields id,name,tasks).

        **Endpoint** `GET /catalog/{catalogId}/assigned-users`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_assigned_users
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Remove Catalog User
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Remove a catalog assigned user

        **Notes for this request**

        Revoke a user's access to this catalog (Meta assigned_users DELETE).

        **Endpoint** `DELETE /catalog/{catalogId}/assigned-users`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `user` | query | yes | Meta user / system-user id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_WA_CATALOG_ID_assigned_users
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: user
        in: query
        required: false
        schema:
          type: string
        example: WA_ASSIGN_USER_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/agencies:
    post:
      tags:
      - WhatsApp
      summary: Add Catalog Agency
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Share a catalog with another business

        Grants another business (agency) access to the catalog. Requires business_management.

        **Notes for this request**

        Share this catalog with another business (Meta agencies edge). 'permittedTasks' defaults to MANAGE.

        **Endpoint** `POST /catalog/{catalogId}/agencies`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `businessId` | query | yes | Meta business id |
        | `permittedTasks` | query | no | Comma-separated tasks granted to the agency |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_agencies
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: businessId
        in: query
        required: false
        schema:
          type: string
        example: WA_AGENCY_BUSINESS_ID
      - name: permittedTasks
        in: query
        required: false
        schema:
          type: string
        example: MANAGE
      responses:
        '200':
          description: OK
    get:
      tags:
      - WhatsApp
      summary: List Catalog Agencies
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List catalog agencies (businesses with access)

        **Notes for this request**

        List businesses (agencies) that can access this catalog (Meta agencies; fields id,name).

        **Endpoint** `GET /catalog/{catalogId}/agencies`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_agencies
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Revoke Catalog Agency
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Revoke a business's catalog access

        **Notes for this request**

        Revoke another business's access to this catalog (Meta agencies DELETE).

        **Endpoint** `DELETE /catalog/{catalogId}/agencies`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `businessId` | query | yes | Meta business id |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_catalog_WA_CATALOG_ID_agencies
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: businessId
        in: query
        required: false
        schema:
          type: string
        example: WA_AGENCY_BUSINESS_ID
      responses:
        '200':
          description: OK
  /whatsapp/catalog/owners:
    get:
      tags:
      - WhatsApp
      summary: List Catalog Owners
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### List Catalog Owners

        **Notes for this request**

        Super-admin/system. Returns the usernames of all onboarded tenants (owners a catalog can be attributed to via ?forUser=).

        **Endpoint** `GET /catalog/owners`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_catalog_owners
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/catalog/{WA_CATALOG_ID}/products/upload:
    post:
      tags:
      - WhatsApp
      summary: Upload Products (CSV / XLSX / TXT)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Bulk upload products from a CSV/XLSX/TXT file

        Header row + one product per row. Column names must match Meta product fields (retailer_id, name, price, currency, image_url, ... — see ProductRequest). Submits one items_batch UPDATE (upsert) for the whole file.

        **Notes for this request**

        Bulk-create/upsert products from a file (max 1000 rows). Every row is validated with the same rules as 13.3 (retailer_id, name, http(s) image_url, price>=0 in minor units, 3-letter currency, GTIN check digit); any invalid row rejects the whole upload and all row errors are reported together. On success one Meta items_batch UPDATE is submitted and the cached products are invalidated — poll 13.8.1 with the returned handle.

        **Endpoint** `POST /catalog/{catalogId}/products/upload`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalogId` | path | yes | Meta catalog id |
        | `file` | query | yes | Binary file |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_catalog_WA_CATALOG_ID_products_upload
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
            examples:
              Upload Products (CSV / XLSX / TXT):
                value:
                  file: ''
      responses:
        '200':
          description: OK
  /whatsapp/catalog/{WA_CATALOG_ID}/products/products-lite:
    get:
      tags:
      - WhatsApp
      summary: List products (id, name, retailer_id, url, image_url)
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List products (id, name, retailer_id, url, image_url)

        Lightweight product list served from the DB mirror. Pass refresh=true to force a re-sync from Meta first.

        **Endpoint** `GET /whatsapp/catalog/{catalogId}/products/products-lite`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `catalogId` | path | yes |  |
        | `refresh` | query | no |  (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_whatsapp_catalog_WA_CATALOG_ID_products_products_lite
      parameters:
      - name: WA_CATALOG_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
  /whatsapp/message/catalog-insights:
    get:
      tags:
      - WhatsApp
      summary: Catalog Insights
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Retrieve Catalog Message Insights

        Fetch detailed insights for a WhatsApp catalog.

        **Notes for this request**

        Engagement insights for catalog/product messages sent from the connected catalog: per-customer message status, with `messageStatus`, `customerNumber`, `customerName`, `receiverNumber`, `search` filters.

        **Endpoint** `GET /message/catalog-insights`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `catalog_Id` | query | yes |  |
        | `search` | query | no | Free-text search |
        | `page` | query | no | Zero-based page index (default `0`) |
        | `size` | query | no | Page size (default `10`) |
        | `messageStatus` | query | no |  |
        | `customerNumber` | query | no |  |
        | `customerName` | query | no |  |
        | `receiverNumber` | query | no |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Catalog insights retrieved successfully. |
        | 400 | Invalid catalog ID or request parameters. |
        | 404 | Catalog not found. |
        | 500 | Internal server error. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_message_catalog_insights
      parameters:
      - name: catalog_Id
        in: query
        required: false
        schema:
          type: string
        example: WA_CATALOG_ID
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: messageStatus
        in: query
        required: false
        schema:
          type: string
      - name: customerNumber
        in: query
        required: false
        schema:
          type: string
      - name: customerName
        in: query
        required: false
        schema:
          type: string
      - name: receiverNumber
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /whatsapp/compliance-records:
    post:
      tags:
      - WhatsApp
      summary: '[operator] Create Compliance Rule'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Create a new compliance record

        Creates a new firewall compliance rule. ruleName must be unique. Requires ADMIN role authorization.

        **Notes for this request**

        Create a firewall rule. ruleName must be unique; statusCode = the Meta error code that triggers it (e.g. 131049). violationCategory ∈ QUALITY_OF_CONTENT|SPAM|POLICY_VIOLATION|RATE_LIMIT|AUTH|MEDIA_ABUSE|TEMPLATE_QUALITY|OTHER. restrictionType ∈ TEMPORARY_BLOCK|PERMANENT_BLOCK. Admin only.

        **Endpoint** `POST /compliance-records/`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Request body** `application/json` — `ComplianceRecordRequest`

        | Field | Type |
        |---|---|
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 201 | Compliance record created successfully |
        | 400 | Invalid request data or duplicate ruleName |
        | 401 | Unauthorized — invalid or missing username in header |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: post_whatsapp_compliance_records
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ruleName:
                  type: string
                description:
                  type: string
                statusCode:
                  type: string
                violationCategory:
                  type: string
                restrictionType:
                  type: string
                blockTemplate:
                  type: boolean
                blockAccount:
                  type: boolean
                blockDuration:
                  type: integer
                blockDurationUnit:
                  type: string
                attemptThreshold:
                  type: integer
                windowUnit:
                  type: string
                active:
                  type: boolean
            examples:
              '[operator] Create Compliance Rule':
                value:
                  ruleName: High spam rate auto-block
                  description: Temporarily block a WABA when spam complaints spike
                  statusCode: '131059'
                  violationCategory: SPAM
                  restrictionType: TEMPORARY_BLOCK
                  blockTemplate: false
                  blockAccount: true
                  blockDuration: 24
                  blockDurationUnit: HOURS
                  attemptThreshold: 5
                  windowUnit: MINUTES
                  active: true
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/search:
    post:
      tags:
      - WhatsApp
      summary: '[operator]  Search / List Rules'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Search / list compliance records

        Paginated, filtered, and sorted list of compliance records. All criteria are supplied in the request body — every field is optional. Free-text 'search' does a case-insensitive LIKE across ruleName, description and errorCode. Supports enum filters (violationCategory, restrictionType), boolean flags (active, blockTemplate, blockAccount), and a createdAt date range.

        **Notes for this request**

        Paginated, filtered, sorted list. Every filter is optional; free-text 'search' does a case-insensitive LIKE across ruleName/description/statusCode.

        **Endpoint** `POST /compliance-records/search`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Request body** `application/json` — `ComplianceRecordFilterRequest`

        | Field | Type |
        |---|---|
        | `search` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `restrictionType` | `RestrictionType` |
        | `active` | `Boolean` |
        | `blockTemplate` | `Boolean` |
        | `blockAccount` | `Boolean` |
        | `startDate` | `LocalDateTime` |
        | `endDate` | `LocalDateTime` |
        | `pageNumber` | `int` |
        | `pageSize` | `int` |
        | `sortBy` | `String` |
        | `sortDir` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Compliance records fetched successfully |
        | 400 | Bad filter parameters — e.g. startDate is after endDate |
        | 401 | Unauthorized |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: post_whatsapp_compliance_records_search
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                search:
                  type: string
                violationCategory: {}
                restrictionType: {}
                active:
                  type: boolean
                blockTemplate: {}
                blockAccount: {}
                startDate: {}
                endDate: {}
                pageNumber:
                  type: integer
                pageSize:
                  type: integer
                sortBy:
                  type: string
                sortDir:
                  type: string
            examples:
              '[operator]  Search / List Rules':
                value:
                  search: ''
                  violationCategory: null
                  restrictionType: null
                  active: true
                  blockTemplate: null
                  blockAccount: null
                  startDate: null
                  endDate: null
                  pageNumber: 0
                  pageSize: 20
                  sortBy: createdAt
                  sortDir: desc
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/{WA_COMPLIANCE_ID}:
    get:
      tags:
      - WhatsApp
      summary: '[operator] Get Rule by ID'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get compliance record by ID

        Fetch a single compliance record by its primary key.

        **Notes for this request**

        Fetch a single compliance rule by primary key.

        **Endpoint** `GET /compliance-records/{id}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `id` | path | yes | ID of the compliance record |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Compliance record fetched successfully |
        | 401 | Unauthorized |
        | 404 | Compliance record not found |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: get_whatsapp_compliance_records_WA_COMPLIANCE_ID
      parameters:
      - name: WA_COMPLIANCE_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_COMPLIANCE_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/update/{WA_COMPLIANCE_ID}:
    put:
      tags:
      - WhatsApp
      summary: '[operator] Update Rule'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update an existing compliance record

        Full update of a compliance record identified by id. ruleName uniqueness is re-validated (own record excluded). Requires ADMIN role.

        **Notes for this request**

        Full update of a compliance rule (ruleName uniqueness re-validated). Admin only.

        **Endpoint** `PUT /compliance-records/update/{id}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `id` | path | yes | ID of the compliance record to update |

        **Request body** `application/json` — `ComplianceRecordRequest`

        | Field | Type |
        |---|---|
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Compliance record updated successfully |
        | 400 | Invalid request data or duplicate ruleName |
        | 401 | Unauthorized — invalid or missing username in header |
        | 404 | Compliance record not found |
        | 500 | Internal server error |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `ComplianceRecordResponse`

        | Field | Type |
        |---|---|
        | `id` | `long` |
        | `ruleName` | `String` |
        | `description` | `String` |
        | `statusCode` | `String` |
        | `violationCategory` | `ViolationCategory` |
        | `blockTemplate` | `boolean` |
        | `blockAccount` | `boolean` |
        | `restrictionType` | `RestrictionType` |
        | `blockDuration` | `int` |
        | `blockDurationUnit` | `TimeUnitEnum` |
        | `attemptThreshold` | `int` |
        | `windowUnit` | `TimeUnitEnum` |
        | `active` | `boolean` |
        | `createdAt` | `LocalDateTime` |
      operationId: put_whatsapp_compliance_records_update_WA_COMPLIANCE_ID
      parameters:
      - name: WA_COMPLIANCE_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_COMPLIANCE_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ruleName:
                  type: string
                description:
                  type: string
                statusCode:
                  type: string
                violationCategory:
                  type: string
                restrictionType:
                  type: string
                blockTemplate:
                  type: boolean
                blockAccount:
                  type: boolean
                blockDuration:
                  type: integer
                blockDurationUnit:
                  type: string
                attemptThreshold:
                  type: integer
                windowUnit:
                  type: string
                active:
                  type: boolean
            examples:
              '[operator] Update Rule':
                value:
                  ruleName: High spam rate auto-block
                  description: Temporarily block a WABA when spam complaints spike
                  statusCode: '131049'
                  violationCategory: SPAM
                  restrictionType: TEMPORARY_BLOCK
                  blockTemplate: false
                  blockAccount: true
                  blockDuration: 24
                  blockDurationUnit: HOURS
                  attemptThreshold: 5
                  windowUnit: MINUTES
                  active: true
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/delete/{WA_COMPLIANCE_ID}:
    delete:
      tags:
      - WhatsApp
      summary: '[operator]  Delete Rule'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete a compliance record

        Permanently deletes a compliance record. Requires ADMIN role.

        **Notes for this request**

        Permanently delete a compliance rule. Admin only.

        **Endpoint** `DELETE /compliance-records/delete/{id}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `id` | path | yes | ID of the compliance record to delete |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 204 | Compliance record deleted successfully |
        | 401 | Unauthorized |
        | 404 | Compliance record not found |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: delete_whatsapp_compliance_records_delete_WA_COMPLIANCE_ID
      parameters:
      - name: WA_COMPLIANCE_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_COMPLIANCE_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/summary:
    get:
      tags:
      - WhatsApp
      summary: '[operator]  Dashboard Summary'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get compliance dashboard summary

        Returns total rules, temporary blocks, permanent blocks, warnings and active rules count.

        **Notes for this request**

        Totals: rules, temporary blocks, permanent blocks, warnings, active rules.

        **Endpoint** `GET /compliance-records/summary`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Summary fetched successfully |
        | 401 | Unauthorized |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `ComplianceSummaryResponse`

        | Field | Type |
        |---|---|
        | `totalRules` | `long` |
        | `temporaryBlocks` | `long` |
        | `permanentBlocks` | `long` |
        | `warnings` | `long` |
        | `activeRules` | `long` |
      operationId: get_whatsapp_compliance_records_summary
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/active-blocks:
    get:
      tags:
      - WhatsApp
      summary: '[operator]  List Active Blocks'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### List currently-active compliance blocks

        Returns one row per WABA that has an active block. Includes ruleId, ruleName, errorCode, scope flags (blockAccount/blockTemplate), triggeredAtMs, expiresAtMs (null for permanent), and a 'permanent' boolean. Used by the admin dashboard to show the firewall's current state. Requires ADMIN role.

        **Notes for this request**

        One row per WABA with an active block — ruleId, ruleName, statusCode, scope flags, triggeredAtMs, expiresAtMs (null = permanent). Admin only.

        **Endpoint** `GET /compliance-records/active-blocks`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Active blocks fetched successfully |
        | 401 | Unauthorized |
        | 500 | Internal server error |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
      operationId: get_whatsapp_compliance_records_active_blocks
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/compliance-records/unblock/{WA_WABA_ID}:
    post:
      tags:
      - WhatsApp
      summary: '[operator] Unblock Client'
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Manually clear a compliance block (admin override)

        Removes the active block entry for the given wabaId, restores OBC.status from BLOCKED to ACTIVE for every user sharing the WABA, and restores templates that were blocked by the same rule (TEMPORARY-block templates only — permanent banInfoJson is left for audit). Idempotent: returns NO_OP if no block was active. Requires ADMIN role.

        **Notes for this request**

        Clear the active block for a WABA, restore OBC.status BLOCKED→ACTIVE for every user on the WABA, and restore TEMPORARY-blocked templates. Idempotent (NO_OP if none active). Admin only.

        **Endpoint** `POST /compliance-records/unblock/{wabaId}`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `wabaId` | path | yes | WABA ID to unblock |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Unblock processed (see status field for UNBLOCKED|NO_OP) |
        | 400 | wabaId blank |
        | 401 | Unauthorized |
        | 500 | Internal server error |
        | 404 | Referenced resource not found for this tenant. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |

        **Response body** `UnblockResponse`

        | Field | Type |
        |---|---|
        | `wabaId` | `String` |
        | `triggeredBy` | `String` |
        | `status` | `String` |
        | `reason` | `String` |
        | `ruleId` | `Long` |
        | `ruleName` | `String` |
        | `errorCode` | `String` |
        | `obcRestored` | `Integer` |
        | `templatesRestored` | `Integer` |
      operationId: post_whatsapp_compliance_records_unblock_WA_WABA_ID
      parameters:
      - name: WA_WABA_ID
        in: path
        required: true
        schema:
          type: string
        example: WA_WABA_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /whatsapp/business-profile:
    get:
      tags:
      - WhatsApp
      summary: Get Business Profile
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get the WhatsApp Business Profile

        Retrieves the business profile (about, address, description, email, profile picture URL,
        websites, and vertical) of the tenant's phone number.

        **Endpoint** `GET /business-profile`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_business_profile
      responses:
        '200':
          description: OK
    put:
      tags:
      - WhatsApp
      summary: Update Business Profile
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Update the WhatsApp Business Profile

        Updates the business profile of the tenant's phone number.
        Only non-null fields in the request body are sent to Meta (partial update).

        **Endpoint** `PUT /business-profile`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `application/json` — `BusinessProfileRequest`

        | Field | Type |
        |---|---|
        | `about` | `String` |
        | `address` | `String` |
        | `description` | `String` |
        | `email` | `String` |
        | `vertical` | `String` |
        | `websites` | `List<String>` |
        | `profile_picture_handle` | `String` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: put_whatsapp_business_profile
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                about:
                  type: string
                address:
                  type: string
                description:
                  type: string
                email:
                  type: string
                vertical:
                  type: string
                websites:
                  type: array
                  items:
                    type: string
                profile_picture_handle:
                  type: string
            examples:
              Update Business Profile:
                value:
                  about: Best coffee in town
                  address: 123 Market St
                  description: Specialty roaster
                  email: hello@example.com
                  vertical: OTHER
                  websites:
                  - https://example.com
                  profile_picture_handle: '{{WA_MEDIA_ID}}'
      responses:
        '200':
          description: OK
  /whatsapp/profile-photo:
    post:
      tags:
      - WhatsApp
      summary: Upload & Set Profile Photo
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Upload and set the business profile photo

        multipart/form-data. 'file' = the image binary (image/jpeg or image/png, max 5 MB). Runs Meta's resumable upload to obtain a media handle, then sets it as the business profile picture. Returns {"handle":"…","success":true|false}.

        **Endpoint** `POST /profile-photo`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Parameters**

        | Name | In | Required | Description |
        |---|---|---|---|
        | `file` | query | yes | Binary file |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_profile_photo
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
            examples:
              Upload & Set Profile Photo:
                value:
                  file: bexeFbgho/brodnet.png
      responses:
        '200':
          description: OK
  /whatsapp/profile-photo/status:
    get:
      tags:
      - WhatsApp
      summary: Get Profile Photo Status
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Get the current business profile photo

        Reads the tenant's business profile and returns its current profile picture URL: {"profilePictureUrl":"…"} (null when no picture is set).

        **Endpoint** `GET /profile-photo/status`

        **Headers** `Authorization: Bearer <JWT>` · `username` · `ipAddress`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_profile_photo_status
      responses:
        '200':
          description: OK
  /whatsapp/block-users:
    get:
      tags:
      - WhatsApp
      summary: List Blocked Users
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### List blocked users

        Returns the WhatsApp users currently blocked for the caller's onboarded phone number.
        Served from the local mirror in milliseconds; pass refresh=true to force a live Meta sync.

        **Endpoint** `GET /block-users`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: get_whatsapp_block_users
      parameters:
      - name: refresh
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      responses:
        '200':
          description: OK
    post:
      tags:
      - WhatsApp
      summary: Block Users
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Block users

        Blocks one or more WhatsApp users on the caller's onboarded phone number.
        Returns Meta's added/failed breakdown.

        **Endpoint** `POST /block-users`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `application/json` — `BlockUsersRequest`

        | Field | Type |
        |---|---|
        | `users` | `List<String>` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: post_whatsapp_block_users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                users:
                  type: array
                  items:
                    type: string
            examples:
              Block Users:
                value:
                  users:
                  - '{{WA_DESTINATION_NO}}'
      responses:
        '200':
          description: OK
    delete:
      tags:
      - WhatsApp
      summary: Unblock Users
      description: |-
        **Authentication:** Header `Authorization: Bearer` `{{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Unblock users

        Unblocks one or more WhatsApp users on the caller's onboarded phone number.
        Returns Meta's removed/failed breakdown.

        **Endpoint** `DELETE /block-users`

        **Headers** `Authorization: Bearer <JWT>` · `ipAddress` · `username`

        **Request body** `application/json` — `BlockUsersRequest`

        | Field | Type |
        |---|---|
        | `users` | `List<String>` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. See the saved example for the response shape. |
        | 400 | Validation error (missing/invalid field, bad JSON, unknown id format). Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token, or the tenant is not allowed to perform this action. |
        | 502 | Meta Graph API rejected the call — `message` carries Meta's `code/subcode` and text. |
        | 500 | Unexpected server error (see `errorCode`). |
      operationId: delete_whatsapp_block_users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                users:
                  type: array
                  items:
                    type: string
            examples:
              Unblock Users:
                value:
                  users:
                  - '{{WA_DESTINATION_NO}}'
      responses:
        '200':
          description: OK
  /telegram/telegram-sender/save:
    post:
      tags:
      - Telegram
      summary: '[operator]  Save Sender'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Create Sender Master

        Creates a new Telegram sender profile for the given username.

        **Endpoint** `POST /telegram/telegram-sender/save`

        **Request body** `application/json`

        | Field | Type |
        | --- | --- |
        | `ID"` | `object` |
        | `apiId` | `object` |
        | `username"` | `object` |
        | `username` | `object` |
        | `Hash"` | `object` |
        | `apiHash` | `object` |
        | `number"` | `object` |
        | `phone` | `object` |
        | `Title"` | `object` |
        | `appTitle` | `object` |
        | `Shortname"` | `object` |
        | `5` | `object` |
        | `32` | `object` |
        | `appShortname` | `object` |
        | `255` | `object` |
        | `appUrl` | `object` |
        | `webhookUrl` | `object` |
        | `50` | `object` |
        | `appPlatform` | `object` |
        | `1000` | `object` |
        | `appDescription` | `object` |
        | `Code"` | `object` |
        | `systemLanguageCode` | `object` |
        | `Model"` | `object` |
        | `deviceModel` | `object` |
        | `Version"` | `object` |
        | `systemVersion` | `object` |
        | `applicationVersion` | `object` |
        | `Level"` | `object` |
        | `logVerbosityLevel` | `object` |
        | `Key"` | `object` |
        | `databaseEncryptionKey` | `object` |
        | `Database"` | `object` |
        | `fileDatabase` | `object` |
        | `chatInfoDatabase` | `object` |
        | `messageDatabase` | `object` |
        | `rateLimit` | `object` |
        | `Chats"` | `object` |
        | `secretChats` | `object` |
        | `reference"` | `object` |
        | `tierId` | `object` |
        | `fee"` | `object` |
        | `isPassthroughFee` | `object` |
        | `messages"` | `object` |
        | `applyToIncoming` | `object` |
        | `"0.0"` | `object` |
        | `subscriptionAmount` | `object` |
        | `otpRate` | `object` |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Sender created successfully |
        | 400 | Invalid request payload |
        | 409 | Sender already exists |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN`
      operationId: post_telegram_telegram_sender_save
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                appDescription:
                  type: string
                appPlatform:
                  type: string
                appShortname:
                  type: string
                appTitle:
                  type: string
                applicationVersion:
                  type: string
                applyToIncoming:
                  type: boolean
                databaseEncryptionKey:
                  type: string
                isPassthroughFee:
                  type: boolean
                otpRate:
                  type: number
                phone:
                  type: string
                rateLimit:
                  type: integer
                apiHash:
                  type: string
                subscriptionAmount:
                  type: integer
                tierId:
                  type: integer
                username:
                  type: string
                webhookUrl:
                  type: string
            examples:
              '[operator]  Save Sender':
                value:
                  appDescription: this is discription for broadnet
                  appPlatform: ANDROID
                  appShortname: shortuser27
                  appTitle: test404j
                  applicationVersion: 1.0.0
                  applyToIncoming: true
                  databaseEncryptionKey: wriuuuu
                  isPassthroughFee: true
                  otpRate: 0.001
                  phone: '+447700900108'
                  rateLimit: 60
                  apiHash: ''
                  subscriptionAmount: 5
                  tierId: 15
                  username: TEST104
                  webhookUrl: https://example.com/
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-sender/id:
    put:
      tags:
      - Telegram
      summary: '[operator] Update Sender'
      description: |
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Update Sender Master

        Updates an existing Telegram sender profile using sender ID.

        **Endpoint** `PUT /telegram/telegram-sender/id`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | query | yes | Sender ID |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `ID"` | `object` |
        | `apiId` | `object` |
        | `username"` | `object` |
        | `username` | `object` |
        | `Hash"` | `object` |
        | `apiHash` | `object` |
        | `number"` | `object` |
        | `phone` | `object` |
        | `Title"` | `object` |
        | `appTitle` | `object` |
        | `Shortname"` | `object` |
        | `5` | `object` |
        | `32` | `object` |
        | `appShortname` | `object` |
        | `255` | `object` |
        | `appUrl` | `object` |
        | `webhookUrl` | `object` |
        | `50` | `object` |
        | `appPlatform` | `object` |
        | `1000` | `object` |
        | `appDescription` | `object` |
        | `Code"` | `object` |
        | `systemLanguageCode` | `object` |
        | `Model"` | `object` |
        | `deviceModel` | `object` |
        | `Version"` | `object` |
        | `systemVersion` | `object` |
        | `applicationVersion` | `object` |
        | `Level"` | `object` |
        | `logVerbosityLevel` | `object` |
        | `Key"` | `object` |
        | `databaseEncryptionKey` | `object` |
        | `Database"` | `object` |
        | `fileDatabase` | `object` |
        | `chatInfoDatabase` | `object` |
        | `messageDatabase` | `object` |
        | `rateLimit` | `object` |
        | `Chats"` | `object` |
        | `secretChats` | `object` |
        | `reference"` | `object` |
        | `tierId` | `object` |
        | `fee"` | `object` |
        | `isPassthroughFee` | `object` |
        | `messages"` | `object` |
        | `applyToIncoming` | `object` |
        | `"0.0"` | `object` |
        | `subscriptionAmount` | `object` |
        | `otpRate` | `object` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Sender updated successfully |
        | 404 | Sender not found |
        | 400 | Validation error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `SUPER_TOKEN`
      operationId: put_telegram_telegram_sender_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: SENDER_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                apiId:
                  type: string
                appDescription:
                  type: string
                appPlatform:
                  type: string
                appShortname:
                  type: string
                appTitle:
                  type: string
                appUrl:
                  type: string
                applicationVersion:
                  type: string
                applyToIncoming:
                  type: boolean
                chatInfoDatabase:
                  type: boolean
                deviceModel:
                  type: string
                fileDatabase:
                  type: boolean
                isPassthroughFee:
                  type: boolean
                logVerbosityLevel:
                  type: integer
                messageDatabase:
                  type: boolean
                otpRate:
                  type: number
                phone:
                  type: string
                rateLimit:
                  type: integer
                secretChats:
                  type: boolean
                subscriptionAmount:
                  type: integer
                systemLanguageCode:
                  type: string
                systemVersion:
                  type: string
                testDc:
                  type: boolean
                tierId:
                  type: integer
                webhookUrl:
                  type: string
            examples:
              '[operator] Update Sender':
                value:
                  apiId: ''
                  appDescription: this is discription for broadnet acme
                  appPlatform: ANDROID
                  appShortname: shortuser27
                  appTitle: test404j
                  appUrl: ''
                  applicationVersion: 1.0.0
                  applyToIncoming: true
                  chatInfoDatabase: false
                  deviceModel: ''
                  fileDatabase: false
                  isPassthroughFee: true
                  logVerbosityLevel: 0
                  messageDatabase: false
                  otpRate: 0.001
                  phone: '+447700900108'
                  rateLimit: 60
                  secretChats: false
                  subscriptionAmount: 5
                  systemLanguageCode: en
                  systemVersion: ''
                  testDc: false
                  tierId: 15
                  webhookUrl: https://example.com/
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    get:
      tags:
      - Telegram
      summary: '[operator] GET Sender By Id'
      description: |
        **System_Token -** used by super admin and system roles to perform provider functionality.he API gateway answers 401 for user access tokens.

        ### Get Sender Master by ID

        Fetches sender configuration using sender ID.

        **Endpoint** `GET /telegram/telegram-sender/id`

        **Parameters**

        | Name | In | Required | Notes |
        | --- | --- | --- | --- |
        | `id` | query | yes | Sender ID |

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Sender found |
        | 404 | Sender not found |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `SUPER_TOKEN`
      operationId: get_telegram_telegram_sender_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: SENDER_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
    delete:
      tags:
      - Telegram
      summary: '[operator] Delete Sender'
      description: |
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Delete Sender Master

        Deletes a Telegram sender profile using sender ID.

        **Endpoint** `DELETE /telegram/telegram-sender/id`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | query | yes | Sender ID |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Sender deleted successfully |
        | 404 | Sender not found |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `SUPER_TOKEN`
      operationId: delete_telegram_telegram_sender_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: SENDER_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-sender/me:
    get:
      tags:
      - Telegram
      summary: '[operator] Get ME'
      description: |-
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        ### Get My Sender Master

        Returns the sender profile associated with the given username.

        **Endpoint** `GET /telegram/telegram-sender/me`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Sender found |
        | 404 | Sender not found |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---

        ### Auth

        This collection uses two tokens:

        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.

        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).


        **This request uses:** `SUPER_TOKEN , ACCESS_TOKEN`
      operationId: get_telegram_telegram_sender_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-sender:
    get:
      tags:
      - Telegram
      summary: '[operator] Get All Senders'
      description: |
        **Operator (super) token required** — the API gateway answers 401 for tenant tokens.

        List all senders visible to the caller (paged).

        ### List Sender Masters

        Returns a paginated list of sender profiles with optional search and date range filters.

        **Endpoint** `GET /telegram/telegram-sender`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `search` | query | no | Search by phone, app title, or shortname |
        | `startDate` | query | no | Start date (ISO-8601) |
        | `endDate` | query | no | End date (ISO-8601) |
        | `toGmt` | query | no | Convert date range to GMT |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Sender masters retrieved successfully |
        | 400 | Invalid request parameters |
        | 404 | No sender masters found |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `SUPER_TOKEN`
      operationId: get_telegram_telegram_sender
      parameters:
      - name: search
        in: query
        required: false
        schema:
          type: string
        example: '9329933429'
      - name: startDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-14T00:00:00.000'
      - name: endDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-09-14T23:59:59.999'
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
        example: GMT+05:30#1
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-client/send-password:
    post:
      tags:
      - Telegram
      summary: '[operator] Send Password'
      description: |
        **Access token required** — use the tenant `ACCESS_TOKEN`.

        Request the Telegram login code (sends SMS/Telegram message).

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_client_send_password
      parameters:
      - name: phoneNumber
        in: query
        required: false
        schema:
          type: string
        example: PHONE_NUMBER
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-client/login:
    post:
      tags:
      - Telegram
      summary: '[operator] Login'
      description: |
        **Access token required** — use the tenant `ACCESS_TOKEN`.

        Complete login with the OTP code (+ optional 2FA password).

        ### Login using phone and code/password

        Completes the Telegram login using phone number, password/code, and login hash.

        **Endpoint** `POST /telegram/telegram-client/login`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `phone` | `string` |
        | `authHash` | `object` |
        | `"\\d{5` | `object` |
        | `authPassword` | `object` |
        | `rememberMe` | `boolean` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_client_login
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phoneNumber:
                  type: string
                code:
                  type: string
                password:
                  type: string
            examples:
              '[operator] Login':
                value:
                  phoneNumber: '{{PHONE_NUMBER}}'
                  code: '12345'
                  password: ''
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-client/apps:
    get:
      tags:
      - Telegram
      summary: '[operator] Get Apps'
      description: |
        **Access token required** — use the tenant `ACCESS_TOKEN`.

        List apps/configs registered for this tenant.

        ### Fetch existing Telegram app configuration

        Fetches Telegram app details (API ID, hash, public keys, etc.) after successful login.

        **Endpoint** `GET /telegram/telegram-client/apps`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `phone` | query | yes | Telegram phone number used to retrieve stored login/session information |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_client_apps
      parameters:
      - name: phone
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-client/create:
    post:
      tags:
      - Telegram
      summary: '[operator] Create New App'
      description: |
        **Access token required** — use the tenant `ACCESS_TOKEN`.

        Register a new Telegram app/client for this tenant.

        ### Create a new Telegram app

        Registers a new Telegram app with the provided title, shortname, platform, and description.

        **Endpoint** `POST /telegram/telegram-client/create`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `id` | `integer` |
        | `/apps"` | `object` |
        | `authHash` | `object` |
        | `title"` | `object` |
        | `64` | `object` |
        | `appTitle` | `object` |
        | `5` | `object` |
        | `32` | `object` |
        | `appShortname` | `object` |
        | `bot"` | `object` |
        | `2048` | `object` |
        | `appUrl` | `object` |
        | `type"` | `object` |
        | `appPlatform` | `object` |
        | `description"` | `object` |
        | `512` | `object` |
        | `appDescription` | `object` |
        | `{}` | `object` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_client_create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                appName:
                  type: string
                phoneNumber:
                  type: string
                apiId:
                  type: string
                apiHash:
                  type: string
            examples:
              '[operator] Create New App':
                value:
                  appName: BroadNet-TG
                  phoneNumber: '{{PHONE_NUMBER}}'
                  apiId: '{{TG_APP_ID}}'
                  apiHash: <api-hash>
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/telegram-client/update:
    put:
      tags:
      - Telegram
      summary: '[operator] Update App'
      description: |
        **Access token required** — use the tenant `ACCESS_TOKEN`.

        ### Update existing sender configuration

        Updates configuration details for an already registered Telegram sender.

        **Endpoint** `PUT /telegram/telegram-client/update`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | query | yes | Sender ID whose configuration needs to be updated |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `apiId` | `integer` |
        | `authHash` | `string` |
        | `appTitle` | `string` |
        | `appShortname` | `string` |
        | `phone` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: put_telegram_telegram_client_update
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                appId:
                  type: string
                appName:
                  type: string
            examples:
              '[operator] Update App':
                value:
                  appId: '{{TG_APP_ID}}'
                  appName: BroadNet-TG-2
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /telegram/session/status:
    get:
      tags:
      - Telegram
      summary: Session Authorization Section
      description: |
        The **Telegram Session Authorization Status API** verifies whether a Telegram client session associated with an authenticated user is fully authorized and ready for operation.

        This endpoint performs a direct validation against the underlying TDLib session and returns a simplified, binary authentication result. It confirms whether the login process has been successfully completed and whether the session is capable of sending or receiving Telegram messages.

        Unlike the Session State API (which exposes detailed lifecycle states), this endpoint is designed for operational checks and returns a clean authorization outcome suitable for production validation and monitoring.

        ---

        ## Core Behavior

        When invoked, the API performs the following checks:

        1. Retrieves the Telegram session mapped to the authenticated user

        2. Validates that a session exists

        3. Evaluates the TDLib authorization flag (`haveAuthorization()`)

        4. Returns a simplified authorization status


        This ensures that only properly authenticated sessions are allowed to proceed with Telegram operations.

        ---

        ## Response Values

        The API returns a plain-text response: `AUTHORIZED`

        The Telegram session is fully authenticated and ready for message operations.

        ### `NOT_AUTHORIZED`

        The session exists but has not completed the required authentication steps.

        If no active session is found for the user, the API returns an error instructing the client to initiate a session connection first.

        ---

        ## Operational Significance

        This endpoint is commonly used for:

        - Pre-validation before sending Telegram messages

        - Health-check validation of Telegram connectivity

        - Automated monitoring of session readiness

        - Production-level authentication verification


        By confirming authorization status in advance, this API helps prevent runtime message failures caused by incomplete, expired, or invalid authentication sessions.

        ---

        ## Technical Specifications

        - **HTTP Method:** `GET`

        - **Endpoint:** `/telegram/session/status`

        - **Response Type:** Plain text (`AUTHORIZED` or `NOT_AUTHORIZED`)

        - **Security:** Requires a valid authenticated request and mapped Telegram session

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_session_status
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                variables:
                  type: string
            examples:
              Session Authorization Section:
                value:
                  query: ''
                  variables: ''
      responses:
        '200':
          description: OK
  /telegram/session/state:
    get:
      tags:
      - Telegram
      summary: Session Authorization State
      description: |
        The Telegram Session Authorization State API returns the current authentication state of a Telegram client session for the authenticated user.

        This endpoint is a **critical checkpoint** in the onboarding flow. After connecting a session via `POST /telegram-sandbox/connect`, this API tells you exactly what Telegram requires next — whether it is an OTP, email verification, 2FA password, or if the session is already fully authenticated and ready for go-live.

        Unlike the Authorization Status API which returns a binary result, this endpoint provides detailed lifecycle insight into every stage of the Telegram login flow.

        📌 **When to call this API:** Wait **1 minute** after calling `POST /telegram-sandbox/connect`, then call this API. Based on the state returned, proceed with the appropriate verification step. Keep calling this API after each verification step until the state returns `READY`.

        **How It Works**

        | # | Description |
        | --- | --- |
        | 1 | Retrieves the Telegram session mapped to the authenticated user |
        | 2 | Validates that an active session exists for the user |
        | 3 | Reads the current `ClientAuthorizationState` from TDLib |
        | 4 | Maps the internal TDLib state to a standardized plain-text response |
        | 5 | Returns the current session state |

        **Possible Session States**

        | State | Meaning | Action Required |
        | --- | --- | --- |
        | `WAIT_CODE` | Telegram has sent a verification OTP | Call `POST /telegram/session/code?code={code}` |
        | `WAIT_PASSWORD` | Telegram is requesting 2FA password | Call `POST /telegram/session/password` |
        | `WAIT_EMAIL_ADDRESS` | Telegram requires email address | Call `POST /telegram/session/email` |
        | `WAIT_EMAIL_CODE` | Telegram has sent a code to your email | Call `POST /telegram/session/email-code` |
        | `WAIT_PHONE_NUMBER` | Telegram requires phone number confirmation | Call phone verification API |
        | `WAIT_OTHER_DEVICE_CONFIRMATION` | Confirmation required from another logged-in device | Confirm on another active Telegram device |
        | `WAIT_REGISTRATION` | Phone number is not registered on Telegram | Create a Telegram account for this number first |
        | `WAIT_TDLIB_PARAMETERS` | TDLib is still initializing | Wait a few seconds and retry |
        | `READY` | Session is fully authenticated | Proceed to `POST /telegram/golive` |
        | `LOGGING_OUT` | Session is logging out | Wait or reinitialize the session |
        | `CLOSING` | Session is closing | Reconnect via `POST /telegram-sandbox/connect` |
        | `CLOSED` | Session has been terminated | Reconnect via `POST /telegram-sandbox/connect` |
        | `AUTH_TIMEOUT` | Authentication process timed out | Reconnect and restart the flow |
        | `UNKNOWN_STATE` | State could not be determined | Retry or contact support |

        **Response — 200 OK**

        ```
        READY

         ```

        **Operational Purpose**

        This API plays a critical role in:

        - Monitoring the Telegram authentication lifecycle at every stage

        - Determining which verification step is required next — OTP, email, or 2FA password

        - Preventing go-live activation during incomplete authentication

        - Detecting session termination or logout events in real time

        - Ensuring the session is fully `READY` before executing any messaging or go-live operations


        📌 **Note:** If no active session exists for the specified user, the API returns a `400` error — `No session available. Please connect first.` Ensure `POST /telegram-sandbox/connect` has been called before invoking this endpoint.

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | State returned successfully | Session exists and state is readable |
        | 400 | No session available. Please connect first. | Session not initialized — call `POST /telegram-sandbox/connect` first |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 500 | Failed to get authorization state | Internal TDLib error or session client unavailable |

        🔜 **Next Step:** Call the appropriate verification API based on the state returned. Once this API returns `READY`, proceed to `POST /telegram/golive` to activate your Telegram sender in LIVE mode.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_session_state
      responses:
        '200':
          description: OK
  /telegram/session/register:
    post:
      tags:
      - Telegram
      summary: Telegram Registration
      description: |
        The Complete Telegram Registration API submits the user's first and last name to Telegram to complete the account registration process.

        This API is called **only when** `GET /telegram/session/state` returns `WAIT_REGISTRATION` — meaning the phone number being used is not yet registered on Telegram and requires a new account to be created before the session can proceed.

        **Important:** Do not call this API directly. Always check `GET /telegram/session/state` first. Only call this API if the state returns `WAIT_REGISTRATION`. This is a rare scenario — it occurs only when the phone number has never been registered on Telegram.

        **Purpose**

        - Completes the Telegram account registration for a new, unregistered phone number

        - Submits the user's first and last name to create a new Telegram account

        - Moves the session forward after successful registration


        **Query Parameters**

        | Param | Required | Description |
        | --- | --- | --- |
        | `firstName` | ✅ Yes | First name for the new Telegram account. Must be between 1–64 characters. Example: `alex` |
        | `lastName` | ❌ Optional | Last name for the new Telegram account. Can be empty. Maximum 64 characters. Example: `morgan` |

        **Request Headers**

        | Header | Required | Description |
        | --- | --- | --- |
        | `ipAddress` | ✅ Yes | Client IP address making the request. Example: `203.0.113.10` |
        | `username` | ✅ Yes | Username of the authenticated user. Example: `alex.morgan` |

        **When This API Is Required**

        | # | Condition |
        | --- | --- |
        | 1 | A login session has already been initiated via `POST /telegram-sandbox/connect` |
        | 2 | `GET /telegram/session/state` has returned `WAIT_REGISTRATION` |
        | 3 | The phone number being used is not registered on Telegram |

        **Behavior & Validation**

        | # | Rule |
        | --- | --- |
        | 1 | A valid Telegram session must already exist before calling this API |
        | 2 | The session state must be `WAIT_REGISTRATION` — confirmed via `GET /telegram/session/state` |
        | 3 | `firstName` is mandatory and must be between 1–64 characters |
        | 4 | `lastName` is optional — can be left empty |
        | 5 | After successful registration, always call `GET /telegram/session/state` to confirm the updated state |

        **Authentication Flow Context**

        | Step | Action | API |
        | --- | --- | --- |
        | 1 | Connect Session | `POST /telegram-sandbox/connect` |
        | 2 | Check Session State | `GET /telegram/session/state` |
        | 3 | Submit Authentication Code _(if_ `_WAIT_CODE_`_)_ | `POST /telegram/session/code` |
        | 4 | Check Session State Again | `GET /telegram/session/state` |
        | **5** | **Complete Registration** _**(if**_ `_**WAIT_REGISTRATION**_`_**)**_ | **`POST /telegram/session/register`** **← You are here** |
        | 6 | Check Session State Again | `GET /telegram/session/state` |
        | 7 | Go Live _(when_ `_READY_`_)_ | `POST /telegram/golive` |

        ⚠️ **Important:** A successful response only confirms that registration details were submitted. Always call `GET /telegram/session/state` after this API to confirm the updated state before proceeding.

        🔜 **Next Step:** After submitting registration details, call `GET /telegram/session/state` to check the updated state. Once the state returns `READY`, proceed to `POST /telegram/golive` to activate your Telegram sender in LIVE mode.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_session_register
      parameters:
      - name: firstName
        in: query
        required: false
        schema:
          type: string
        example: alex
      - name: lastName
        in: query
        required: false
        schema:
          type: string
        example: morgan
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              Telegram Registration:
                value: ''
      responses:
        '200':
          description: OK
  /telegram/session/password:
    post:
      tags:
      - Telegram
      summary: Verify 2FA Password
      description: |
        The Verify Telegram 2FA Password API submits the Two-Step Verification password to complete the session login process.

        This API is called **only when** `GET /telegram/session/state` returns `WAIT_PASSWORD` — meaning your Telegram account has Two-Step Verification enabled and requires a password before the session can be fully authenticated.

        **Important:** Do not call this API directly. Always check `GET /telegram/session/state` first. Only call this API if the state returns `WAIT_PASSWORD`.

        **Purpose**

        - Submits the 2FA password to TDLib to complete the session authentication process

        - Finalizes session authorization when Two-Step Verification is enabled on the Telegram account

        - Moves the session forward — after successful verification, session state transitions to `READY`


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that a Telegram session already exists for the given user |
        | 2 | Confirms the current session state is `WAIT_PASSWORD` |
        | 3 | Submits the provided 2FA password to TDLib |
        | 4 | Completes the session login process upon successful verification |
        | 5 | Rejects the request if no active session is found |

        **When This API Is Required**

        | # | Condition |
        | --- | --- |
        | 1 | A login session has already been initiated via `POST /telegram-sandbox/connect` |
        | 2 | `GET /telegram/session/state` has returned `WAIT_PASSWORD` |
        | 3 | The Telegram account has Two-Step Verification (2FA) enabled |

        **Behavior & Validation**

        | # | Rule |
        | --- | --- |
        | 1 | A valid Telegram session must already exist before calling this API |
        | 2 | The session state must be `WAIT_PASSWORD` — checked via `GET /telegram/session/state` |
        | 3 | The provided password must match the 2FA password configured in the Telegram account |
        | 4 | If no session exists, the request is rejected immediately |
        | 5 | If the password is incorrect, verification fails |
        | 6 | After successful verification, always call `GET /telegram/session/state` to confirm the updated state |

        **Response — 200 OK**

        ```
        Password submitted for session: alex.morgan

         ```

        ⚠️ **Important:** A `200` response only confirms the password was submitted — it does not confirm authentication is complete. Always call `GET /telegram/session/state` after this API to check the current state.

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Password submitted successfully | Correct 2FA password provided |
        | 400 | No session available. Please connect first. | Session not initialized before password submission |
        | 400 | Invalid password | Incorrect 2FA password provided |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 500 | Failed to verify authentication password | Telegram verification failure or internal processing error |

        **Authentication Flow Context**

        | Step | Action | API |
        | --- | --- | --- |
        | 1 | Connect Session | `POST /telegram-sandbox/connect` |
        | 2 | Check Session State | `GET /telegram/session/state` |
        | 3 | Submit Authentication Code _(if_ `_WAIT_CODE_`_)_ | `POST /telegram/session/code` |
        | 4 | Check Session State Again | `GET /telegram/session/state` |
        | **5** | **Submit 2FA Password** _**(if**_ `_**WAIT_PASSWORD**_`_**)**_ | **`POST /telegram/session/password`** **← You are here** |
        | 6 | Check Session State Again | `GET /telegram/session/state` |
        | 7 | Go Live _(when_ `_READY_`_)_ | `POST /telegram/golive` |

        🔜 **Next Step:** After submitting the 2FA password, call `GET /telegram/session/state` to check the updated session state. If the state returns `READY`, proceed to `POST /telegram/golive` to activate your Telegram sender in LIVE mode.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_session_password
      parameters:
      - name: password
        in: query
        required: false
        schema:
          type: string
        example: PASSWORD
      responses:
        '200':
          description: OK
  /telegram/session/email:
    post:
      tags:
      - Telegram
      summary: Verify Email Address
      description: |
        The Verify Telegram Email Address API submits the email address to Telegram (TDLib) when email verification is required during the authentication process.

        This API is called **only when** `GET /telegram/session/state` returns `WAIT_EMAIL_ADDRESS` — meaning Telegram has requested email verification as part of enhanced account security during login.

        **Important:** Do not call this API directly. Always check `GET /telegram/session/state` first. Only call this API if the state returns `WAIT_EMAIL_ADDRESS`. If Telegram does not require email verification, this step is automatically skipped.

        **Purpose**

        - Submits the email address associated with the Telegram account to TDLib

        - Handles the email verification step in the authentication flow

        - Moves the session forward — after successful submission, Telegram will send a verification code to the provided email


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that a Telegram session is already initialized for the given user |
        | 2 | Confirms the current session state is `WAIT_EMAIL_ADDRESS` |
        | 3 | Submits the provided email address to TDLib |
        | 4 | Continues the authentication process upon successful verification |
        | 5 | Rejects the request if no active session exists |

        **When This API Is Required**

        | # | Condition |
        | --- | --- |
        | 1 | A login session has already been initiated via `POST /telegram-sandbox/connect` |
        | 2 | `GET /telegram/session/state` has returned `WAIT_EMAIL_ADDRESS` |
        | 3 | Telegram has explicitly requested email verification during login |

        **Behavior & Validation**

        | # | Rule |
        | --- | --- |
        | 1 | A valid Telegram session must already exist before calling this API |
        | 2 | The session state must be `WAIT_EMAIL_ADDRESS` — confirmed via `GET /telegram/session/state` |
        | 3 | The email address submitted must be the one associated with the Telegram account |
        | 4 | If no session exists, the request is rejected immediately |
        | 5 | Invalid or mismatched email submissions will cause verification failure |
        | 6 | After successful submission, Telegram will send a verification code to the email — check session state again to confirm next step |

        **Response — 200 OK**

        ```
        Email submitted for session: alex.morgan

         ```

        ⚠️ **Important:** A `200` response only confirms the email was submitted — it does not confirm authentication is complete. Always call `GET /telegram/session/state` after this API to check the updated state. If the state returns `WAIT_EMAIL_CODE`, proceed to submit the email verification code.

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Email submitted successfully | Email verification step accepted |
        | 400 | No session available. Please connect first. | Session not initialized before email submission |
        | 400 | Invalid email state | Email not expected at this stage — session state is not `WAIT_EMAIL_ADDRESS` |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 500 | Failed to verify email address | Telegram verification failure or internal processing error |

        **Authentication Flow Context**

        | Step | Action | API |
        | --- | --- | --- |
        | 1 | Connect Session | `POST /telegram-sandbox/connect` |
        | 2 | Check Session State | `GET /telegram/session/state` |
        | 3 | Submit Authentication Code _(if_ `_WAIT_CODE_`_)_ | `POST /telegram/session/code` |
        | 4 | Check Session State Again | `GET /telegram/session/state` |
        | 5 | Submit 2FA Password _(if_ `_WAIT_PASSWORD_`_)_ | `POST /telegram/session/password` |
        | 6 | Check Session State Again | `GET /telegram/session/state` |
        | **7** | **Submit Email Address** _**(if**_ `_**WAIT_EMAIL_ADDRESS**_`_**)**_ | **`POST /telegram/session/email`** **← You are here** |
        | 8 | Check Session State Again | `GET /telegram/session/state` |
        | 9 | Go Live _(when_ `_READY_`_)_ | `POST /telegram/golive` |

        🔜 **Next Step:** After submitting the email address, call `GET /telegram/session/state` to check the updated state. If the state returns `WAIT_EMAIL_CODE`, submit the verification code sent to your email. Once the state returns `READY`, proceed to `POST /telegram/golive`.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_session_email
      parameters:
      - name: email
        in: query
        required: false
        schema:
          type: string
        example: user%40example.com
      responses:
        '200':
          description: OK
  /telegram/session/code:
    post:
      tags:
      - Telegram
      summary: Verify Authentication Code
      description: |
        The Verify Telegram Authentication Code API submits the 5 or 6-digit authentication code received from Telegram — via SMS or another logged-in device — to complete the TDLib session login process.

        Think of this as the key that unlocks your session — once you submit the correct code, your Telegram session moves forward in the authorization process. However, submitting the code alone does not confirm that authentication is complete. You must check the session state after submission to know what Telegram requires next.

        **Important:** This API must be called **only when** `GET /telegram/session/state` returns `WAIT_CODE`. Do not call this API independently or before checking the session state.

        **Purpose**

        - Submits the OTP received on your Telegram account to verify and authenticate the current session

        - Validates the code through TDLib to continue the Telegram authorization process

        - Moves the session forward — either completing authentication or prompting for the next verification step


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that a Telegram session is already initialized for the given username |
        | 2 | Confirms the current session state is `WAIT_CODE` before accepting the code |
        | 3 | Submits the provided authentication code to TDLib |
        | 4 | Continues the Telegram login process upon successful verification |
        | 5 | Rejects the request if no active session exists |

        **When This API Is Required**

        | # | Condition |
        | --- | --- |
        | 1 | A login session has already been initiated via `POST /telegram-sandbox/connect` |
        | 2 | `GET /telegram/session/state` has returned `WAIT_CODE` |
        | 3 | Telegram has sent a 5 or 6-digit authentication code to your registered phone number |

        **Behavior & Validation**

        | # | Rule |
        | --- | --- |
        | 1 | A valid Telegram session must already exist before calling this API |
        | 2 | The code must be exactly 5 or 6 digits as received from Telegram |
        | 3 | If no session is available, the request is rejected immediately |
        | 4 | If the Telegram client state is invalid or inactive, verification fails |
        | 5 | Submitting the code does not guarantee authentication is complete — always check session state after submission |

        **Query Parameter**

        | Param | Required | Description |
        | --- | --- | --- |
        | `code` | ✅ Yes | The 5 or 6-digit OTP received on your Telegram account. Must be entered exactly as received — no spaces, no modifications |

        📌 **Note:** The code is session-specific and expires after a short period. If the code expires before submission, reconnect via `POST /telegram-sandbox/connect` and restart the flow.

        **Response — 200 OK**

        ```
        Code submitted for session: super

         ```

        ⚠️ **Important:** A `200` response only confirms the code was submitted — it does not confirm authentication is complete. Always call `GET /telegram/session/state` after this API to check the current state.

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Code submitted successfully | Code accepted and forwarded to TDLib |
        | 400 | No session available. Please connect first. | Session not initialized before code submission |
        | 400 | Invalid code format | Code is not 5–6 digits |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 500 | Failed to verify authentication code | Telegram client not active or internal processing failure |
        | 500 | No active Telegram clients available | Session client not properly initialized |

        **Authentication Flow Context**

        | Step | Action | API |
        | --- | --- | --- |
        | 1 | Connect Session | `POST /telegram-sandbox/connect` |
        | 2 | Check Session State | `GET /telegram/session/state` |
        | **3** | **Submit Authentication Code** | **`POST /telegram/session/code`** **← You are here** |
        | 4 | Check Session State Again | `GET /telegram/session/state` |
        | 5 | Submit 2FA Password _(if_ `_WAIT_PASSWORD_`_)_ | `POST /telegram/session/password` |
        | 6 | Submit Email _(if_ `_WAIT_EMAIL_ADDRESS_`_)_ | `POST /telegram/session/email` |
        | 7 | Go Live _(when_ `_READY_`_)_ | `POST /telegram/golive` |

        🔜 **Next Step:** After submitting the code, call `GET /telegram/session/state` to check the updated session state. If the state returns `READY`, proceed to `POST /telegram/golive`. If Telegram requests additional verification, complete the respective step first.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_session_code
      parameters:
      - name: code
        in: query
        required: false
        schema:
          type: string
        example: '77344'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
            examples:
              Verify Authentication Code:
                value: ''
      responses:
        '200':
          description: OK
  /telegram/golive:
    post:
      tags:
      - Telegram
      summary: Go Live Session
      description: |
        The Go Live Session API activates the Telegram sender in **LIVE mode**. Once activated, the sender becomes fully operational in the production environment and can send and receive real-time Telegram messages.

        This API is called **only when** `GET /telegram/session/state` returns `READY` — meaning all authentication and verification steps have been successfully completed and the session is fully authorized.

        **Important:** Do not call this API directly. Always check `GET /telegram/session/state` first. Only call this API when the state returns `READY`. If 2FA, email verification, or any other verification step was requested by Telegram during authentication, those must be completed first.

        **Purpose**

        - Activates the Telegram sender account in `LIVE` mode on the OmniInbox platform

        - Makes the Telegram client fully operational in the production environment

        - Performs all necessary system-level updates to ensure the sender is ready for real-time messaging


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that the sender exists in the system |
        | 2 | Ensures the sender account status is `ACTIVE` |
        | 3 | Confirms that `GET /telegram/session/state` has returned `READY` |
        | 4 | Checks whether the sender is already operating in `LIVE` mode |
        | 5 | If already `LIVE` — returns a confirmation response without making any changes |
        | 6 | If not `LIVE` — updates the sender configuration to enable `LIVE` mode |
        | 7 | Refreshes the Telegram client instance |
        | 8 | Reloads queue processor configuration |
        | 9 | Reattaches webhook URL if configured |
        | 10 | Saves the updated sender state in the database |
        | 11 | Logs activation activity for audit purposes |

        **Mode Activation Logic**

        | Current State | Action Taken |
        | --- | --- |
        | Not `LIVE` | Sender is converted to `LIVE` mode |
        | Already `LIVE` | No change — confirmation response returned |
        | `INACTIVE` | Request is rejected — ensure sender is `ACTIVE` before calling this API |

        **System Updates Performed on Activation**

        | Component | Action |
        | --- | --- |
        | Sender Mode Flag | Updated to `LIVE` |
        | Database | Sender configuration persisted |
        | In-Memory Cache | Sender cache refreshed |
        | Telegram Client | Instance reinitialized |
        | Queue Processor | Configuration reloaded |
        | Webhook | Reapplied if configured |
        | Audit Log | Activation event logged with username and IP address |

        **Authentication Flow Context**

        | Step | Action | API |
        | --- | --- | --- |
        | 1 | Connect Session | `POST /telegram-sandbox/connect` |
        | 2 | Check Session State | `GET /telegram/session/state` |
        | 3 | Submit Authentication Code _(if_ `_WAIT_CODE_`_)_ | `POST /telegram/session/code` |
        | 4 | Check Session State Again | `GET /telegram/session/state` |
        | 5 | Submit 2FA Password _(if_ `_WAIT_PASSWORD_`_)_ | `POST /telegram/session/password` |
        | 6 | Submit Email Address _(if_ `_WAIT_EMAIL_ADDRESS_`_)_ | `POST /telegram/session/email` |
        | 7 | Complete Registration _(if_ `_WAIT_REGISTRATION_`_)_ | `POST /telegram/session/register` |
        | 8 | Check Session State Again | `GET /telegram/session/state` |
        | **9** | **GO LIVE** _**(only when**_ `_**READY**_`_**)**_ | **`POST /telegram/golive`** **← You are here** |

        **Response — 200 OK (Activated)**

        ``` json
        {
          "apiId": 24866922,
          "status": "LIVE",
          "message": "Sender successfully activated to LIVE mode.",
          "updatedBy": "super",
          "ipAddress": "203.0.113.10",
          "timestamp": "2026-02-11T10:56:11.968"
        }

         ```

        **Response — 200 OK (Already Live)**

        ```
        Sender with API ID 24866922 is already in LIVE mode.

         ```

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Sender activated successfully | `LIVE` mode enabled |
        | 200 | Already in `LIVE` mode | Sender was already active |
        | 400 | Sender inactive | Account is not in `ACTIVE` state — verify sender status before retrying |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 404 | Sender not found | Invalid username — verify the correct username is being used |
        | 500 | Internal server error | Unexpected system failure — contact support if this persists |

        📌 **Note:** A `200` response with `status: LIVE` confirms full activation. If you receive the "already in LIVE mode" message, your sender was previously activated and no further action is needed — you can proceed directly to sending messages.

        🎉 **Your Telegram sender is now live.** You can begin sending real-time messages via `POST /telegram-sms/send`.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_golive
      requestBody:
        required: true
        content:
          text/plain:
            schema:
              type: string
            examples:
              Go Live Session:
                value: ''
      responses:
        '200':
          description: OK
  /telegram/disconnect:
    post:
      tags:
      - Telegram
      summary: Disconnect Session
      description: |
        The Disconnect Session API safely terminates the active Telegram client session associated with the authenticated user. After disconnection, the sender will no longer be able to send or receive Telegram messages until a new session is initialized.

        **Important:** This API only disconnects the session — it does **not** delete or clear the session data. If you want to completely remove all session data and start fresh, use `POST /telegram/disconnect-and-clear` instead.

        **Purpose**

        - Safely closes the running Telegram client session for the specified user

        - Removes the associated queue processor and releases all in-memory resources

        - Stops all pending message processing immediately for this session


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that the sender exists in the system |
        | 2 | Removes the active queue processor instance |
        | 3 | Terminates the running Telegram client session |
        | 4 | Clears in-memory session references |
        | 5 | Logs the disconnection activity with username and IP address |
        | 6 | Returns a confirmation message upon successful disconnection |

        **Session Termination Logic**

        | Scenario | Action Taken |
        | --- | --- |
        | Valid active session | Session terminated successfully |
        | Sender not found | Request rejected with 404 |
        | Unexpected error | Internal server error returned |

        **Important Behavior**

        - After disconnection, message sending and receiving is immediately disabled

        - Any pending queue processing is stopped immediately

        - Disconnection only affects the session of the specified username — other users are not impacted

        - To resume messaging, a new session must be initialized via `POST /telegram-sandbox/connect`


        **Response — 200 OK**

        ```
        Session disconnected successfully for username: super

         ```

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Session disconnected successfully | Valid disconnection completed |
        | 400 | Bad Request | Invalid request parameters |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 404 | Sender not found | Username does not exist in the system |
        | 500 | Internal server error | Unexpected failure during session cleanup |

        **Disconnect vs Disconnect and Clear**

        | Action | API | When To Use |
        | --- | --- | --- |
        | Disconnect only | `POST /telegram/disconnect` ← This API | Temporary disconnection — session data is preserved. Use when you want to reconnect later |
        | Disconnect and Clear | `POST /telegram/disconnect-and-clear` | Permanent disconnection — all session data is deleted. Use when you want to start completely fresh |

        🔜 **To reconnect:** Call `POST /telegram-sandbox/connect` to initialize a new session and follow the authentication flow again.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_disconnect
      responses:
        '200':
          description: OK
  /telegram/disconnect-and-clear:
    post:
      tags:
      - Telegram
      summary: Disconnect And Clear Session
      description: |
        The Disconnect and Clear Session API terminates the active Telegram client session and permanently removes all stored session data, authentication state, and cached chat history for the specified user.

        This is a **complete session reset** — unlike `POST /telegram/disconnect` which only closes the session while preserving data, this API wipes everything clean. After calling this API, a full re-authentication process will be required before the sender can resume operations.

        **Important:** This action is **irreversible**. All local session data, authentication state, and cached chat history will be permanently deleted. Only use this API when a complete session reset is required.

        **Purpose**

        - Permanently terminates the Telegram client session and removes all associated data

        - Clears the local TDLib database, stored authentication state, and cached chat history

        - Ensures a completely fresh state — as if the sender was never connected before


        **Core Behavior**

        | # | Description |
        | --- | --- |
        | 1 | Validates that the sender exists in the system |
        | 2 | Stops and removes the active queue processor |
        | 3 | Terminates the Telegram client session |
        | 4 | Deletes the sender's local session directory recursively |
        | 5 | Removes stored authentication state and cached chat history |
        | 6 | Logs cleanup activity with username and IP address |
        | 7 | Returns a confirmation message after successful cleanup |

        **Session Cleanup Logic**

        | Scenario | Action Taken |
        | --- | --- |
        | Valid active session | Session disconnected and all data cleared |
        | Sender not found | Request rejected with 404 |
        | Directory exists | Recursively deleted |
        | Unexpected error | Internal server error returned |

        **What Gets Cleared**

        | Component | Action |
        | --- | --- |
        | Active Telegram Client Instance | Terminated and removed |
        | Queue Processor Reference | Stopped and cleared |
        | Local TDLib Database Directory | Permanently deleted |
        | Stored Authentication State | Removed |
        | Cached Chat History | Deleted |
        | Stored Session Files | Wiped completely |

        **When To Use This API**

        | Scenario | Description |
        | --- | --- |
        | Session Reset | Start completely fresh with a new session |
        | Account Switching | Switch to a different Telegram account on the same sender |
        | Corrupted Session Recovery | Fix a broken or stuck session that cannot be recovered |
        | Security Cleanup | Remove all session data for security purposes |

        **Disconnect vs Disconnect and Clear**

        | Action | API | When To Use |
        | --- | --- | --- |
        | Disconnect only | `POST /telegram/disconnect` | Temporary disconnection — session data is preserved. Use when you want to reconnect later |
        | Disconnect and Clear | `POST /telegram/disconnect-and-clear` ← This API | Permanent disconnection — all session data is deleted. Use when you want to start completely fresh |

        **Response — 200 OK**

        ```
        Session disconnected successfully for username: super

         ```

        **Error Reference**

        | HTTP Code | Description | When It Occurs |
        | --- | --- | --- |
        | 200 | Session disconnected and cleared successfully | Valid cleanup completed |
        | 400 | Bad Request | Invalid request parameters |
        | 401 | Unauthorized | Invalid or expired authentication token |
        | 404 | Sender not found | Username does not exist in the system |
        | 500 | Internal server error | Failure during session or file cleanup |

        📌 **Note:** After this operation, the sender's local session data is permanently gone. A complete re-authentication flow must be performed — starting from `POST /telegram-sandbox/connect` — before the sender can resume Telegram operations.

        🔜 **To reconnect:** Call `POST /telegram-sandbox/connect` to initialize a new session and follow the full authentication flow from the beginning.

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_disconnect_and_clear
      responses:
        '200':
          description: OK
  /telegram-sms/send:
    post:
      tags:
      - Telegram
      summary: Send Text Message
      description: |-
        To send a text message, make a POST call to `/telegram-sms/send` and attach a message object with type = `"TEXT"`. Then, add a text object.

        For more information about the Text Object structure,**.**

        ### Response

        A successful response includes an object with an identifier. Use the ID listed in the response to track your message status.

        **Destination numbers**

        ``` json
        {
          "totalFilesProcessed": 0,
          "totalNumbersSuccess": 1,
          "totalNumbersFailed": 0,
          "totalNumbersDuplicate": 0,
          "batchId": "2601221336333031021",
          "files": []
        }

         ```

        **Destination file**

        ``` json
        {
          "totalFilesProcessed": 1,
          "totalNumbersSuccess": 4,
          "totalNumbersFailed": 0,
          "totalNumbersDuplicate": 0,
          "batchId": "2602061336187631861",
          "files": [
            {
              "fileName": "SampleTelegramCsv.csv",
              "totalNumbersCount": 4,
              "successNumbersCount": 4,
              "failedNumbers": [],
              "duplicateNumbers": []
            }
          ]
        }

         ```
      operationId: post_telegram_sms_send
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                campaignName:
                  type: string
                allowDuplicate:
                  type: string
                messageType:
                  type: string
                delay:
                  type: string
                destinationNo:
                  type: string
                content:
                  type: string
                scheduled:
                  type: string
                scheduleTime:
                  type: string
                gmt:
                  type: string
                batchId:
                  type: string
                destinationFiles:
                  type: string
                  format: binary
                templateId:
                  type: string
            examples:
              Send Text Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: TEXT
                  delay: '10'
                  destinationNo: '+447700900108'
                  content: hi !!😀
                  scheduled: 'true'
                  scheduleTime: '2027-02-07 16:35:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  destinationFiles: ''
                  templateId: TEMPLATE_ID
              Send Reply Text Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: TEXT
                  destinationNo: '+447700900109'
                  content: hi !!😀
                  batchId: '0'
                  replyToMessageId: '447700900132'
              Send Image Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: PHOTO
                  delay: '10'
                  destinationNo: '+447700900133'
                  destinationFiles: ''
                  content: hey
                  file: recipients.jpg
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 16:41:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  showCaptionAboveMedia: 'true'
                  hasSpoiler: 'true'
              Send Reply Image Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: PHOTO
                  destinationNo: '+447700900133'
                  content: hey
                  file: recipients.jpg
                  batchId: '0'
                  showCaptionAboveMedia: 'false'
                  hasSpoiler: 'false'
                  replyToMessageId: '6292504576'
              Send Document Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: DOCUMENT
                  delay: '11'
                  destinationNo: '+447700900133'
                  content: HI
                  file: recipients.csv
                  scheduled: 'true'
                  scheduleTime: '2026-02-06 17:56:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  destinationFiles: ''
              Send Reply Document Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: DOCUMENT
                  destinationNo: '+447700900109'
                  content: HI
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Video Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  delay: '10'
                  destinationNo: '+447700900109'
                  content: hello
                  file: WFeS2FBux/sample-5.mp4
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 16:41:00.000'
                  gmt: GMT+05:30#1
                  hasSpoiler: 'true'
                  showCaptionAboveMedia: 'true'
                  supportsStreaming: 'true'
                  batchId: '0'
                  destinationFiles: ''
              Send Reply Video Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  destinationNo: '+447700900109'
                  content: hello
                  file: postman-cloud:///00000000-0000-4000-8000-000000000000
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 16:60:00.000'
                  gmt: GMT+05:30#1
                  hasSpoiler: 'true'
                  showCaptionAboveMedia: 'true'
                  supportsStreaming: 'false'
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Audio Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  delay: '1'
                  destinationNo: '+447700900109'
                  file: nc9_Xu7WC/flute-music-363036.mp3
                  scheduled: 'true'
                  scheduleTime: '2026-02-06 16:41:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
              Send Reply Audio Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: AUDIO
                  destinationNo: '+447700900109'
                  file: Pa7PyFYhA/14472107_2160_3840_25fps.mp4
                  scheduled: 'false'
                  scheduleTime: '2027-02-06 16:41:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send GIF Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  delay: '1'
                  destinationNo: '+447700900109'
                  file: ndQZ4AHYL/14472107_2160_3840_25fps.mp4
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:27:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
              Send Reply GIF Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: VIDEO
                  destinationNo: '+447700900109'
                  file: ndQZ4AHYL/14472107_2160_3840_25fps.mp4
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:27:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Sticker Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: STICKER
                  delay: '10'
                  destinationNo: '+447700900109'
                  file: 4mTiudrzC/sticker.webp
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:27:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
              Send Reply Sticker Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: STICKER
                  destinationNo: '+447700900109'
                  file: 4mTiudrzC/sticker.webp
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:27:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Location Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: LOCATION
                  delay: '11'
                  destinationNo: '+447700900133'
                  latitude: '23.2599'
                  longitude: '77.4126'
                  batchId: '0'
              Send Reply Location Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: LOCATION
                  destinationNo: '+447700900109'
                  latitude: '23.2599'
                  longitude: '77.4126'
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:27:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Contact Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: CONTACT
                  delay: '1'
                  destinationNo: '+447700900109'
                  phoneNumber: '447700900135'
                  firstName: ALEX
                  lastName: MORGAN
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:42:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
              Send Reply Contact Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: CONTACT
                  destinationNo: '+447700900109'
                  phoneNumber: '447700900135'
                  firstName: ALEX
                  lastName: MORGAN
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:42:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Poll Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: CONTACT
                  delay: '1'
                  destinationNo: '+447700900109'
                  phoneNumber: '447700900135'
                  firstName: ALEX
                  lastName: MORGAN
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:42:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
              Send Reply Poll Message:
                value:
                  campaignName: common
                  allowDuplicate: 'true'
                  messageType: CONTACT
                  destinationNo: '+447700900109'
                  phoneNumber: '447700900135'
                  firstName: ALEX
                  lastName: MORGAN
                  scheduled: 'true'
                  scheduleTime: '2027-02-06 17:42:00.000'
                  gmt: GMT+05:30#1
                  batchId: '0'
                  replyToMessageId: '447700900134'
              Send Reaction Message:
                value:
                  campaignName: common
                  allowDuplicate: 'false'
                  messageType: REACTION
                  destinationNo: '-1001365590827'
                  emoji: ❤️
                  replyToMessageId: '75514316324864'
                  batchId: '0'
      responses:
        '200':
          description: OK
  /telegram-templates/save:
    post:
      tags:
      - Telegram
      summary: Create Template
      description: |
        Creates a new Telegram template. `templateRequest` is a JSON string (form field), and `file` is required for any media type other than TEXT (PHOTO, VIDEO, AUDIO, DOCUMENT, VOICE, GIF, STICKER).

        ---
        ### Auth
        This collection uses the tenant token:
        - `ACCESS_TOKEN` - required for every Telegram Template endpoint.

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_templates_save
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                templateRequest:
                  type: string
            examples:
              Create Template:
                value:
                  file: ''
                  templateRequest: '{"name": "Welcome Template", "text": "Hello first_name, welcome to BroadNet!", "mediaType":
                    "TEXT", "supportsStreaming": false, "showCaptionAboveMedia": false, "hasSpoiler": false, "latitude": 0.0,
                    "longitude": 0.0, "accuracy": 0.0, "livePeriod": 0, "phoneNumber": "", "firstName": "", "lastName": "",
                    "vcard": "", "contentUserId": 0, "pollQuestion": "", "pollOptions": [], "pollAnonymous": false, "pollType":
                    "", "pollOpenPeriod": 0, "pollCloseDate": 0, "pollClosed": false, "category": "marketing", "languageCode":
                    "en"}'
      responses:
        '200':
          description: OK
  /telegram-templates/update/{TEMPLATE_ID}:
    put:
      tags:
      - Telegram
      summary: Update Template
      description: |
        Updates an existing template by ID. Same multipart shape as create - `templateRequest` JSON string plus an optional replacement `file`.

        ---
        ### Auth
        This collection uses the tenant token:
        - `ACCESS_TOKEN` - required for every Telegram Template endpoint.

        **This request uses:** `ACCESS_TOKEN`
      operationId: put_telegram_templates_update_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                templateRequest:
                  type: string
            examples:
              Update Template:
                value:
                  file: ''
                  templateRequest: '{"name": "Welcome Template", "text": "Hello first_name, welcome to BroadNet!", "mediaType":
                    "TEXT", "supportsStreaming": false, "showCaptionAboveMedia": false, "hasSpoiler": false, "latitude": 0.0,
                    "longitude": 0.0, "accuracy": 0.0, "livePeriod": 0, "phoneNumber": "", "firstName": "", "lastName": "",
                    "vcard": "", "contentUserId": 0, "pollQuestion": "", "pollOptions": [], "pollAnonymous": false, "pollType":
                    "", "pollOpenPeriod": 0, "pollCloseDate": 0, "pollClosed": false, "category": "marketing", "languageCode":
                    "en"}'
      responses:
        '200':
          description: OK
  /telegram-templates/by-id/{TEMPLATE_ID}:
    get:
      tags:
      - Telegram
      summary: Get Template By ID
      description: |
        Retrieves a single Telegram template by its ID.

        ---
        ### Auth
        This collection uses the tenant token:
        - `ACCESS_TOKEN` - required for every Telegram Template endpoint.

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_templates_by_id_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
  /telegram-templates/delete/{TEMPLATE_ID}:
    delete:
      tags:
      - Telegram
      summary: Delete Template
      description: |
        Permanently deletes a Telegram template by ID.

        ---
        ### Auth
        This collection uses the tenant token:
        - `ACCESS_TOKEN` - required for every Telegram Template endpoint.

        **This request uses:** `ACCESS_TOKEN`
      operationId: delete_telegram_templates_delete_TEMPLATE_ID
      parameters:
      - name: TEMPLATE_ID
        in: path
        required: true
        schema:
          type: string
        example: TEMPLATE_ID
      responses:
        '200':
          description: OK
  /telegram-templates/get-all:
    post:
      tags:
      - Telegram
      summary: All List Templates
      description: |
        Fetches a paginated list of templates. `page`/`size` are query params; the body is an optional filter (`startDate`, `endDate`, `mediaType`, `search`) - send `{}` for no filters.

        ---
        ### Auth
        This collection uses the tenant token:
        - `ACCESS_TOKEN` - required for every Telegram Template endpoint.

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_templates_get_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                startDate:
                  type: string
                endDate:
                  type: string
                mediaType:
                  type: string
                search:
                  type: string
            examples:
              All List Templates:
                value:
                  startDate: '2024-01-01T00:00:00.000'
                  endDate: '2024-12-31T23:59:59.000'
                  mediaType: TEXT
                  search: welcome
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/edit:
    get:
      tags:
      - Telegram
      summary: Bulk Edit
      description: |
        ## Load a batch for editing (pauses if live)

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED` (if was INPROGRESS), record returned

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/pause:
    get:
      tags:
      - Telegram
      summary: Bulk Pause
      description: |
        ## Pause an in-flight batch

        - **Allowed initial status**: `PENDING`, `INPROGRESS`
        - Returns `400` if status is `PAUSED`, `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED`

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/resume:
    get:
      tags:
      - Telegram
      summary: Bulk Resume
      description: |
        ## Resume a paused batch

        - **Allowed initial status**: `PAUSED` only
        - Returns `400` if status is `PENDING`, `INPROGRESS`, `DONE`, `ABORTED`, `FAILED` (prevents DONE/ABORTED re-fire)
        - On success: status → `INPROGRESS`

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/abort:
    delete:
      tags:
      - Telegram
      summary: Bulk Abort
      description: |
        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: delete_telegram_telegram_sms_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/all-bulk:
    post:
      tags:
      - Telegram
      summary: All Bulk
      description: |
        ## List the tenant's bulk campaigns

        Optional filter body supports `status`, `campaignType`, `messageType`, `active`, `scheduled`, date ranges.

        **Status filter accepts** any of: `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED`, `FAILED`.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sms_all_bulk
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                page:
                  type: string
                size:
                  type: string
                toGmt:
                  type: string
                status:
                  type: string
                sortBy:
                  type: string
                sortDir:
                  type: string
            examples:
              All Bulk:
                value:
                  page: '0'
                  size: '20'
                  toGmt: GMT+05:30#1
                  status: ''
                  sortBy: batchId
                  sortDir: DESC
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/file:
    get:
      tags:
      - Telegram
      summary: GET File
      description: |
        ### Download batch media file

        Returns the actual media file as binary (NOT Base64).
        Clients receive raw image/video/document exactly as stored.

        **Endpoint** `GET /telegram/telegram-sms/file`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `batch_Id` | query | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | File downloaded successfully |
        | 404 | Batch or file not found |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_file
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: BATCH_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/group/create:
    post:
      tags:
      - Telegram
      summary: Create Groups
      description: |
        ### Create a basic group

        Creates a new basic group and adds the specified users as members.

        **Endpoint** `POST /telegram/telegram-sms/group/create`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `userIds` | query | yes |  |
        | `title` | query | yes | Title of the new basic group; 1-128 characters |
        | `messageAutoDeleteTime` | query | no | Message auto-delete time in seconds (default `0`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sms_group_create
      parameters:
      - name: userIds
        in: query
        required: false
        schema:
          type: string
      - name: title
        in: query
        required: false
        schema:
          type: string
      - name: messageAutoDeleteTime
        in: query
        required: false
        schema:
          type: string
        example: '0'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                members:
                  type: array
                  items:
                    type: string
            examples:
              Create Groups:
                value:
                  title: BroadNet Group
                  members:
                  - '{{TG_CHAT_ID}}'
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/channel/create:
    post:
      tags:
      - Telegram
      summary: Create Channel
      description: |
        ### Create a channel

        Creates a new Telegram channel.

        **Endpoint** `POST /telegram/telegram-sms/channel/create`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `title` | query | yes | Title of the channel; 1-128 characters |
        | `description` | query | no | Description of the channel |
        | `messageAutoDeleteTime` | query | no | Message auto-delete time in seconds (default `0`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sms_channel_create
      parameters:
      - name: title
        in: query
        required: false
        schema:
          type: string
      - name: description
        in: query
        required: false
        schema:
          type: string
      - name: messageAutoDeleteTime
        in: query
        required: false
        schema:
          type: string
        example: '0'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                description:
                  type: string
                isPublic:
                  type: boolean
            examples:
              Create Channel:
                value:
                  title: BroadNet Channel
                  description: Announcements
                  isPublic: false
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/set:
    get:
      tags:
      - Telegram
      summary: Set Sticker
      description: |
        ### Get a sticker set by ID

        Returns a sticker set by its identifier.

        **Endpoint** `GET /telegram/telegram-sms/sticker/set`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `setId` | query | yes | Sticker set identifier |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_sticker_set
      parameters:
      - name: setId
        in: query
        required: false
        schema:
          type: string
        example: STICKER_SET_ID
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/set/search:
    get:
      tags:
      - Telegram
      summary: Search Sticker
      description: |
        ### Search for a sticker set by name

        Searches for a sticker set by its name.

        **Endpoint** `GET /telegram/telegram-sms/sticker/set/search`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `name` | query | yes | Name of the sticker set |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_sticker_set_search
      parameters:
      - name: name
        in: query
        required: false
        schema:
          type: string
        example: cat
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/installed/search:
    get:
      tags:
      - Telegram
      summary: Installed Sticker Search
      description: |
        Search the user's installed sticker sets.

        ### Search installed sticker sets

        Searches for installed sticker sets matching the query.

        **Endpoint** `GET /telegram/telegram-sms/sticker/installed/search`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `query` | query | no | Query to search for (default ``) |
        | `limit` | query | no | Maximum number of sticker sets to return (default `100`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_sticker_installed_search
      parameters:
      - name: query
        in: query
        required: false
        schema:
          type: string
      - name: limit
        in: query
        required: false
        schema:
          type: string
        example: '100'
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/sets/search:
    post:
      tags:
      - Telegram
      summary: Sticker Search
      description: |
        ### Search sticker sets

        Searches for sticker sets by looking for the query in their title and name.

        **Endpoint** `POST /telegram/telegram-sms/sticker/sets/search`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `query` | query | yes | Query to search for |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sms_sticker_sets_search
      parameters:
      - name: query
        in: query
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                limit:
                  type: integer
            examples:
              Sticker Search:
                value:
                  query: cat
                  limit: 20
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/trending:
    get:
      tags:
      - Telegram
      summary: Trending Sticker
      description: |
        ### Get trending sticker sets

        Returns trending sticker sets.

        **Endpoint** `GET /telegram/telegram-sms/sticker/trending`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `offset` | query | no | Offset from which to return sticker sets (default `0`) |
        | `limit` | query | no | Maximum number of sticker sets to return (default `100`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_sticker_trending
      parameters:
      - name: offset
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: limit
        in: query
        required: false
        schema:
          type: string
        example: '100'
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/sticker/get:
    get:
      tags:
      - Telegram
      summary: Stickers
      description: |
        ### Get stickers matching a query

        Returns stickers from installed sticker sets that correspond to the given emoji or keywords.

        **Endpoint** `GET /telegram/telegram-sms/sticker/get`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `query` | query | yes | Search query (emoji or keyword) |
        | `limit` | query | no | Maximum number of stickers to return (default `100`) |
        | `chatId` | query | no | Chat identifier for context (default `0`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_sticker_get
      parameters:
      - name: query
        in: query
        required: false
        schema:
          type: string
        example: STICKER_SET_ID
      - name: limit
        in: query
        required: false
        schema:
          type: string
        example: '100'
      - name: chatId
        in: query
        required: false
        schema:
          type: string
        example: '0'
      responses:
        '200':
          description: OK
  /telegram/telegram-bot/send:
    post:
      tags:
      - Telegram
      summary: Bot Message Send
      description: |
        ### Send a message via Telegram Bot API

        Sends a text message to a specified chat using the Telegram Bot API.

        **Endpoint** `POST /telegram/telegram-bot/send`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `chatId` | query | yes | Target chat identifier |
        | `text` | query | yes | Message text to send |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_bot_send
      parameters:
      - name: chatId
        in: query
        required: false
        schema:
          type: string
        example: '5623933750'
      - name: text
        in: query
        required: false
        schema:
          type: string
        example: heeloooo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                botToken:
                  type: string
                chatId:
                  type: string
                text:
                  type: string
                parseMode:
                  type: string
            examples:
              Bot Message Send:
                value:
                  botToken: '{{TG_BOT_TOKEN}}'
                  chatId: '{{TG_CHAT_ID}}'
                  text: Hello from the bot
                  parseMode: HTML
      responses:
        '200':
          description: OK
  /telegram/telegram-bot/me:
    get:
      tags:
      - Telegram
      summary: Bot Me
      description: |
        ### Get bot information

        Returns information about the current bot user.

        **Endpoint** `GET /telegram/telegram-bot/me`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_bot_me
      parameters:
      - name: botToken
        in: query
        required: false
        schema:
          type: string
        example: BOT_TOKEN
      responses:
        '200':
          description: OK
  /telegram/telegram-bot/webhook/set:
    post:
      tags:
      - Telegram
      summary: Set Webhook Url
      description: |
        ### Set webhook URL

        Sets the webhook URL for receiving updates via the Telegram Bot API.

        **Endpoint** `POST /telegram/telegram-bot/webhook/set`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `webhookUrl` | query | yes | Webhook URL |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_bot_webhook_set
      parameters:
      - name: webhookUrl
        in: query
        required: false
        schema:
          type: string
        example: https://example.com/
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                botToken:
                  type: string
                webhookUrl:
                  type: string
            examples:
              Set Webhook Url:
                value:
                  botToken: '{{TG_BOT_TOKEN}}'
                  webhookUrl: https://api.broadnet.me/telegram-bot/webhook
      responses:
        '200':
          description: OK
  /telegram/telegram-bot/webhook/info:
    get:
      tags:
      - Telegram
      summary: Webhook Information
      description: |
        ### Get webhook information

        Returns current webhook status and configuration.

        **Endpoint** `GET /telegram/telegram-bot/webhook/info`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_bot_webhook_info
      parameters:
      - name: botToken
        in: query
        required: false
        schema:
          type: string
        example: BOT_TOKEN
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/gift/send:
    post:
      tags:
      - Telegram
      summary: Send Gift
      description: |
        ### Send a gift to a user

        Sends a gift to another user. May return an error if the gift was sold out.

        **Endpoint** `POST /telegram/telegram-sms/gift/send`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `giftId` | query | yes | Identifier of the gift to send |
        | `userId` | query | yes | Identifier of the user to receive the gift |
        | `text` | query | no | Text to show along with the gift |
        | `isPrivate` | query | no | Show sender and text only to receiver (default `false`) |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sms_gift_send
      parameters:
      - name: giftId
        in: query
        required: false
        schema:
          type: string
      - name: userId
        in: query
        required: false
        schema:
          type: string
      - name: text
        in: query
        required: false
        schema:
          type: string
      - name: isPrivate
        in: query
        required: false
        schema:
          type: string
        example: 'false'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                giftId:
                  type: string
                recipientId:
                  type: string
                message:
                  type: string
            examples:
              Send Gift:
                value:
                  giftId: <gift-id>
                  recipientId: '{{TG_CHAT_ID}}'
                  message: Cheers!
      responses:
        '200':
          description: OK
  /telegram/telegram-sms/gift/available:
    get:
      tags:
      - Telegram
      summary: Available Gift
      description: |
        ### Get available gifts

        Returns gifts that can be sent to other users and channel chats.

        **Endpoint** `GET /telegram/telegram-sms/gift/available`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: get_telegram_telegram_sms_gift_available
      responses:
        '200':
          description: OK
  /telegram/telegram-sandbox/connect:
    post:
      tags:
      - Telegram
      summary: Connect Sandbox
      description: |
        Connect the sandbox TDLib instance for smoke-testing.

        ### Connect Sandbox Session

        Initializes a sandbox Telegram session for the given API ID. Once connected, you can send messages via `/telegram-sandbox/send`.

        **Endpoint** `POST /telegram/telegram-sandbox/connect`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sandbox_connect
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phoneNumber:
                  type: string
                apiId:
                  type: string
                apiHash:
                  type: string
            examples:
              Connect Sandbox:
                value:
                  phoneNumber: '{{PHONE_NUMBER}}'
                  apiId: '{{APP_ID}}'
                  apiHash: <api-hash>
      responses:
        '200':
          description: OK
  /telegram/telegram-sandbox/send:
    post:
      tags:
      - Telegram
      summary: Send Sandbox
      description: |
        ### Send Message or Media (Sandbox)

        Sends a text or media message via the sandbox Telegram client.
        🔹 **Supported Destinations**
        - Raw `chatId` (numeric: private, group, supergroup, or channel)
        - Public `@username`
        - Phone number (`+447700900111`)
        - Group name (from recent chats)
        🔹 **Supported Media Types**
        - `TEXT` → Plain message
        - `PHOTO`, `VIDEO`, `AUDIO`, `DOCUMENT`, `VOICE`, `GIF`, `STICKER`
        - `LOCATION` → With latitude/longitude
        - `CONTACT` → With name, phone, vCard
        - `POLL` → Question with multiple options
        🔹 **Notes**
        - `file` is mandatory for all media except TEXT, LOCATION, CONTACT, POLL
        - Stickers must be valid Telegram formats (`.webp`, `.tgs`)
        - Polls only work in groups/supergroups
        - Live locations require `livePeriod` in seconds
        - Contact messages must include at least `phoneNumber` and `firstName`

        **Endpoint** `POST /telegram/telegram-sandbox/send`

        **Request body** `multipart/form-data`

        | Field | Type |
        |---|---|
        | `destinationNo` | `string` |
        | `campaignName` | `string` |
        | `content` | `string` |
        | `messageType` | `MessageType` |
        | `file` | `string` |
        | `supportsStreaming` | `boolean` |
        | `showCaptionAboveMedia` | `boolean` |
        | `hasSpoiler` | `boolean` |
        | `latitude` | `number` |
        | `longitude` | `number` |
        | `accuracy` | `number` |
        | `livePeriod` | `integer` |
        | `phoneNumber` | `string` |
        | `firstName` | `string` |
        | `lastName` | `string` |
        | `vcard` | `string` |
        | `contactUserId` | `integer` |
        | `pollQuestion` | `string` |
        | `pollOptions` | `array` |
        | `pollAnonymous` | `boolean` |
        | `pollType` | `string` |
        | `pollOpenPeriod` | `integer` |
        | `pollCloseDate` | `integer` |
        | `pollClosed` | `boolean` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |

        ---
        ### Auth
        This collection uses two tokens:
        - `SUPER_TOKEN` — operator / provider token. Required only for **Client Onboarding** endpoints.
        - `ACCESS_TOKEN` — tenant token. Required for everything else (channel live, session auth, message send/lifecycle, groups, stickers, bot, gifts, sandbox).

        **This request uses:** `ACCESS_TOKEN`
      operationId: post_telegram_telegram_sandbox_send
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                to:
                  type: string
                text:
                  type: string
                attachment:
                  type: string
                  format: binary
            examples:
              Send Sandbox:
                value:
                  to: CHAT_ID
                  text: Sandbox test
                  attachment: ''
      responses:
        '200':
          description: OK
  /email/email-providers:
    post:
      tags:
      - Email
      summary: Create Email Provider
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        Create a new SMTP provider config for the tenant.

        ### Create Email Provider

        Creates a new email provider configuration with SMTP and IMAP settings

        **Endpoint** `POST /email/email-providers`

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `systemId` | `string` |
        | `host` | `string` |
        | `port` | `integer` |
        | `encryptionType` | `object` |
        | `emailUser` | `string` |
        | `emailPassword` | `string` |
        | `authType` | `AuthType` |
        | `verified` | `boolean` |
        | `readInbox` | `boolean` |
        | `webHookUrl` | `string` |
        | `imapHost` | `string` |
        | `imapPort` | `integer` |
        | `description` | `string` |
        | `imapEncType` | `object` |
        | `displayName` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `isPassthroughFee` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `emailPackageCount` | `integer` |
        | `emailPackageSize` | `integer` |
        | `emailPackagePrice` | `number` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 201 | Email provider created successfully |
        | 400 | Invalid request data |
        | 401 | Unauthorized access |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_providers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                applyToIncoming:
                  type: boolean
                authType:
                  type: string
                displayName:
                  type: string
                emailPackageCount:
                  type: integer
                emailPackagePrice:
                  type: integer
                emailPackageSize:
                  type: integer
                emailPassword:
                  type: string
                emailUser:
                  type: string
                encryptionType:
                  type: string
                host:
                  type: string
                imapEncType:
                  type: string
                imapHost:
                  type: string
                imapPort:
                  type: integer
                isPassthroughFee:
                  type: boolean
                port:
                  type: integer
                rateLimit:
                  type: integer
                readInbox:
                  type: boolean
                systemId:
                  type: string
                tierId:
                  type: integer
                verified:
                  type: boolean
                webHookUrl:
                  type: string
            examples:
              Create Email Provider:
                value:
                  applyToIncoming: true
                  authType: PASSWORD
                  displayName: Postman
                  emailPackageCount: 30000
                  emailPackagePrice: 1
                  emailPackageSize: 30000
                  emailPassword: YOUR_PASSWORD
                  emailUser: user@example.com
                  encryptionType: SSL
                  host: mail.example.com
                  imapEncType: SSL
                  imapHost: mail.example.com
                  imapPort: 993
                  isPassthroughFee: true
                  port: 465
                  rateLimit: 60
                  readInbox: true
                  systemId: test104
                  tierId: 1
                  verified: true
                  webHookUrl: ''
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-providers/update/{EMAIL_PROVIDER_ID}:
    put:
      tags:
      - Email
      summary: Update Email Provider
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Update Email Provider

        Updates an existing email provider configuration by ID

        **Endpoint** `PUT /email/email-providers/update/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `systemId` | `string` |
        | `host` | `string` |
        | `port` | `integer` |
        | `encryptionType` | `object` |
        | `emailUser` | `string` |
        | `emailPassword` | `string` |
        | `authType` | `AuthType` |
        | `verified` | `boolean` |
        | `readInbox` | `boolean` |
        | `webHookUrl` | `string` |
        | `imapHost` | `string` |
        | `imapPort` | `integer` |
        | `description` | `string` |
        | `imapEncType` | `object` |
        | `displayName` | `string` |
        | `rateLimit` | `integer` |
        | `tierId` | `integer` |
        | `isPassthroughFee` | `boolean` |
        | `applyToIncoming` | `boolean` |
        | `emailPackageCount` | `integer` |
        | `emailPackageSize` | `integer` |
        | `emailPackagePrice` | `number` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Email provider updated successfully |
        | 400 | Invalid request data |
        | 401 | Unauthorized access |
        | 404 | Email provider not found |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: put_email_email_providers_update_EMAIL_PROVIDER_ID
      parameters:
      - name: EMAIL_PROVIDER_ID
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_PROVIDER_ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                applyToIncoming:
                  type: boolean
                authType:
                  type: string
                displayName:
                  type: string
                emailPackageCount:
                  type: integer
                emailPackagePrice:
                  type: integer
                emailPackageSize:
                  type: integer
                emailPassword:
                  type: string
                emailUser:
                  type: string
                encryptionType:
                  type: string
                host:
                  type: string
                imapEncType:
                  type: string
                imapHost:
                  type: string
                imapPort:
                  type: integer
                isPassthroughFee:
                  type: boolean
                port:
                  type: integer
                rateLimit:
                  type: integer
                readInbox:
                  type: boolean
                systemId:
                  type: string
                tierId:
                  type: integer
                verified:
                  type: boolean
                webHookUrl:
                  type: string
            examples:
              Update Email Provider:
                value:
                  applyToIncoming: true
                  authType: PASSWORD
                  displayName: Postman
                  emailPackageCount: 30000
                  emailPackagePrice: 1
                  emailPackageSize: 30000
                  emailPassword: YOUR_PASSWORD
                  emailUser: user@example.com
                  encryptionType: SSL
                  host: mail.example.com
                  imapEncType: SSL
                  imapHost: mail.example.com
                  imapPort: 993
                  isPassthroughFee: true
                  port: 465
                  rateLimit: 60
                  readInbox: true
                  systemId: test104
                  tierId: 1
                  verified: true
                  webHookUrl: ''
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-providers/{EMAIL_PROVIDER_ID}:
    get:
      tags:
      - Email
      summary: Get Email Provider By Id
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Get Email Provider by ID

        Retrieves a specific email provider configuration by ID

        **Endpoint** `GET /email/email-providers/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Email provider retrieved successfully |
        | 401 | Unauthorized access |
        | 404 | Email provider not found |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_email_email_providers_EMAIL_PROVIDER_ID
      parameters:
      - name: EMAIL_PROVIDER_ID
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_PROVIDER_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-providers/me:
    get:
      tags:
      - Email
      summary: Get Me
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}},{{ACCESS_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        Get the calling user's primary provider.

        ### Get Email Provider by Username

        Retrieves the email provider configuration for the authenticated user's system ID

        **Endpoint** `GET /email/email-providers/me`

        **Responses**

        | Status | Meaning |
        | --- | --- |
        | 200 | Email provider retrieved successfully |
        | 401 | Unauthorized access |
        | 404 | Email provider not found |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_email_email_providers_me
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-providers/get-all:
    post:
      tags:
      - Email
      summary: Get All Email Provider
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        List providers, paged + filterable. Body optional.

        ### Get All Email Providers

        Retrieves a paginated list of email providers using request body based filters. Supports filtering by systemId, host, IMAP host, IMAP encryption type, SMTP encryption type, authentication type, search keyword, and created date range.

        **Endpoint** `POST /email/email-providers/get-all`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `page` | query | no | Page number (0-indexed) (default `0`) |
        | `size` | query | no | Page size (default `10`) |

        **Request body** `application/json`

        | Field | Type |
        |---|---|
        | `search` | `string` |
        | `systemId` | `string` |
        | `host` | `string` |
        | `imapHost` | `string` |
        | `imapEncType` | `object` |
        | `encryptionType` | `object` |
        | `authType` | `AuthType` |
        | `toGmt` | `string` |
        | `startDate` | `string` |
        | `endDate` | `string` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Email providers retrieved successfully |
        | 401 | Unauthorized access |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_providers_get_all
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                providerName:
                  type: string
                active: {}
            examples:
              Get All Email Provider:
                value:
                  providerName: ''
                  active: null
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-providers/delete/{EMAIL_PROVIDER_ID}:
    delete:
      tags:
      - Email
      summary: Delete Email Provider
      description: |-
        **Authentication:** `Authorization: Bearer {{SUPER_TOKEN}}`

        This request uses: `SUPER_TOKEN` — operator / provider token.

        ### Delete Email Provider

        Deletes an email provider configuration by ID

        **Endpoint** `DELETE /email/email-providers/delete/{id}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `id` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Email provider deleted successfully |
        | 401 | Unauthorized access |
        | 404 | Email provider not found |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: delete_email_email_providers_delete_EMAIL_PROVIDER_ID
      parameters:
      - name: EMAIL_PROVIDER_ID
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_PROVIDER_ID
      responses:
        '200':
          description: OK
      security:
      - operatorAuth: []
  /email/email-service/send:
    post:
      tags:
      - Email
      summary: Send Email
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Plain immediate send

        Simplest combination: no template, no file, no attachments. `recipients` is parsed as plain text — split on `,` `;` newline, tab — each address lower-cased and matched against `^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$`. Invalid rows are skipped with a warning, not rejected.

        | Field | Type | Required | Notes |
        |---|---|---|---|
        | `smtpId` | long | ✓ | Onboarded SMTP provider id |
        | `subject` | string | ✓ (without template) | |
        | `body` | string | ✓ (without template) | HTML allowed |
        | `recipients` | string | ✓ (or `recipientsFile`) | Comma / semicolon / newline / tab separated |
        | `campaignName` | string | | Falls back to template name when templateId is used |
        | `delay` | double | | Seconds between mails |
        | `scheduled` | boolean | | `false` → dispatch starts immediately on a ProcessingThread |
        | `allowDuplicates` | boolean | | `false` → duplicate addresses collapse to one |

        **Response** `200` — plain 19-digit `batchId` (captured into `EMAIL_BATCH_ID`).

        **Errors** — `400 No Valid Recipient Found` if every parsed address fails validation.
      operationId: post_email_email_service_send
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                subject:
                  type: string
                body:
                  type: string
                recipients:
                  type: string
                fromAddress:
                  type: string
                fromName:
                  type: string
                campaignName:
                  type: string
                scheduled:
                  type: string
                scheduleTime:
                  type: string
                smtpId:
                  type: string
                templateId:
                  type: string
                recurrence:
                  type: string
                repeatCount:
                  type: string
                delay:
                  type: string
            examples:
              Send Email:
                value:
                  subject: Hello from BroadNet
                  body: <p>Hi usertest104,</p><p>This is a test message.</p>
                  recipients: user@example.com,user@example.com
                  fromAddress: no-reply@broadnet.me
                  fromName: BroadNet
                  campaignName: Welcome-Drip-W22
                  scheduled: 'false'
                  scheduleTime: '2026-09-20 12:24:00'
                  smtpId: '16'
                  templateId: '11'
                  recurrence: NONE
                  repeatCount: '0'
                  delay: '99'
              Send Recipients:
                value:
                  smtpId: '16'
                  campaignName: JSON-Array-Test
                  subject: Hello from BroadNet
                  body: <p>JSON array recipients.</p>
                  recipients: user@example.com,test2@example.com,test3@example.com
                  scheduled: 'false'
              Send Recipients from CSV / TXT / Excel file:
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: File-Upload-Batch
                  subject: Monthly newsletter
                  body: <p>Newsletter body.</p>
                  recipientsFile:
                  - ''
                  - recipients.txt
                  scheduled: 'false'
              Send with attachments:
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: Invoice-Run
                  subject: Your invoice
                  body: <p>Invoice attached.</p>
                  recipients: user@example.com
                  attachmentList: ''
                  scheduled: 'false'
              Send with CC and BCC:
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: CC-BCC-Test
                  subject: Quarterly report
                  body: <p>Report attached below.</p>
                  recipients: user@example.com
                  ccRecipients: '["user@example.com"]'
                  bccRecipients: '["user@example.com"]'
                  scheduled: 'false'
              Send from a saved template (templateId):
                value:
                  smtpId: EMAIL_SMTP_ID
                  templateId: EMAIL_TEMPLATE_ID
                  recipients: user@example.com
                  scheduled: 'false'
                  subject: jjjjjjjjjjjjjjjjjjjjjjj
              Send Template + sharedParams (same values for everyone):
                value:
                  smtpId: EMAIL_SMTP_ID
                  templateId: EMAIL_TEMPLATE_ID
                  recipients: user@example.com
                  sharedParams: '{"companyName":"BroadNet","offerCode":"SAVE20","expiryDate":"2026-10-01"}'
                  scheduled: 'false'
              Send Template + per-row personalisation file + sharedParams:
                value:
                  smtpId: EMAIL_SMTP_ID
                  templateId: EMAIL_TEMPLATE_ID
                  campaignName: Personalised-Oct
                  recipientsFile:
                  - ''
                  - recipients.txt
                  sharedParams: '{"companyName":"BroadNet"}'
                  delay: '0.5'
                  scheduled: 'false'
              Send Allow Duplicates:
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: Dup-Allowed
                  subject: Reminder
                  body: <p>Reminder body.</p>
                  recipients: user@example.com
                  allowDuplicates: 'true'
                  scheduled: 'false'
              Send  Scheduled one-time:
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: Diwali-Blast
                  subject: Festive offer
                  body: <p>Offer inside.</p>
                  recipients: test1@example.com,test2@example.com
                  scheduled: 'true'
                  scheduleTime: '2026-12-25 14:30:00'
                  gmt: GMT+05:30
                  recurrence: NONE
                  repeatCount: '0'
              Send Scheduled Recurring (DAILY + end time):
                value:
                  smtpId: EMAIL_SMTP_ID
                  campaignName: Daily-Digest
                  subject: Your daily digest
                  body: <p>Digest body.</p>
                  recipients: test1@example.com
                  scheduled: 'true'
                  scheduleTime: '2026-10-01 09:00:00'
                  gmt: GMT+05:30
                  recurrence: DAILY
                  repeatCount: '30'
                  recurrenceEndTime: '2026-10-31 09:00:00'
      responses:
        '200':
          description: OK
  /email-templates/save:
    post:
      tags:
      - Email
      summary: Template Save
      description: |
        ### Create Email Template

        **Endpoint:** `POST /email-templates/save`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Content-Type:** `multipart/form-data` (auto-set by Postman)

        **Request Fields**

        | Field | Type | Required | Notes |
        |-------|------|----------|-------|
        | `name` | string | ✓ | Unique per user+language |
        | `category` | enum | ✓ | `AUTHENTICATION`, `MARKETING`, or `UTILITY` |
        | `languageCode` | string | ✓ | Comma-separated ISO codes: `en,hi,es` |
        | `headerText` | string | | Template header, supports `{{placeholder}}` |
        | `bodyText` | string | | HTML/text body, supports `{{placeholder}}` |
        | `footerText` | string | | Footer text |
        | `specialSettings` | JSON string | | Custom settings as JSON object |
        | `mediaFiles` | file[] | | Optional attachments (images, docs, video) |

        **Placeholder Format**
        - Named: `{{firstName}}`, `{{email}}`, `{{userId}}` — alphanumeric + underscore
        - Positional: `{{1}}`, `{{2}}` — indices
        - Invalid: `{{}}` or `{{@invalid}}`

        **Response** `201 Created`
        ```json
        "email template created successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `VALIDATION_ERROR` | Missing required fields |
        | 400 | `BAD_REQUEST` | Template already exists |
        | 400 | `BAD_REQUEST` | Invalid language code format |
        | 400 | `BAD_REQUEST` | File type not allowed |
        | 401 | `UNAUTHORIZED` | Invalid/missing Authorization token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: post_email_templates_save
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                category:
                  type: string
                languageCode:
                  type: string
                headerText:
                  type: string
                bodyText:
                  type: string
                footerText:
                  type: string
                specialSettings:
                  type: string
                mediaFiles:
                  type: string
                  format: binary
            examples:
              Template Save:
                value:
                  name: Welcome Email
                  category: AUTHENTICATION
                  languageCode: en,hi
                  headerText: Welcome firstName!
                  bodyText: <html><body>Thank you for joining. Your email is email</body></html>
                  footerText: © 2026 BroadNet. All rights reserved.
                  specialSettings: '{"priority": "high", "retryCount": 3}'
                  mediaFiles: ''
      responses:
        '200':
          description: OK
  /email-templates/update:
    put:
      tags:
      - Email
      summary: Template Update
      description: |
        ### Update Email Template

        **Endpoint:** `PUT /email-templates/update`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Content-Type:** `multipart/form-data`

        **Request Fields**

        | Field | Type | Required | Notes |
        |-------|------|----------|-------|
        | `id` | long | ✓ | Template ID to update |
        | `name` | string | | Update name |
        | `headerText` | string | | Update header |
        | `bodyText` | string | | Update body |
        | `footerText` | string | | Update footer |
        | `specialSettings` | JSON string | | Update settings |
        | `mediaFiles` | file[] | | Add/replace media files |

        **Response** `200 OK`
        ```json
        "email template updated successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `BAD_REQUEST` | Template not found |
        | 400 | `BAD_REQUEST` | Invalid file type |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: put_email_templates_update
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                id:
                  type: string
                name:
                  type: string
                headerText:
                  type: string
                bodyText:
                  type: string
                footerText:
                  type: string
                specialSettings:
                  type: string
            examples:
              Template Update:
                value:
                  id: EMAIL_TEMPLATE_ID
                  name: Welcome Email - Updated
                  headerText: Welcome back firstName!
                  bodyText: <html><body>Thank you for returning. Your email is email</body></html>
                  footerText: © 2026 BroadNet. Updated.
                  specialSettings: '{"priority": "high", "retryCount": 5}'
      responses:
        '200':
          description: OK
  /email-templates/id:
    get:
      tags:
      - Email
      summary: Get Template By Id
      description: |
        ### Get Email Template by ID

        **Endpoint:** `GET /email-templates/id`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters**

        | Parameter | Type | Required |
        |-----------|------|----------|
        | `id` | long | ✓ |

        **Response** `200 OK`
        ```json
        {
          "id": "123",
          "name": "Welcome Email",
          "category": "AUTHENTICATION",
          "languageCode": "en,hi",
          "headerText": "Welcome {{firstName}}!",
          "bodyText": "<html>...</html>",
          "footerText": "© 2026 BroadNet",
          "specialSettings": "{...}",
          "createdAt": "2026-09-15T10:30:00",
          "updatedAt": "2026-09-15T11:00:00",
          "username": "tenant-1"
        }
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 404 | `NOT_FOUND` | Template not found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: get_email_templates_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_TEMPLATE_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Email
      summary: Delete Template By Id
      description: |
        ### Delete Email Template

        **Endpoint:** `DELETE /email-templates/id`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters**

        | Parameter | Type | Required |
        |-----------|------|----------|
        | `id` | long | ✓ |

        **Response** `200 OK`
        ```json
        "email template deleted successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 404 | `NOT_FOUND` | Template not found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: delete_email_templates_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_TEMPLATE_ID
      responses:
        '200':
          description: OK
  /email-templates/getAll:
    get:
      tags:
      - Email
      summary: Get All Templates
      description: |
        ### List Email Templates (Paginated)

        **Endpoint:** `GET /email-templates/getAll`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters** (all optional)

        | Parameter | Type | Default | Notes |
        |-----------|------|---------|-------|
        | `search` | string | | Keyword in name/category |
        | `startDate` | date | | Format: `yyyy-MM-dd HH:mm:ss.SSS` |
        | `endDate` | date | | Format: `yyyy-MM-dd HH:mm:ss.SSS` |
        | `page` | int | 0 | 0-based page number |
        | `size` | int | 10 | Records per page |
        | `sortBy` | string | createdAt | Valid: `name`, `category`, `languageCode`, `createdAt`, `updatedAt` |
        | `sortDirection` | string | DESC | `ASC` or `DESC` |
        | `toGmt` | string | | Timezone conversion (e.g., `GMT+5:30`) |

        **Response** `200 OK`
        ```json
        {
          "content": [
            {
              "id": "123",
              "name": "Welcome Email",
              "category": "AUTHENTICATION",
              "languageCode": "en,hi",
              "createdAt": "2026-09-15T10:30:00",
              "updatedAt": "2026-09-15T11:00:00",
              "username": "tenant-1"
            }
          ],
          "pageNumber": 0,
          "pageSize": 10,
          "totalElements": 25,
          "totalPages": 3,
          "last": false
        }
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `BAD_REQUEST` | Invalid sort column |
        | 404 | `NOT_FOUND` | No templates found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: get_email_templates_getAll
      parameters:
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-01-01 00:00:00.000'
      - name: endDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-12-31 23:59:59.999'
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: DESC
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
        example: GMT+5:30
      responses:
        '200':
          description: OK
  /email-templates/grouped-by-category:
    get:
      tags:
      - Email
      summary: Get Template Group By Category
      description: |
        ### Get Email Templates Grouped by Category

        **Endpoint:** `GET /email-templates/grouped-by-category`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Purpose** — Lightweight data (id + name only) optimized for dropdown menus. Templates grouped by `AUTHENTICATION`, `MARKETING`, `UTILITY`.

        **Response** `200 OK`
        ```json
        {
          "AUTHENTICATION": [
            { "id": 1, "name": "Login Verification" },
            { "id": 2, "name": "Password Reset" }
          ],
          "MARKETING": [
            { "id": 3, "name": "Newsletter Digest" },
            { "id": 4, "name": "Promotional Offer" }
          ],
          "UTILITY": [
            { "id": 5, "name": "Order Confirmation" }
          ]
        }
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 404 | `NOT_FOUND` | No templates found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 401 | `UNAUTHORIZED_REQUEST` | User not authorized |
        | 403 | `UNAUTHORIZED_OPERATION` | Insufficient permissions |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: get_email_templates_grouped_by_category
      responses:
        '200':
          description: OK
  /frame-templates/save:
    post:
      tags:
      - Email
      summary: Save Frame Templates
      description: |
        ### Create Frame Template (WhatsApp)

        **Endpoint:** `POST /frame-templates/save`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Content-Type:** `multipart/form-data`

        **Request Fields**

        | Field | Type | Required | Notes |
        |-------|------|----------|-------|
        | `name` | string | ✓ | Unique per user |
        | `headerText` | string | | Frame title/emoji |
        | `bodyText` | string | | Message body, supports `{{placeholder}}` |
        | `footerText` | string | | Footer text |
        | `specialSettings` | JSON string | | Custom settings (buttons, actions, etc.) |
        | `mediaFiles` | file[] | | Optional media attachments |

        **Placeholder Format**
        - Named: `{{firstName}}`, `{{orderId}}`, `{{status}}` — alphanumeric + underscore
        - Positional: `{{1}}`, `{{2}}`
        - Invalid: `{{}}` or `{{@invalid}}`

        **Response** `201 Created`
        ```json
        "frame template created successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `VALIDATION_ERROR` | Missing `name` field |
        | 400 | `BAD_REQUEST` | Template already exists |
        | 400 | `BAD_REQUEST` | Invalid file type |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: post_frame_templates_save
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                headerText:
                  type: string
                bodyText:
                  type: string
                footerText:
                  type: string
                specialSettings:
                  type: string
                mediaFiles:
                  type: string
                  format: binary
            examples:
              Save Frame Templates:
                value:
                  name: Order Status Update
                  headerText: 📦 Your Order
                  bodyText: 'Hi firstName, your order #orderId is status.'
                  footerText: Thank you for your order!
                  specialSettings: '{"buttons": ["Track Order", "Contact Support"]}'
                  mediaFiles: ''
      responses:
        '200':
          description: OK
  /frame-templates/update:
    put:
      tags:
      - Email
      summary: Update Frame Templates
      description: |
        ### Update Frame Template

        **Endpoint:** `PUT /frame-templates/update`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Content-Type:** `multipart/form-data`

        **Request Fields**

        | Field | Type | Required | Notes |
        |-------|------|----------|-------|
        | `id` | long | ✓ | Template ID to update |
        | `name` | string | | Update template name |
        | `headerText` | string | | Update header |
        | `bodyText` | string | | Update body |
        | `footerText` | string | | Update footer |
        | `specialSettings` | JSON string | | Update settings |
        | `mediaFiles` | file[] | | Add/replace media |

        **Response** `200 OK`
        ```json
        "frame template updated successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `BAD_REQUEST` | Template not found |
        | 400 | `BAD_REQUEST` | Invalid file type |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: put_frame_templates_update
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                id:
                  type: string
                name:
                  type: string
                headerText:
                  type: string
                bodyText:
                  type: string
                footerText:
                  type: string
                specialSettings:
                  type: string
            examples:
              Update Frame Templates:
                value:
                  id: FRAME_TEMPLATE_ID
                  name: Order Status Update - v2
                  headerText: 📦 Order Notification
                  bodyText: 'Hi firstName, your order #orderId status: status. Estimated delivery: deliveryDate'
                  footerText: Questions? Contact support.
                  specialSettings: '{"buttons": ["Track Order", "Contact", "Help"]}'
      responses:
        '200':
          description: OK
  /frame-templates/id:
    get:
      tags:
      - Email
      summary: Get Frame By Id
      description: |
        ### Get Frame Template by ID

        **Endpoint:** `GET /frame-templates/id`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters**

        | Parameter | Type | Required |
        |-----------|------|----------|
        | `id` | long | ✓ |

        **Response** `200 OK`
        ```json
        {
          "id": "456",
          "name": "Order Status Update",
          "headerText": "📦 Your Order",
          "bodyText": "Hi {{firstName}}, your order #{{orderId}} is {{status}}.",
          "footerText": "Thank you for your order!",
          "specialSettings": "{\"buttons\": [...]}",
          "createdAt": "2026-09-15T10:30:00",
          "updatedAt": "2026-09-15T11:00:00",
          "username": "tenant-1"
        }
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 404 | `NOT_FOUND` | Template not found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: get_frame_templates_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: FRAME_TEMPLATE_ID
      responses:
        '200':
          description: OK
    delete:
      tags:
      - Email
      summary: Delete Al Frames
      description: |
        ### Delete Frame Template

        **Endpoint:** `DELETE /frame-templates/id`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters**

        | Parameter | Type | Required |
        |-----------|------|----------|
        | `id` | long | ✓ |

        **Response** `200 OK`
        ```json
        "frame deleted successfully"
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 404 | `NOT_FOUND` | Template not found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: delete_frame_templates_id
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        example: FRAME_TEMPLATE_ID
      responses:
        '200':
          description: OK
  /frame-templates/getAll:
    get:
      tags:
      - Email
      summary: Get All Frames
      description: |
        ### List Frame Templates (User)

        **Endpoint:** `GET /frame-templates/getAll`

        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        **Query Parameters** (all optional)

        | Parameter | Type | Default | Notes |
        |-----------|------|---------|-------|
        | `search` | string | | Keyword in name/body |
        | `startDate` | date | | Format: `yyyy-MM-dd HH:mm:ss.SSS` |
        | `endDate` | date | | Format: `yyyy-MM-dd HH:mm:ss.SSS` |
        | `page` | int | 0 | 0-based page number |
        | `size` | int | 10 | Records per page |
        | `sortBy` | string | createdAt | Valid: `name`, `backgroundColor`, `status`, `createdAt`, `updatedAt` |
        | `sortDirection` | string | DESC | `ASC` or `DESC` |

        **Response** `200 OK`
        ```json
        {
          "content": [
            {
              "id": "456",
              "name": "Order Status Update",
              "createdAt": "2026-09-15T10:30:00",
              "updatedAt": "2026-09-15T11:00:00",
              "username": "tenant-1"
            }
          ],
          "pageNumber": 0,
          "pageSize": 10,
          "totalElements": 15,
          "totalPages": 2,
          "last": false
        }
        ```

        **Error Responses**

        | Status | Error | Reason |
        |--------|-------|--------|
        | 400 | `BAD_REQUEST` | Invalid sort column |
        | 404 | `NOT_FOUND` | No templates found |
        | 401 | `UNAUTHORIZED` | Invalid/missing token |
        | 403 | `UNAUTHORIZED_OPERATION` | User lacks permission |
        | 500 | `INTERNAL_SERVER_ERROR` | Unexpected error |
      operationId: get_frame_templates_getAll
      parameters:
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: startDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-01-01 00:00:00.000'
      - name: endDate
        in: query
        required: false
        schema:
          type: string
        example: '2026-12-31 23:59:59.999'
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '10'
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: createdAt
      - name: sortDirection
        in: query
        required: false
        schema:
          type: string
        example: DESC
      responses:
        '200':
          description: OK
  /email/email-service/edit:
    get:
      tags:
      - Email
      summary: Get Edit Batch
      description: |
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Load a batch for editing (pauses if live)

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED` (if was INPROGRESS), record returned
      operationId: get_email_email_service_edit
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_BATCH_ID
      responses:
        '200':
          description: OK
  /email/email-service/pause:
    get:
      tags:
      - Email
      summary: Get Bulk Pause
      description: |
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Pause an in-flight batch

        - **Allowed initial status**: `PENDING`, `INPROGRESS`
        - Returns `400` if status is `PAUSED`, `DONE`, `ABORTED`, `FAILED`
        - On success: status → `PAUSED`
      operationId: get_email_email_service_pause
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_BATCH_ID
      responses:
        '200':
          description: OK
  /email/email-service/resume:
    get:
      tags:
      - Email
      summary: Get Resume Batch
      description: |
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Resume a paused batch

        - **Allowed initial status**: `PAUSED` only
        - Returns `400` if status is `PENDING`, `INPROGRESS`, `DONE`, `ABORTED`, `FAILED` (prevents DONE/ABORTED re-fire)
        - On success: status → `INPROGRESS`
      operationId: get_email_email_service_resume
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_BATCH_ID
      responses:
        '200':
          description: OK
  /email/email-service/abort:
    delete:
      tags:
      - Email
      summary: Delete Batch
      description: |
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## Abort a batch (terminal — persists ABORTED for audit)

        **Changed 2026-05-27**: previously deleted the record; now persists it for audit history.

        - **Allowed initial status**: `PENDING`, `INPROGRESS`, `PAUSED`
        - Returns `400` if status is already `DONE`, `ABORTED`, `FAILED` (prevents destroying completed campaign records)
        - On success: status → `ABORTED`, row stays in DB
        - UI tip: filter out `ABORTED` if you don't want aborted batches in lists
      operationId: delete_email_email_service_abort
      parameters:
      - name: batch_Id
        in: query
        required: false
        schema:
          type: string
        example: EMAIL_BATCH_ID
      responses:
        '200':
          description: OK
  /email/email-service/all-bulk:
    get:
      tags:
      - Email
      summary: Get All Bulk Batches
      description: |
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ## List the tenant's bulk campaigns

        Optional filter body supports `status`, `campaignType`, `messageType`, `active`, `scheduled`, date ranges.

        **Status filter accepts** any of: `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED`, `FAILED`.

        **Canonical batch status values** (same across every channel — 2026-05-27 sync):
        - `PENDING` — created, awaiting dispatch
        - `INPROGRESS` — actively dispatching
        - `PAUSED` — paused by user
        - `DONE` — completed successfully (terminal)
        - `ABORTED` — user-aborted (terminal, persisted for audit)
        - `FAILED` — system-aborted on runtime error (terminal)
      operationId: get_email_email_service_all_bulk
      parameters:
      - name: page
        in: query
        required: false
        schema:
          type: string
        example: '0'
      - name: size
        in: query
        required: false
        schema:
          type: string
        example: '20'
      - name: toGmt
        in: query
        required: false
        schema:
          type: string
        example: GMT+05:30
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
        example: batchId
      - name: sortDir
        in: query
        required: false
        schema:
          type: string
        example: 'DESC '
      - name: search
        in: query
        required: false
        schema:
          type: string
      - name: batchId
        in: query
        required: false
        schema:
          type: string
      - name: smtpId
        in: query
        required: false
        schema:
          type: string
        example: '16'
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: campaignType
        in: query
        required: false
        schema:
          type: string
      - name: campaignName
        in: query
        required: false
        schema:
          type: string
      - name: active
        in: query
        required: false
        schema:
          type: string
      - name: scheduled
        in: query
        required: false
        schema:
          type: string
      - name: createdFrom
        in: query
        required: false
        schema:
          type: string
      - name: createdTo
        in: query
        required: false
        schema:
          type: string
      - name: updatedFrom
        in: query
        required: false
        schema:
          type: string
      - name: updatedTo
        in: query
        required: false
        schema:
          type: string
      - name: scheduleTimeFrom
        in: query
        required: false
        schema:
          type: string
      - name: scheduleTimeTo
        in: query
        required: false
        schema:
          type: string
      - name: recurrenceEndTimeFrom
        in: query
        required: false
        schema:
          type: string
      - name: recurrenceEndTimeTo
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: OK
  /email/email-service/validate/domain/{EMAIL_DOMAIN}:
    get:
      tags:
      - Email
      summary: Get Validated Domain
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        MX + basic deliverability check on the domain.

        ### Validate Domain

        Run comprehensive email security validation (MX, SPF, DMARC) for a domain.

        **Endpoint** `GET /email/email-service/validate/domain/{domain}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `domain` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Domain validation completed |
        | 400 | Invalid domain |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_email_email_service_validate_domain_EMAIL_DOMAIN
      parameters:
      - name: EMAIL_DOMAIN
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_DOMAIN
      responses:
        '200':
          description: OK
  /email/email-service/validate/spf/{EMAIL_DOMAIN}:
    get:
      tags:
      - Email
      summary: Get Validated SPF Domain
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Check SPF Record

        Retrieve and validate the SPF record for a domain.

        **Endpoint** `GET /email/email-service/validate/spf/{domain}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `domain` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | SPF check completed |
        | 400 | Invalid domain |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_email_email_service_validate_spf_EMAIL_DOMAIN
      parameters:
      - name: EMAIL_DOMAIN
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_DOMAIN
      responses:
        '200':
          description: OK
  /email/email-service/validate/dmarc/{EMAIL_DOMAIN}:
    get:
      tags:
      - Email
      summary: Get Validated DMARC Domain
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        ### Check DMARC Record

        Retrieve and validate the DMARC record for a domain.

        **Endpoint** `GET /email/email-service/validate/dmarc/{domain}`

        **Parameters**

        | Name | In | Required | Notes |
        |---|---|---|---|
        | `domain` | path | yes |  |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | DMARC check completed |
        | 400 | Invalid domain |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: get_email_email_service_validate_dmarc_EMAIL_DOMAIN
      parameters:
      - name: EMAIL_DOMAIN
        in: path
        required: true
        schema:
          type: string
        example: EMAIL_DOMAIN
      responses:
        '200':
          description: OK
  /email/email-service/bounce/scan:
    post:
      tags:
      - Email
      summary: Scan Bounce Emails
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        One-off scan of the bounce inbox for the last N hours.

        ### Scan for Bounces

        Scan an IMAP folder for bounce/DSN messages.

        **Endpoint** `POST /email/email-service/bounce/scan`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Bounce scan completed successfully |
        | 400 | Invalid request |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_service_bounce_scan
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                hours:
                  type: string
            examples:
              Scan Bounce Emails:
                value:
                  hours: '24'
      responses:
        '200':
          description: OK
  /email/email-service/bounce/monitor/start:
    post:
      tags:
      - Email
      summary: Start Monitoring Bounce Emails
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        Start the continuous bounce-monitor loop.

        ### Start Bounce Monitoring

        Start scheduled polling for bounce messages.

        **Endpoint** `POST /email/email-service/bounce/monitor/start`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Bounce monitoring started |
        | 400 | Invalid request |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_service_bounce_monitor_start
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                intervalSeconds:
                  type: integer
            examples:
              Start Monitoring Bounce Emails:
                value:
                  intervalSeconds: 60
      responses:
        '200':
          description: OK
  /email/email-service/bounce/monitor/stop:
    post:
      tags:
      - Email
      summary: Stop Monitoring Bounce Emails
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        Stop the continuous bounce-monitor loop.

        ### Stop Bounce Monitoring

        Stop scheduled bounce message polling.

        **Endpoint** `POST /email/email-service/bounce/monitor/stop`

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Bounce monitoring stopped |
        | 500 | Internal server error |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_service_bounce_monitor_stop
      responses:
        '200':
          description: OK
  /email/email-sandbox/sendTestEmail:
    post:
      tags:
      - Email
      summary: Send Sandbox Test Email
      description: |-
        **Authentication:** `Authorization: Bearer {{ACCESS_TOKEN}}`

        This request uses: `ACCESS_TOKEN` — tenant token.

        One-shot sandbox send for smoke-testing SMTP config.

        ### Send Email Messages (Sandbox)

        Sends a Email message via the sandbox email client.

        **Endpoint** `POST /email/email-sandbox/sendTestEmail`

        **Request body** `multipart/form-data`

        | Field | Type |
        |---|---|
        | `smtpId` | `integer` |
        | `campaignName` | `string` |
        | `subject` | `string` |
        | `body` | `string` |
        | `recipient` | `string` |
        | `ccRecipients` | `string` |
        | `bccRecipients` | `string` |
        | `attachmentList` | `array` |

        **Responses**

        | Status | Meaning |
        |---|---|
        | 200 | Success. |
        | 400 | Validation error. Body: `ExceptionResponse`. |
        | 401 / 403 | Missing or invalid bearer token / not allowed. |
        | 502 | Provider rejected the call. |
      operationId: post_email_email_sandbox_sendTestEmail
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                recipient:
                  type: string
                subject:
                  type: string
                body:
                  type: string
                fromAddress:
                  type: string
                smtpId:
                  type: string
            examples:
              Send Sandbox Test Email:
                value:
                  recipient: user@example.com
                  subject: Sandbox test
                  body: <p>Smoke test</p>
                  fromAddress: no-reply@broadnet.me
                  smtpId: '16'
      responses:
        '200':
          description: OK
