openapi: 3.0.3
info:
    title: Voice Agent by Mirai Minds
    version: 1.1.0
    description: |
        Build AI voice assistants that call your customers or handle inbound calls — no telephony expertise required.

        ## Authentication

        Every request (except `/health`) requires two headers:
        - `x-public-key` — your public key
        - `x-private-key` — your private key

        Workspace-scoped endpoints also need a `workspace` header with the workspace `_id` returned on onboarding.

        ## Entity Hierarchy

        ```
        Organization
        └── Workspace  (holds assistants + telephony numbers)
            └── Assistant
                ├── Telephony       (inbound + outbound phone numbers)
                ├── Knowledge Base  (documents + FAQ for RAG)
                └── Analysis Plan   (post-call AI evaluation)
        ```

        ## Quick Start (5 minutes)

        1. **Create a workspace** — `POST /v2/workspace/onboard/custom`
           → A default telephony number is auto-assigned in production.
        2. **Create an assistant** — `POST /v1/admin/assistant/create`
           → Use `variant.type: custom` and write your `agent.systemPrompt`.
        3. **Make a call** — `POST /v2/call/initiate`
           → Pass `callbackUrl` to receive real-time webhook events.

        See the **Onboarding** tag below for the full step-by-step guide.
    contact:
        name: API Architecture Team
        url: https://miraiminds.co
    license:
        name: Mirai Minds Proprietary License
        url: https://github.com/MiraiMinds/voice-agent-integration-specs/blob/main/LICENSE.md
servers:
    - url: https://api.voice-agents.miraiminds.co
      description: Production Server
    - url: https://api.stage.voice-agent.miraiminds.co
      description: Staging Server
    - url: http://localhost:3000
      description: Local Server

security:
    - PublicKeyAuth: []
      PrivateKeyAuth: []

# ----------------------------------------------------------------
# Shared example values — defined once here via YAML anchors,
# referenced as *alias wherever needed in path examples below.
# ----------------------------------------------------------------
x-shared-examples:
    abandonedCartVariables: &abandonedCartVariables
        - name: id
          type: string
          isRequired: false
        - name: abandonedCheckoutUrl
          type: string
          isRequired: true
        - name: customer
          type: object
          isRequired: true
          fields:
              - { name: firstName, type: string, isRequired: true }
              - { name: lastName, type: string, isRequired: false }
              - { name: email, type: string, isRequired: false }
              - { name: phone, type: string, isRequired: false }
        - name: totalDiscountSet
          type: object
          isRequired: false
          fields:
              - name: shopMoney
                type: object
                isRequired: false
                fields:
                    - { name: amount, type: string, isRequired: true }
        - name: totalLineItemsPriceSet
          type: object
          isRequired: true
          fields:
              - name: shopMoney
                type: object
                isRequired: true
                fields:
                    - { name: amount, type: string, isRequired: true }
        - name: subtotalPriceSet
          type: object
          isRequired: true
          fields:
              - name: shopMoney
                type: object
                isRequired: true
                fields:
                    - { name: amount, type: string, isRequired: true }
        - name: totalPriceSet
          type: object
          isRequired: true
          fields:
              - name: shopMoney
                type: object
                isRequired: true
                fields:
                    - { name: amount, type: string, isRequired: true }
        - name: lineItems
          type: array
          isRequired: true
          fields:
              - { name: title, type: string, isRequired: true }
              - { name: quantity, type: number, isRequired: true }
              - name: variant
                type: object
                isRequired: true
                fields:
                    - { name: id, type: string, isRequired: true }
                    - { name: title, type: string, isRequired: true }
        - name: note
          type: string
          isRequired: false
        - name: shippingAddress
          type: object
          isRequired: true
          fields:
              - { name: country, type: string, isRequired: true }
              - { name: address1, type: string, isRequired: true }
              - { name: address2, type: string, isRequired: false }
              - { name: city, type: string, isRequired: true }
              - { name: zip, type: string, isRequired: true }
              - { name: province, type: string, isRequired: true }

    abandonedCartCallInsightPlan: &abandonedCartCallInsightPlan
        callConnected:
            type: boolean
            description: 'You are a professional call status evaluator. Analyze the attached call recording and return true only if a live person answered and there was real two-way conversation. If the call went to voicemail, automated message, IVR, ring-tone, greeting, silence, or anything without a live response, return false. Output only true or false.'
            required: true
        customerEngaged:
            type: boolean
            description: 'You are a professional conversation engagement evaluator. Analyze the attached call recording and return true only if the customer did not disconnect abruptly at the beginning and continued engaging in the conversation for at least a few meaningful exchanges; otherwise return false. Output only true or false.'
            required: true

tags:
    - name: Onboarding
      description: |
          Create and configure a workspace. **Custom is the recommended path** for all non-Shopify integrations.

          ---

          ## Complete Onboarding Flow (Custom)

          ### Step 1 — Create a workspace

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v2/workspace/onboard/custom \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "Acme Support Line",
              "currencyCode": "USD",
              "timezone": "America/New_York",
              "supportContacts": {
                "phoneNumber": "+14155550100",
                "email": "support@acme.com"
              },
              "trustSignals": {
                "valuePropositionOneLiner": "Premium 24x7 AI support for Acme customers."
              }
            }'
          ```

          **Response:**
          ```json
          {
            "message": "Workspace onboarded successfully.",
            "data": {
              "_id": "6690a1b2c3d4e5f600000002",
              "name": "Acme Support Line",
              "variant": "custom"
            }
          }
          ```

          > **Auto-assigned number**: In production, every new workspace is automatically assigned a default telephony number. Check your assigned number via the Telephony APIs.

          ---

          ### Step 2 — Create an assistant

          Use the workspace `_id` from Step 1 as the `workspace` header value.

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/admin/assistant/create \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: 6690a1b2c3d4e5f600000002" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "Acme Support Assistant",
              "variant": { "type": "custom" },
              "agent": {
                "identity": { "name": "Priya", "gender": "female", "voice": "priya" },
                "systemPrompt": "You are Priya, a helpful support agent for Acme. The customer name is {{customerName}}. Resolve their issue politely and professionally."
              },
              "icpContext": { "language": "english" },
              "callSettings": {
                "slots": [{ "startTime": "09:00", "endTime": "18:00" }],
                "maxCallDuration": 300,
                "concurrentCallCount": 5,
                "retryProtocol": {
                  "maxAttemptsNoPickup": 2,
                  "maxAttemptsLowEngagement": 1,
                  "reAttemptPeriod": 300,
                  "maxRescheduleCount": 1
                }
              },
              "analysisPlan": {
                "successCriteriaPlan": "Return true only if the customer issue was fully resolved and the customer expressed satisfaction. Return false if they were still confused, unhappy, or escalated.",
                "summaryPlan": "Summarize the customer issue, the resolution provided, and the customer sentiment."
              }
            }'
          ```

          **Response:**
          ```json
          {
            "message": "Assistant created successfully",
            "data": { "assistantId": "69a57cdba3f3ab7e07cca1e4" }
          }
          ```

          > **Number auto-assignment**: The workspace default number is auto-assigned as `outbound` on the **first** assistant in the workspace. Additional assistants need numbers assigned explicitly via the `telephony` field in the create/update payload.

          ---

          ### Step 3 — (Optional) Purchase a dedicated inbound number

          Search for available numbers:
          ```bash
          curl "https://api.voice-agents.miraiminds.co/v1/number-pool/search?countryCode=US&limit=5" \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "organization: YOUR_ORG_ID"
          ```

          Purchase it:
          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/number-pool/purchase \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "organization: YOUR_ORG_ID" \
            -H "Content-Type: application/json" \
            -d '{ "number": "+14155550101", "countryCode": "US", "numberType": "local" }'
          ```

          Assign to assistant (inbound = customers call in, outbound = caller ID for outgoing calls):
          ```bash
          curl -X PUT https://api.voice-agents.miraiminds.co/v1/admin/assistant/update/69a57cdba3f3ab7e07cca1e4 \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: 6690a1b2c3d4e5f600000002" \
            -H "Content-Type: application/json" \
            -d '{
              "telephony": {
                "inbound": "6700a1b2c3d4e5f600000111",
                "outbound": "6700a1b2c3d4e5f600000222"
              }
            }'
          ```

          ---

          ### Step 4 — Make your first call

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v2/call/initiate \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: 6690a1b2c3d4e5f600000002" \
            -H "Content-Type: application/json" \
            -d '{
              "phoneNumber": "+14155550200",
              "assistant": "69a57cdba3f3ab7e07cca1e4",
              "callbackUrl": "https://yourapp.com/webhooks/call-events",
              "payload": { "customerName": "Alex" }
            }'
          ```

    - name: Assistant
      description: |
          Assistants are the core of the platform. Each assistant has:
          - An **identity** (name, voice, gender)
          - A **systemPrompt** (the AI's instructions)
          - **Telephony** config (inbound/outbound numbers)
          - A **Knowledge Base** (documents + FAQ for RAG retrieval)
          - An **analysisPlan** (post-call AI evaluation)
          - **callSettings** (scheduling, retry logic, concurrency)

          ---

          ## Variant Types

          | Variant | Use case | systemPrompt |
          |---------|----------|--------------|
          | `custom` | Any use case you define | Required — you author it |
          | `abandoned_cart` | Shopify cart recovery | Auto-generated — leave empty |
          | `cod_to_prepaid` | Convert Shopify COD orders to prepaid | Auto-generated — leave empty |
          | `address_verification` | Verify or collect Shopify shipping addresses | Auto-generated — leave empty |
          | `order_confirmation` | Confirm Shopify orders before fulfillment | Auto-generated — leave empty |
          | `ndr_followup` | Follow up on failed delivery / NDR events | Auto-generated — leave empty |

          ## Using Preset Variants

          1. Create the assistant with `variant.type` set to the preset variant and leave `agent.systemPrompt` empty.
          2. Put preset configuration under `variant.config.<variant_type>`.
          3. Initiate calls with `payload` fields that match the variant input schema. Shopify order variants use Shopify order-like payloads; `ndr_followup` uses courier NDR data.

          Config quick reference:
          - `cod_to_prepaid`: requires `paymentLinkValidity`, `codFee`, and `supportContacts`.
          - `address_verification`: requires `minDays`, `maxDays`, and `supportContacts`.
          - `order_confirmation`: optional `supportContacts`.
          - `ndr_followup`: optional `maxRescheduleDays`, `webhookToken`, and `supportContacts`. Shiprocket can post NDR events to `POST /v1/shiprocket/ndr-webhook/{assistantId}`; when `webhookToken` is set, send the same value in `x-api-key`.

          ---

          ## Using the Knowledge Base (RAG)

          The knowledge base lets the assistant retrieve information from your uploaded documents and FAQ during a live call.

          ### 1. Upload a document
          See the **Knowledge Base** tag for the full 3-step upload flow. After upload + processing, you get a file URL.

          ### 2. Link to the assistant

          Pass the file URL under `knowledgeBase.documents` when creating or updating the assistant:

          ```json
          {
            "knowledgeBase": {
              "documents": [
                {
                  "url": "https://storage.miraiminds.co/kb/acme-product-catalog.pdf",
                  "title": "Product Catalog",
                  "type": "pdf"
                }
              ],
              "faq": [
                {
                  "question": "What is your return policy?",
                  "answer": "We offer a 7-day return policy for unused items in original packaging."
                },
                {
                  "question": "How long does shipping take?",
                  "answer": "Standard shipping is 3–5 business days."
                }
              ]
            }
          }
          ```

          ### 3. Tell the assistant to use it in systemPrompt

          ```
          You are Priya, a support agent for Acme.

          When a customer asks about products, pricing, policies, or shipping:
          1. Search the knowledge base first.
          2. Use the retrieved information to answer accurately.
          3. If you cannot find the answer, say: "I don't have that detail right now — let me connect you with a specialist."

          Never make up information that is not in the knowledge base.
          Always greet the customer as {{customerName}}.
          ```

          ---

          ## Using analysisPlan

          `analysisPlan` instructs the AI to evaluate each call after it ends. Results appear in the `end-of-call` webhook event and the call dashboard.

          | Field | Type | Purpose |
          |-------|------|---------|
          | `successCriteriaPlan` | string prompt | AI returns `true`/`false` — was the goal achieved? |
          | `summaryPlan` | string prompt | AI returns a plain-English summary of the call |
          | `callInsightPlan` | object | AI returns structured key/value insights you define |

          ### Example — Customer Support

          ```json
          {
            "analysisPlan": {
              "successCriteriaPlan": "Return true ONLY if the customer issue was fully resolved and they expressed satisfaction before ending the call. Return false if they were still confused, frustrated, or requested a callback to a human agent.",
              "summaryPlan": "Summarize: (1) the customer issue, (2) the solution provided, (3) customer sentiment (positive/neutral/negative), and (4) any follow-up action needed.",
              "callInsightPlan": {
                "issueResolved": {
                  "type": "boolean",
                  "description": "Was the customer issue fully resolved during the call?",
                  "required": true
                },
                "escalationRequested": {
                  "type": "boolean",
                  "description": "Did the customer ask to speak with a human agent?",
                  "required": true
                },
                "customerSentiment": {
                  "type": "string",
                  "description": "Overall customer sentiment at end of call",
                  "required": true,
                  "enum": ["positive", "neutral", "negative"]
                }
              }
            }
          }
          ```

          ### Example — Appointment Booking

          ```json
          {
            "analysisPlan": {
              "successCriteriaPlan": "Return true ONLY if an appointment was confirmed with a specific date and time agreed by both parties. Return false for all other outcomes.",
              "summaryPlan": "Summarize: the appointment date, time, service type, and any special instructions the customer provided.",
              "callInsightPlan": {
                "appointmentBooked": {
                  "type": "boolean",
                  "description": "Was an appointment successfully booked?",
                  "required": true
                },
                "appointmentDate": {
                  "type": "string",
                  "description": "The confirmed appointment date (format: YYYY-MM-DD)",
                  "required": false
                }
              }
            }
          }
          ```

          ---

          ## Inbound Calls

          To handle inbound calls, assign a telephony number to `telephony.inbound`. When a customer calls that number, the assistant answers automatically.

          ```json
          {
            "telephony": {
              "inbound": "6700a1b2c3d4e5f600000111",
              "outbound": "6700a1b2c3d4e5f600000222"
            }
          }
          ```

          > Each inbound number can only be assigned to **one** assistant at a time. Assigning it to a new assistant automatically removes it from the previous one.

    - name: Knowledge Base
      description: |
          Upload documents so your assistant can answer questions from its own knowledge during a call (RAG — Retrieval-Augmented Generation).

          **Supported file types:** PDF, TXT, DOCX, Markdown
          **Max file size:** 100 MB
          **Max chunk size:** 10 MB per chunk

          ---

          ## Upload Flow (3 steps)

          Files are uploaded in chunks to handle network interruptions gracefully.

          ### Step 1 — Start an upload session

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/knowledge-base/upload/start \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: YOUR_WORKSPACE_ID" \
            -H "Content-Type: application/json" \
            -d '{
              "fileName": "product-catalog.pdf",
              "totalChunks": 1,
              "fileSize": 524288,
              "mimeType": "application/pdf"
            }'
          ```

          **Response:**
          ```json
          { "message": "Upload session created successfully.", "sessionId": "sess_abc123xyz" }
          ```

          ### Step 2 — Upload each chunk

          Repeat for each chunk (start at `chunkIndex: 0`):

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/knowledge-base/upload/chunk/sess_abc123xyz \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: YOUR_WORKSPACE_ID" \
            -F "chunk=@product-catalog.pdf" \
            -F "chunkIndex=0"
          ```

          **Response:**
          ```json
          { "message": "Chunk uploaded successfully." }
          ```

          ### Step 3 — Complete the upload

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/knowledge-base/upload/complete/sess_abc123xyz \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: YOUR_WORKSPACE_ID"
          ```

          **Response:**
          ```json
          {
            "message": "Upload completed. Processing has started in the background.",
            "sessionId": "sess_abc123xyz",
            "knowledgeBaseId": "6701a1b2c3d4e5f600000050",
            "knowledgeBaseStatus": "processing"
          }
          ```

          Processing is asynchronous. Poll `GET /v1/knowledge-base/files/{knowledgeBaseId}` until `status` is `ready`, then link the file to your assistant.

          ---

          ## What to Write in systemPrompt to Trigger Knowledge Base Retrieval

          ```
          You are a support agent for Acme.

          When a customer asks about products, pricing, policies, or shipping:
          1. Search the knowledge base first.
          2. Answer using only information found in the knowledge base.
          3. If the answer is not in the knowledge base, say:
             "I don't have that detail right now — let me connect you with a specialist."

          Never make up information. Always be accurate.
          ```

    - name: Telephony
      description: |
          Manage phone numbers for outbound and inbound calls.

          - **Outbound**: caller ID used when the assistant places a call to a customer
          - **Inbound**: the number customers dial to reach the assistant

          ---

          ## Using an Existing (Auto-Assigned) Number

          Every new workspace gets a default telephony number assigned automatically in production. Retrieve it and assign it to your assistant's `telephony.outbound` or `telephony.inbound`.

          ---

          ## Purchasing a New Number and Assigning to an Assistant

          ### Step 1 — Search available numbers

          ```bash
          curl "https://api.voice-agents.miraiminds.co/v1/number-pool/search?countryCode=US&numberType=local&limit=5" \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "organization: YOUR_ORG_ID"
          ```

          **Response:**
          ```json
          {
            "data": [
              { "number": "+14155550101", "countryCode": "US", "numberType": "local", "monthlyRateCents": 100 },
              { "number": "+14155550102", "countryCode": "US", "numberType": "local", "monthlyRateCents": 100 }
            ]
          }
          ```

          ### Step 2 — Purchase a number

          ```bash
          curl -X POST https://api.voice-agents.miraiminds.co/v1/number-pool/purchase \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "organization: YOUR_ORG_ID" \
            -H "Content-Type: application/json" \
            -d '{
              "number": "+14155550101",
              "countryCode": "US",
              "numberType": "local"
            }'
          ```

          **Response** (contains `_id` for use in assistant `telephony`):
          ```json
          {
            "data": {
              "_id": "6700a1b2c3d4e5f600000111",
              "number": "+14155550101",
              "status": "active"
            }
          }
          ```

          ### Step 3 — Assign to an assistant

          Use the `_id` from Step 2:

          ```bash
          curl -X PUT https://api.voice-agents.miraiminds.co/v1/admin/assistant/update/YOUR_ASSISTANT_ID \
            -H "x-public-key: YOUR_PUBLIC_KEY" \
            -H "x-private-key: YOUR_PRIVATE_KEY" \
            -H "workspace: YOUR_WORKSPACE_ID" \
            -H "Content-Type: application/json" \
            -d '{
              "telephony": {
                "inbound": "6700a1b2c3d4e5f600000111",
                "outbound": "6700a1b2c3d4e5f600000222"
              }
            }'
          ```

          > **Inbound exclusivity**: Each inbound number can only be held by one assistant at a time. Assigning it to a new assistant automatically removes it from the previous one.

    - name: Call
      description: |
          ## Outbound Calls

          Use `POST /v2/call/initiate` to trigger an outbound call to a customer. The assistant calls the number, runs the conversation, and fires webhook events to your `callbackUrl`.

          ---

          ## Inbound Calls

          Assign a telephony number to `telephony.inbound` on an assistant. When a customer dials that number, the assistant picks up automatically. No API call required — just the number assignment.

          ```
          Customer dials +14155550101
              → Number is linked to "Acme Support" assistant
              → Assistant picks up and follows its systemPrompt
              → Call events fire to your callbackUrl (if configured)
          ```

          ---

          ## Webhook Events Reference

          Register a `callbackUrl` on `POST /v2/call/initiate` to receive real-time call events.

          ### Event Payload Shape

          ```json
          {
            "event": {
              "type": "<event-type>",
              "data": { ... }
            }
          }
          ```

          ### Call Lifecycle Events

          | Event | When | What to do |
          |-------|------|-----------|
          | `call.initiate` | Call has been queued | Log that the call started |
          | `call.in-progress` | Customer answered, conversation started | Start session timer |
          | `call.ended` | Call hung up, analysis running | Update call record to pending |
          | `call.completed` | Call done + analysis complete | Read `analysis.success` and `analysis.summary` |
          | `call.timeout` | Call exceeded `maxCallDuration` | Flag for manual review |
          | `call.failed` | Network/telephony error | Retry or alert your team |
          | `call.busy` | Customer line was busy | Schedule retry |
          | `call.no-answer` | Rang with no answer | Schedule retry |
          | `call.skip` | Call skipped (outside allowed hours, etc.) | Log and continue |
          | `call.rescheduled` | Customer asked to be called back | Wait for next attempt |
          | `call.aborted` | Call cancelled via `/v2/call/abort` | Stop tracking |
          | `call.validation-failed` | Payload validation failed before calling | Fix payload and resubmit |
          | `call.lifecycle-ended` | All retries exhausted — call is permanently done | Final status update |
          | `end-of-call` | Same as `call.completed` with full analysis included | Primary event for reading results |
          | `action` | Assistant triggered a business action mid-call | Execute the action in your system |

          ### `end-of-call` Payload Example

          ```json
          {
            "event": {
              "type": "end-of-call",
              "data": {
                "call": {
                  "id": "call_6701abc123",
                  "status": "completed",
                  "startedAt": "2026-06-30T10:00:00.000Z",
                  "endedAt": "2026-06-30T10:05:32.000Z",
                  "durationSeconds": 332,
                  "recordingUrl": "https://storage.miraiminds.co/.../recording.wav",
                  "detailUrl": "https://app.miraiminds.co/calls/call_6701abc123"
                },
                "analysis": {
                  "success": true,
                  "summary": "Customer called about a delayed order. Issue resolved — package was confirmed dispatched. Customer was satisfied.",
                  "insights": {
                    "issueResolved": true,
                    "escalationRequested": false,
                    "customerSentiment": "positive"
                  }
                },
                "credits": {
                  "used": 2.5,
                  "available": 97.5
                }
              }
            }
          }
          ```

          ### `action` Event Payload Example

          ```json
          {
            "event": {
              "type": "action",
              "data": {
                "action": "create_order",
                "call": { "id": "call_6701abc123" },
                "payload": {
                  "email": "alex@example.com",
                  "phone": "+14155550200",
                  "lineItems": [{ "title": "Blue Sneakers", "quantity": 1 }],
                  "cartTotal": 99.99
                }
              }
            }
          }
          ```

          **Available action types:** `create_order`, `send_whatsapp`, `mark_prepaid`, `update_address`, `confirmed_address`

    - name: Setting
      description: Platform health and maintenance status.

    - name: Organization
      description: Archive and unarchive organizations and workspaces.

    - name: Voice Gallery
      description: List available AI voices for use in assistant configuration.

    - name: Showcase
      description: Real call recordings and use-case flow demos.

paths:
    /health:
        get:
            summary: platform health status
            operationId: getHealthMonitor
            description: >
                Returns whether the platform is currently under maintenance. No authentication required.
            tags:
                - Setting
            responses:
                '200':
                    description: Platform health status
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    status_code:
                                        type: integer
                                        example: 200
                                    message:
                                        type: string
                                        example: Platform is operational.
                                    data:
                                        type: object
                                        properties:
                                            underMaintenance:
                                                type: boolean
                                                example: false
                                            status:
                                                type: string
                                                example: healthy

    /v2/workspace/onboard/custom:
        post:
            summary: Onboard a custom workspace
            operationId: onboardCustomWorkspace
            description: >
                Creates a new **custom** workspace under the authenticated organization.
                Use this where you build assistants from scratch
                with your own system prompts and variables. The organization is resolved from
                the public/private key pair. A default outbound telephony number is auto-assigned
                in production.
            tags:
                - Onboarding
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CustomOnboardingRequest'
                        example:
                            name: 'Acme Support Line'
                            currencyCode: USD
                            timezone: 'America/New_York'
                            supportContacts:
                                phoneNumber: '+14155550100'
                                email: 'support@acme.com'
                            trustSignals:
                                valuePropositionOneLiner: 'Premium 24x7 customer support for Acme products.'
            responses:
                '200':
                    description: Workspace onboarded successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Workspace onboarded successfully.
                                    data:
                                        $ref: '#/components/schemas/Workspace'
                            example:
                                message: Workspace onboarded successfully.
                                data:
                                    _id: '6690a1b2c3d4e5f600000002'
                                    name: 'Acme Support Line'
                                    slug: 'acme-support-line'
                                    organization: '6690a1b2c3d4e5f600000001'
                                    variant: custom
                                    currencyCode: USD
                                    timezone: 'America/New_York'
                                    supportContacts:
                                        phoneNumber: '+14155550100'
                                        email: 'support@acme.com'
                                    createdAt: '2026-06-18T10:00:00.000Z'
                '400':
                    description: Validation Error or organization is archived
                '403':
                    description: Stand-alone organizations cannot create new workspaces
                '409':
                    description: Workspace already exists

    /v2/workspace/onboard/shopify:
        post:
            summary: Onboard a Shopify store (Shopify merchants only)
            operationId: initializeWorkspace
            description: >
                Shopify-specific onboarding. Uploads the store's identity, trust metrics, and policies.
                Returns the Workspace ID and Billing Configuration.

                **For all other integrations, use `POST /v2/workspace/onboard/custom` instead.**
            tags:
                - Onboarding
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/OnboardingRequest'
            responses:
                '201':
                    description: Workspace Created & Billing Configured
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/OnboardingResponse'
                '400':
                    description: Validation Error

    /v1/admin/assistant/get/{assistantId}:
        get:
            summary: Get AI Assistant
            operationId: adminGetAssistant
            description: >
                Fetches a single assistant by ID. Returns the full internal assistant configuration
                including variant config, agent identity, callSettings, analysisPlan, and knowledgeBase.
            tags:
                - Assistant
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: assistantId
                  in: path
                  required: true
                  schema:
                      type: string
            responses:
                '200':
                    description: Assistant fetched successfully
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/AssistantAdminGetResponse'
                            example:
                                message: Assistant fetched successfully
                                data:
                                    _id: '69a57cdba3f3ab7e07cca1e4'
                                    name: 'My Abandoned Cart Assistant'
                                    variant:
                                        type: abandoned_cart
                                        config:
                                            inputSchema: *abandonedCartVariables
                                            abandoned_cart:
                                                paymentPlan:
                                                    mode: online
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
                                    icpContext:
                                        targetAgeGroups: [millennials]
                                        locationTiers: [metro_urban]
                                        language: english
                                        targetAudience: [female]
                                    callSettings:
                                        slots:
                                            - startTime: '10:00'
                                              endTime: '17:30'
                                        maxCallDuration: 200
                                        concurrentCallCount: 5
                                        retryProtocol:
                                            maxAttemptsNoPickup: 2
                                            maxAttemptsLowEngagement: 1
                                            reAttemptPeriod: 300
                                            maxRescheduleCount: 1
                                    analysisPlan:
                                        successCriteriaPlan: "You are a professional order intent evaluator. Analyze the call recording and return true ONLY when ALL these conditions are met:\n1) Customer explicitly confirms they want to place/proceed with the order (e.g., \"yes, place it\", \"confirm the order\", \"go ahead\")\n2) Total price/amount was clearly discussed AND customer explicitly agreed to it\n3) Customer selects or confirms payment method (COD or prepaid)\n\nReturn false if:\n- Customer is \"just inquiring\", \"checking\", \"thinking about it\", or \"will let you know\"\n- Price not mentioned, customer objects to price, or asks for more discount after final price\n- Customer says \"already ordered\", \"will order online myself\", or \"order later\"\n- Call disconnected before explicit order confirmation\n- Intent is ambiguous or customer gives vague responses\n\nNote: Address validation is handled separately. If customer confirms order intent without mentioning address, they may be using an address already in context.\n\nWhen in doubt, return false."
                                        summaryPlan: 'Provide a concise summary of the conversation, customer objections, and the outcome'
                                        callInsightPlan: *abandonedCartCallInsightPlan
                                    knowledgeBase:
                                        documents:
                                            - url: 'https://example.com/product-catalog.pdf'
                                              title: 'Product Catalog'
                                              type: pdf
                                        faq:
                                            - question: 'What is your return policy?'
                                              answer: 'We offer a 7-day return policy for unused items.'
                                    archivedAt: null
                                    createdAt: '2026-03-02T12:04:43.086Z'
                                    timezone: UTC
                '404':
                    description: Assistant not found

    /v1/admin/assistant/list:
        get:
            summary: List AI Assistants
            operationId: adminListAssistants
            description: >
                Returns all assistants in the current workspace. Each item carries the **same
                payload** as the get-by-id endpoint (`GET /v1/admin/assistant/get/{assistantId}`),
                so no field selection is needed. Takes no query parameters or request body.
            tags:
                - Assistant
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            responses:
                '200':
                    description: Assistants fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Assistants fetched successfully
                                    data:
                                        type: array
                                        items:
                                            $ref: '#/components/schemas/AssistantDetailResponse'

    /v1/admin/assistant/create:
        post:
            summary: Create AI Assistant
            operationId: adminCreateAssistant
            description: >
                Creates a new AI assistant with the specified configuration.
                The `variant.type` determines the assistant's behavior and the required `variant.config` structure.


                **Variants**


                - `abandoned_cart` — a ready-made flow; provide `variant.config.abandoned_cart` (e.g. payment plan).
                  The system prompt is generated from the variant template, so `agent.systemPrompt` can be left empty.

                - `cod_to_prepaid` — converts Shopify COD orders to prepaid. Provide
                  `variant.config.cod_to_prepaid.paymentLinkValidity`, `codFee`, and `supportContacts`.

                - `address_verification` — verifies or collects Shopify shipping addresses. Provide
                  `variant.config.address_verification.minDays`, `maxDays`, and `supportContacts`.

                - `order_confirmation` — confirms Shopify orders before fulfillment. Optional config:
                  `variant.config.order_confirmation.supportContacts`.

                - `ndr_followup` — follows up on failed delivery / NDR events. Optional config:
                  `variant.config.ndr_followup.maxRescheduleDays`, `webhookToken`, and `supportContacts`.

                - `custom` — you fully author the behavior. Put your prompt in `agent.systemPrompt` and declare any
                  dynamic variables in `variant.config.inputSchema`.

                For preset variants, leave `agent.systemPrompt` empty and pass the required per-call data in
                `payload` when initiating the call.


                **Using variables in `agent.systemPrompt` (custom variant)**


                Reference a variable with the `{{variableName}}` placeholder syntax; nested values use dot-paths,
                e.g. `{{customer.firstName}}`. Each variable you reference should be declared in
                `variant.config.inputSchema` (name + type, mark `isRequired: true` when mandatory). The actual values
                are supplied **per call** through the `variableValues` object when you initiate the call — at that point
                every `{{placeholder}}` is substituted with the matching value. Any placeholder with no matching value
                is left untouched in the prompt.
            tags:
                - Assistant
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/AdminAssistantRequest'
                        examples:
                            custom:
                                summary: Custom assistant (recommended)
                                description: >
                                    `variant.type` is `custom` — use this for any use case you define.
                                    Variables referenced in `agent.systemPrompt` (e.g. `{{customerName}}`, `{{orderId}}`)
                                    are declared in `variant.config.inputSchema` and supplied per call via `variableValues`
                                    when initiating the call.
                                value:
                                    name: 'Order Update Assistant'
                                    variant:
                                        type: custom
                                        config:
                                            inputSchema:
                                                - name: customerName
                                                  type: string
                                                  isRequired: true
                                                - name: orderId
                                                  type: string
                                                  isRequired: true
                                                - name: deliveryDate
                                                  type: string
                                                  isRequired: false
                                                - name: token
                                                  type: string
                                                  isRequired: false
                                    agent:
                                        identity:
                                            name: priya
                                            gender: female
                                            voice: priya
                                        systemPrompt: 'You are Priya, a friendly support agent for Acme. Greet the customer: Hello {{customerName}}! You are calling about order {{orderId}}. If a delivery date is available, mention it: your order is expected on {{deliveryDate}}. Confirm the details and answer any questions politely. When asked about policies or products, search the knowledge base first.'
                                        tools:
                                            - '6710a1b2c3d4e5f600000020'
                                    telephony:
                                        inbound: '6700a1b2c3d4e5f600000111'
                                        outbound: '6700a1b2c3d4e5f600000222'
                                    preCall:
                                        apiPlan:
                                            method: post
                                            url: 'https://crm.acme.com/api/voice/lookup'
                                            headers:
                                                Authorization: 'Bearer {{variableValues.token}}'
                                            body:
                                                orderId: '{{variableValues.orderId}}'
                                                phone: '{{number}}'
                                    icpContext:
                                        language: english
                                    callSettings:
                                        slots:
                                            - startTime: '09:00'
                                              endTime: '18:00'
                                        maxCallDuration: 300
                                        concurrentCallCount: 5
                                        retryProtocol:
                                            maxAttemptsNoPickup: 2
                                            maxAttemptsLowEngagement: 1
                                            reAttemptPeriod: 300
                                            maxRescheduleCount: 1
                                    analysisPlan:
                                        successCriteriaPlan: 'Return true ONLY if the customer confirmed receipt of order details and had no unresolved concerns. Return false if they were confused, had complaints, or the call ended without confirmation.'
                                        summaryPlan: 'Summarize the order details discussed, any questions the customer asked, and the final outcome of the call.'
                                    knowledgeBase:
                                        documents:
                                            - url: 'https://storage.miraiminds.co/kb/acme-product-catalog.pdf'
                                              title: 'Product Catalog'
                                              type: pdf
                                        faq:
                                            - question: 'What is your return policy?'
                                              answer: 'We offer a 7-day return policy for unused items in original packaging.'
                            abandonedCart:
                                summary: Abandoned-cart assistant (Shopify)
                                description: >
                                    For `variant.type: abandoned_cart`. The system prompt is auto-generated
                                    from the variant template — leave `agent.systemPrompt` empty.
                                value:
                                    name: 'My Abandoned Cart Assistant'
                                    variant:
                                        type: abandoned_cart
                                        config:
                                            abandoned_cart:
                                                paymentPlan:
                                                    mode: online
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
                                    telephony:
                                        inbound: '6700a1b2c3d4e5f600000111'
                                        outbound: '6700a1b2c3d4e5f600000222'
                                    icpContext:
                                        targetAgeGroups: [millennials]
                                        locationTiers: [metro_urban]
                                        language: english
                                        targetAudience: [female]
                                    callSettings:
                                        slots:
                                            - startTime: '10:00'
                                              endTime: '17:30'
                                        maxCallDuration: 200
                                        concurrentCallCount: 5
                                        retryProtocol:
                                            maxAttemptsNoPickup: 2
                                            maxAttemptsLowEngagement: 1
                                            reAttemptPeriod: 300
                                            maxRescheduleCount: 1
                                    analysisPlan:
                                        successCriteriaPlan: 'Return true only when the customer explicitly confirms the order, agrees to the price, and selects a payment method; otherwise return false.'
                                        summaryPlan: 'Provide a concise summary of the conversation, customer objections, and the outcome'
                                    knowledgeBase:
                                        documents:
                                            - url: 'https://example.com/product-catalog.pdf'
                                              title: 'Product Catalog'
                                              type: pdf
                                        faq:
                                            - question: 'What is your return policy?'
                                              answer: 'We offer a 7-day return policy for unused items.'
                            codToPrepaid:
                                summary: COD-to-prepaid assistant (Shopify)
                                description: >
                                    For `variant.type: cod_to_prepaid`. The system prompt is auto-generated
                                    from the variant template — leave `agent.systemPrompt` empty.
                                value:
                                    name: 'COD to Prepaid Assistant'
                                    variant:
                                        type: cod_to_prepaid
                                        config:
                                            cod_to_prepaid:
                                                paymentLinkValidity: 30
                                                codFee: 50
                                                supportContacts:
                                                    phoneNumber: '+919876543210'
                                                    email: 'support@example.com'
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
                            addressVerification:
                                summary: Address-verification assistant (Shopify)
                                description: >
                                    For `variant.type: address_verification`. The system prompt is auto-generated
                                    from the variant template — leave `agent.systemPrompt` empty.
                                value:
                                    name: 'Address Verification Assistant'
                                    variant:
                                        type: address_verification
                                        config:
                                            address_verification:
                                                minDays: 3
                                                maxDays: 5
                                                supportContacts:
                                                    phoneNumber: '+919876543210'
                                                    email: 'support@example.com'
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
                            orderConfirmation:
                                summary: Order-confirmation assistant (Shopify)
                                description: >
                                    For `variant.type: order_confirmation`. The system prompt is auto-generated
                                    from the variant template — leave `agent.systemPrompt` empty.
                                value:
                                    name: 'Order Confirmation Assistant'
                                    variant:
                                        type: order_confirmation
                                        config:
                                            order_confirmation:
                                                supportContacts:
                                                    phoneNumber: '+919876543210'
                                                    email: 'support@example.com'
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
                            ndrFollowup:
                                summary: NDR follow-up assistant
                                description: >
                                    For `variant.type: ndr_followup`. The system prompt is auto-generated
                                    from the variant template — leave `agent.systemPrompt` empty.
                                value:
                                    name: 'NDR Follow-up Assistant'
                                    variant:
                                        type: ndr_followup
                                        config:
                                            ndr_followup:
                                                maxRescheduleDays: 3
                                                webhookToken: 'shiprocket-secret'
                                                supportContacts:
                                                    phoneNumber: '+919876543210'
                                                    email: 'support@example.com'
                                    agent:
                                        identity:
                                            name: neha
                                            gender: female
                                            voice: neha
                                        systemPrompt: ''
            responses:
                '200':
                    description: Assistant Created
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Assistant created successfully
                                    data:
                                        type: object
                                        properties:
                                            assistantId:
                                                type: string
                '400':
                    description: Validation Error
                '409':
                    description: Assistant with this name already exists

    /v1/admin/assistant/update/{assistantId}:
        put:
            summary: Update AI Assistant
            operationId: adminUpdateAssistant
            description: >
                Updates an existing assistant's configuration. All fields are optional — only the provided fields will be updated.
                The variant type cannot be changed. Any active campaigns for this assistant will be briefly paused and resumed during the update.
            tags:
                - Assistant
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: assistantId
                  in: path
                  required: true
                  schema:
                      type: string
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/AdminAssistantUpdateRequest'
                        example:
                            name: 'My Abandoned Cart Assistant'
                            variant:
                                config:
                                    abandoned_cart:
                                        paymentPlan:
                                            mode: online
                            agent:
                                identity:
                                    name: neha
                                    gender: female
                                    voice: neha
                                systemPrompt: ''
                                tools: ['6710a1b2c3d4e5f600000020']
                            telephony:
                                inbound: '6700a1b2c3d4e5f600000111'
                                outbound: '6700a1b2c3d4e5f600000222'
                            preCall:
                                apiPlan:
                                    method: post
                                    url: 'https://crm.acme.com/api/voice/lookup'
                                    headers:
                                        Authorization: 'Bearer {{variableValues.token}}'
                                    body:
                                        orderId: '{{variableValues.orderId}}'
                                        phone: '{{number}}'
                            icpContext:
                                targetAgeGroups: [millennials]
                                locationTiers: [metro_urban]
                                language: english
                                targetAudience: [female]
                            callSettings:
                                slots:
                                    - startTime: '10:00'
                                      endTime: '17:30'
                                maxCallDuration: 200
                                concurrentCallCount: 5
                                retryProtocol:
                                    maxAttemptsNoPickup: 2
                                    maxAttemptsLowEngagement: 1
                                    reAttemptPeriod: 300
                                    maxRescheduleCount: 1
                            analysisPlan:
                                successCriteriaPlan: "You are a professional order intent evaluator. Analyze the call recording and return true ONLY when ALL these conditions are met:\n1) Customer explicitly confirms they want to place/proceed with the order (e.g., \"yes, place it\", \"confirm the order\", \"go ahead\")\n2) Total price/amount was clearly discussed AND customer explicitly agreed to it\n3) Customer selects or confirms payment method (COD or prepaid)\n\nReturn false if:\n- Customer is \"just inquiring\", \"checking\", \"thinking about it\", or \"will let you know\"\n- Price not mentioned, customer objects to price, or asks for more discount after final price\n- Customer says \"already ordered\", \"will order online myself\", or \"order later\"\n- Call disconnected before explicit order confirmation\n- Intent is ambiguous or customer gives vague responses\n\nNote: Address validation is handled separately. If customer confirms order intent without mentioning address, they may be using an address already in context.\n\nWhen in doubt, return false."
                                summaryPlan: 'Provide a concise summary of the conversation, customer objections, and the outcome'
                            knowledgeBase:
                                documents:
                                    - url: 'https://example.com/product-catalog.pdf'
                                      title: 'Product Catalog'
                                      type: pdf
                                faq:
                                    - question: 'What is your return policy?'
                                      answer: 'We offer a 7-day return policy for unused items.'
            responses:
                '200':
                    description: Assistant Updated
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    assistantId:
                                        type: string
                '400':
                    description: Assistant is archived and cannot be updated
                '404':
                    description: Assistant not found
                '409':
                    description: Assistant with this name already exists

    /v1/number-pool/search:
        get:
            summary: Search available phone numbers
            operationId: searchAvailableNumbers
            description: >
                Returns a list of phone numbers available to purchase from the configured
                telephony provider, filtered by country and (optionally) a matching pattern.
            tags:
                - Telephony
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/OrganizationHeader'
                - name: countryCode
                  in: query
                  required: true
                  description: '2-letter ISO country code (case-insensitive).'
                  schema:
                      type: string
                      minLength: 2
                      maxLength: 2
                      example: IN
                - name: numberType
                  in: query
                  required: false
                  schema:
                      type: string
                      enum: [local]
                      example: local
                - name: pattern
                  in: query
                  required: false
                  description: 'Optional digit/letter pattern to match within available numbers.'
                  schema:
                      type: string
                      example: '415'
                - name: limit
                  in: query
                  required: false
                  schema:
                      type: integer
                      minimum: 1
                      maximum: 50
                      default: 20
                - name: provider
                  in: query
                  required: false
                  schema:
                      type: string
                      default: miraiminds
                      example: miraiminds
            responses:
                '200':
                    description: Available numbers fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Available numbers fetched successfully
                                    data:
                                        type: array
                                        items:
                                            $ref: '#/components/schemas/AvailableNumber'
                            example:
                                message: Available numbers fetched successfully
                                data:
                                    - number: '+918155550101'
                                      countryCode: IN
                                      numberType: local
                                      monthlyRateCents: 100
                                      setupFeeCents: 0
                                    - number: '+918155550102'
                                      countryCode: IN
                                      numberType: local
                                      monthlyRateCents: 100
                                      setupFeeCents: 0
                '400':
                    description: Validation Error

    /v1/number-pool/purchase:
        post:
            summary: Purchase an available phone number
            operationId: purchaseNumber
            description: >
                Purchases a phone number for the organization from the telephony provider.
                The organization is charged the setup fee and recurring monthly rate; a
                `402` is returned if the organization has insufficient credit balance.
            tags:
                - Telephony
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/OrganizationHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/PurchaseNumberRequest'
                        example:
                            number: '+918155550101'
                            provider: miraiminds
                            countryCode: IN
                            numberType: local
            responses:
                '201':
                    description: Phone number purchased successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Phone number purchased successfully
                                    data:
                                        $ref: '#/components/schemas/TelephonyNumber'
                            example:
                                message: Phone number purchased successfully
                                data:
                                    _id: '6700a1b2c3d4e5f600000222'
                                    number: '+918155550101'
                                    provider: miraiminds
                                    organization: '6690a1b2c3d4e5f600000001'
                                    workspace: null
                                    status: active
                                    providerNumberId: '6700a1b2c3d4e5f600000290'
                                    monthlyRateCents: 100
                                    setupFeeCents: 0
                                    countryCode: IN
                                    numberType: local
                                    createdAt: '2026-06-17T10:00:00.000Z'
                                    updatedAt: '2026-06-17T10:00:00.000Z'
                '400':
                    description: Validation Error
                '402':
                    description: Insufficient credit balance to purchase this number
                '404':
                    description: Organization not found

    /v1/number-pool/{telephonyNumberId}:
        delete:
            summary: Release a purchased phone number
            operationId: releaseNumber
            description: >
                Releases a previously purchased phone number back to the provider and marks
                the record as `released`. Recurring billing for the number stops.
            tags:
                - Telephony
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/OrganizationHeader'
                - name: telephonyNumberId
                  in: path
                  required: true
                  description: 'ObjectId of the telephony number record to release.'
                  schema:
                      type: string
                      example: '6700a1b2c3d4e5f600000222'
            responses:
                '200':
                    description: Phone number released successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: Phone number released successfully
                                    data:
                                        $ref: '#/components/schemas/TelephonyNumber'
                            example:
                                message: Phone number released successfully
                                data:
                                    _id: '6700a1b2c3d4e5f600000222'
                                    number: '+918155550101'
                                    provider: miraiminds
                                    organization: '6690a1b2c3d4e5f600000001'
                                    workspace: null
                                    status: released
                                    providerNumberId: '6700a1b2c3d4e5f600000290'
                                    monthlyRateCents: 100
                                    setupFeeCents: 0
                                    countryCode: IN
                                    numberType: local
                                    createdAt: '2026-06-17T10:00:00.000Z'
                                    updatedAt: '2026-06-17T11:00:00.000Z'
                '404':
                    description: Phone number not found for this organization
                '409':
                    description: Phone number is already released

    /v1/admin/tool/api:
        get:
            summary: List workspace API tools
            operationId: listApiTools
            description: 'Lists all user-defined API tools owned by the current workspace.'
            tags:
                - Tools
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            responses:
                '200':
                    description: API tools retrieved successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: API tools retrieved successfully.
                                    data:
                                        type: array
                                        items:
                                            $ref: '#/components/schemas/ApiTool'
        post:
            summary: Create an API tool
            operationId: createApiTool
            description: >
                Creates a user-defined API tool the assistant can call. The `name` must be
                unique within the workspace (a slug is auto-generated from it).
            tags:
                - Tools
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CreateApiToolRequest'
                        example:
                            name: Check Order Status
                            description: 'Look up the current status of a customer order by its ID.'
                            url: 'https://api.example.com/orders/status'
                            method: post
                            headers:
                                - key: Authorization
                                  value: 'Bearer <token>'
                            parameters:
                                required: [orderId]
                                properties:
                                    - name: orderId
                                      description: 'The order identifier to look up.'
                                      type: string
                            isActive: true
            responses:
                '201':
                    description: API tool created successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: API tool created successfully.
                                    data:
                                        $ref: '#/components/schemas/ApiTool'
                '400':
                    description: Validation Error
                '409':
                    description: An API tool with a similar name already exists in this workspace

    /v1/admin/tool/api/{toolId}:
        put:
            summary: Update an API tool
            operationId: updateApiTool
            description: 'Updates an existing API tool. All fields are optional — only provided fields are updated.'
            tags:
                - Tools
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: toolId
                  in: path
                  required: true
                  schema:
                      type: string
                      example: '6710a1b2c3d4e5f600000020'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/UpdateApiToolRequest'
                        example:
                            description: 'Updated description for when to use this tool.'
                            isActive: false
            responses:
                '200':
                    description: API tool updated successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: API tool updated successfully.
                                    data:
                                        $ref: '#/components/schemas/ApiTool'
                '400':
                    description: Validation Error
                '404':
                    description: API tool not found
                '409':
                    description: An API tool with a similar name already exists in this workspace
        delete:
            summary: Delete an API tool
            operationId: deleteApiTool
            description: 'Soft-deletes an API tool owned by the current workspace.'
            tags:
                - Tools
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: toolId
                  in: path
                  required: true
                  schema:
                      type: string
                      example: '6710a1b2c3d4e5f600000020'
            responses:
                '200':
                    description: API tool deleted successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: API tool deleted successfully.
                '404':
                    description: API tool not found

    # ----------------------------------------------------------------
    # KNOWLEDGE BASE UPLOAD API
    # ----------------------------------------------------------------

    /v1/knowledge-base/files:
        get:
            summary: List Knowledge Base Files
            operationId: listKnowledgeBaseFiles
            description: >
                Returns all uploaded knowledge base files for the current workspace.
                Use the returned file URL to set in `knowledgeBase.documents` on an assistant.
                Use the `collectionName` if manually configuring the RAG tool.
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            responses:
                '200':
                    description: Knowledge base files retrieved successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: 'Knowledge base files retrieved successfully.'
                                    data:
                                        type: array
                                        items:
                                            $ref: '#/components/schemas/KnowledgeBaseFile'
                            example:
                                message: 'Knowledge base files retrieved successfully.'
                                data:
                                    - _id: '6701a1b2c3d4e5f600000050'
                                      fileName: 'product-catalog.pdf'
                                      collectionName: 'rag_acme_product_catalog_v1'
                                      type: 'application/pdf'
                                      size: 524288
                                      status: 'ready'
                                      processingPercentage: 100
                                      workspace: '6690a1b2c3d4e5f600000002'
                                      createdAt: '2026-06-30T10:00:00.000Z'

    /v1/knowledge-base/files/{knowledgeBaseId}:
        get:
            summary: Get Knowledge Base File
            operationId: getKnowledgeBaseFile
            description: >
                Returns a single knowledge base file by ID including its processing status.
                Poll this endpoint after completing an upload to check when `status` changes to `ready`.
                Once `ready`, add the file to `knowledgeBase.documents` on the assistant.
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: knowledgeBaseId
                  in: path
                  required: true
                  schema:
                      type: string
                      example: '6701a1b2c3d4e5f600000050'
            responses:
                '200':
                    description: Knowledge base file retrieved successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: 'Knowledge base file retrieved successfully.'
                                    data:
                                        $ref: '#/components/schemas/KnowledgeBaseFile'
                            example:
                                message: 'Knowledge base file retrieved successfully.'
                                data:
                                    _id: '6701a1b2c3d4e5f600000050'
                                    fileName: 'product-catalog.pdf'
                                    collectionName: 'rag_acme_product_catalog_v1'
                                    type: 'application/pdf'
                                    size: 524288
                                    status: 'ready'
                                    processingPercentage: 100
                                    workspace: '6690a1b2c3d4e5f600000002'
                                    createdAt: '2026-06-30T10:00:00.000Z'
                '404':
                    description: Knowledge base file not found

    /v1/knowledge-base/upload/start:
        post:
            summary: Start Knowledge Base Upload Session
            operationId: startKnowledgeBaseUpload
            description: >
                Creates an upload session for a new knowledge base document.
                Returns a `sessionId` used for the subsequent chunk upload and complete calls.


                **Supported MIME types:** `application/pdf`, `text/plain`,
                `application/vnd.openxmlformats-officedocument.wordprocessingml.document`, `text/markdown`


                **Max file size:** 100 MB | **Max chunk size:** 10 MB
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/StartUploadSessionRequest'
                        example:
                            fileName: 'product-catalog.pdf'
                            totalChunks: 1
                            fileSize: 524288
                            mimeType: 'application/pdf'
            responses:
                '201':
                    description: Upload session created
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: 'Upload session created successfully.'
                                    sessionId:
                                        type: string
                                        example: 'sess_abc123xyz'
                            example:
                                message: 'Upload session created successfully.'
                                sessionId: 'sess_abc123xyz'
                '400':
                    description: File size exceeds 100 MB limit or MIME type not supported

    /v1/knowledge-base/upload/chunk/{sessionId}:
        post:
            summary: Upload Knowledge Base Chunk
            operationId: uploadKnowledgeBaseChunk
            description: >
                Uploads a single chunk of a file to an existing upload session.
                Send chunks sequentially starting from `chunkIndex: 0`.
                Use `multipart/form-data` with a `chunk` binary field and a `chunkIndex` form field.


                **Max chunk size:** 10 MB
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: sessionId
                  in: path
                  required: true
                  schema:
                      type: string
                      example: 'sess_abc123xyz'
            requestBody:
                required: true
                content:
                    multipart/form-data:
                        schema:
                            type: object
                            required:
                                - chunk
                                - chunkIndex
                            properties:
                                chunk:
                                    type: string
                                    format: binary
                                    description: 'The raw file chunk data'
                                chunkIndex:
                                    type: integer
                                    minimum: 0
                                    description: 'Zero-based index of this chunk (start at 0)'
                                    example: 0
            responses:
                '200':
                    description: Chunk uploaded successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: 'Chunk uploaded successfully.'
                '400':
                    description: Missing chunk file, negative chunkIndex, or chunk exceeds 10 MB
                '404':
                    description: Upload session not found

    /v1/knowledge-base/upload/complete/{sessionId}:
        post:
            summary: Complete Knowledge Base Upload
            operationId: completeKnowledgeBaseUpload
            description: >
                Finalises an upload session and triggers background processing (chunking, indexing, embedding).
                Returns a `knowledgeBaseId` you can use to poll status.


                Processing is asynchronous — poll `GET /v1/knowledge-base/files/{knowledgeBaseId}`
                until `status` is `ready`, then add the file URL to `knowledgeBase.documents` on your assistant.
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: sessionId
                  in: path
                  required: true
                  schema:
                      type: string
                      example: 'sess_abc123xyz'
            responses:
                '200':
                    description: Upload completed, processing started
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/CompleteUploadResponse'
                            example:
                                message: 'Upload completed. Processing has started in the background.'
                                sessionId: 'sess_abc123xyz'
                                knowledgeBaseId: '6701a1b2c3d4e5f600000050'
                                knowledgeBaseStatus: 'processing'
                '400':
                    description: Session not in `uploading` state, or already linked to a knowledge base
                '404':
                    description: Upload session not found

    /v1/knowledge-base/collection/{collectionName}:
        delete:
            summary: Delete Knowledge Base Collection
            operationId: deleteKnowledgeBaseCollection
            description: >
                Permanently deletes a knowledge base collection and all its indexed data.
                This action cannot be undone.


                The collection **cannot be deleted** if it is currently assigned to an assistant.
                Remove it from `knowledgeBase.documents` on the assistant first.
            tags:
                - Knowledge Base
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: collectionName
                  in: path
                  required: true
                  schema:
                      type: string
                      example: 'rag_acme_product_catalog_v1'
            responses:
                '200':
                    description: Collection deleted successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    message:
                                        type: string
                                        example: "Collection 'rag_acme_product_catalog_v1' deleted successfully."
                '404':
                    description: Collection not found for this workspace
                '409':
                    description: Collection is in use by an assistant and cannot be deleted

    /v2/call/initiate:
        post:
            summary: Initiate AI Call
            operationId: initiateCall
            tags:
                - Call
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/InitiateCallRequest'
                        examples:
                            abandoned_cart:
                                summary: 'Example for abandoned_cart variant'
                                description: 'Use this example when the assistant variant is abandoned_cart'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_123'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        id: 'gid://shopify/AbandonedCheckout/66509168181329'
                                        abandonedCheckoutUrl: 'https://example-store.myshopify.com/checkouts/ac/abc123xyz/recover?key=sample_recovery_key&locale=en-IN'
                                        customer:
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            email: null
                                            phone: '+919876543210'
                                        discountCodes: []
                                        totalLineItemsPriceSet:
                                            shopMoney:
                                                amount: '1895.0'
                                        totalDiscountSet:
                                            shopMoney:
                                                amount: '0.0'
                                        subtotalPriceSet:
                                            shopMoney:
                                                amount: '1895.0'
                                        totalPriceSet:
                                            shopMoney:
                                                amount: '1895.0'
                                        taxesIncluded: true
                                        taxLines:
                                            - rate: 0.05
                                              ratePercentage: 5
                                              source: null
                                              title: 'IGST'
                                              price: '90.24'
                                        lineItems:
                                            - title: 'Sample Product Name'
                                              quantity: 1
                                              variant:
                                                  id: 'gid://shopify/ProductVariant/58523289485393'
                                                  title: 'Default / Standard / Regular'
                                        billingAddress:
                                            country: 'India'
                                            phone: '+919876543211'
                                        shippingAddress:
                                            country: 'India'
                                            address1: '123 Sample Street, Sample Area'
                                            address2: 'Apt 4B'
                                            city: 'Delhi'
                                            province: 'DL'
                                            provinceCode: 'DL'
                                            zip: '110001'
                                            phone: '+919876543211'
                            cod_to_prepaid:
                                summary: 'Example for cod_to_prepaid variant'
                                description: 'Use this example when the assistant variant is cod_to_prepaid'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_789'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        name: '#1093'
                                        customer:
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            email: 'john@example.com'
                                            phone: '+919876543210'
                                        totalPrice: '1895.00'
                                        lineItems:
                                            - title: 'Sample Product Name'
                                              quantity: 1
                                              variantTitle: 'Default / Standard / Regular'
                                        discountCodes:
                                            - code: 'PREPAID50'
                                              amount: '50'
                                              type: 'fixed'
                            address_verification:
                                summary: 'Example for address_verification variant'
                                description: 'Use this example when the assistant variant is address_verification'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_790'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        name: '#1093'
                                        customer:
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            email: 'john@example.com'
                                            phone: '+919876543210'
                                        totalPrice: '1895.00'
                                        lineItems:
                                            - title: 'Sample Product Name'
                                              quantity: 1
                                              variantTitle: 'Default / Standard / Regular'
                                        shippingAddress:
                                            name: 'John Doe'
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            phone: '+919876543210'
                                            address1: '123 Sample Street'
                                            address2: 'Apt 4B'
                                            city: 'Delhi'
                                            zip: '110001'
                                            province: 'Delhi'
                                            country: 'India'
                            order_confirmation:
                                summary: 'Example for order_confirmation variant'
                                description: 'Use this example when the assistant variant is order_confirmation'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_791'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        name: '#1093'
                                        customer:
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            email: 'john@example.com'
                                            phone: '+919876543210'
                                        totalPrice: '1895.00'
                                        lineItems:
                                            - title: 'Sample Product Name'
                                              quantity: 1
                                              variantTitle: 'Default / Standard / Regular'
                                        financialStatus: 'pending'
                                        paymentGatewayNames: ['cash_on_delivery']
                            ndr_followup:
                                summary: 'Example for ndr_followup variant'
                                description: 'Use this example when the assistant variant is ndr_followup'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_792'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        awb: '190123456789'
                                        courierName: 'Delhivery'
                                        ndrReason: 'customer_unavailable'
                                        ndrRemark: 'Customer not available'
                                        attemptCount: 2
                                        orderId: '#1093'
                                        orderItems: 'one t-shirt'
                                        codAmount: '1895.00'
                                        paymentMethod: 'COD'
                                        nextAttemptDate: '2026-07-30'
                                        customer:
                                            firstName: 'John'
                                            lastName: 'Doe'
                                            email: 'john@example.com'
                                            phone: '+919876543210'
                                        shippingAddress:
                                            address1: '123 Sample Street'
                                            address2: 'Apt 4B'
                                            city: 'Delhi'
                                            zip: '110001'
                                            province: 'Delhi'
                                            country: 'India'
                            custom:
                                summary: 'Example for custom variant'
                                description: 'Use this example when the assistant variant is custom'
                                value:
                                    phoneNumber: '+919876543210'
                                    assistant: 'assistant_456'
                                    callbackUrl: 'https://example.com/webhooks/call-events'
                                    payload:
                                        orderId: 'ORD-12345'
                                        customerName: 'Jane Smith'
                                        orderValue: 2500
                                        status: 'pending'
                                        notes: 'Customer requested callback'
            responses:
                '200':
                    description: Call queued
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/InitiateCallResponse'
                '400':
                    description: Validation Error
                '404':
                    description: Assistant not found

    /v2/call/web:
        post:
            summary: Initiate AI Web Call
            operationId: initiateWebCall
            tags:
                - Call
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/InitiateWebCallRequest'
            responses:
                '201':
                    description: Web Call Initiated
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/InitiateWebCallResponse'
                '400':
                    description: Validation Error
                '404':
                    description: Assistant not found

    /v1/shiprocket/ndr-webhook/{assistantId}:
        post:
            summary: Receive Shiprocket NDR webhook
            operationId: shiprocketNdrWebhook
            description: >
                Queues an NDR follow-up call for an assistant whose `variant.type` is `ndr_followup`.
                If `variant.config.ndr_followup.webhookToken` is configured, send the same value in
                the `x-api-key` header.
            tags:
                - Call
            parameters:
                - name: assistantId
                  in: path
                  required: true
                  schema:
                      type: string
                - name: x-api-key
                  in: header
                  required: false
                  schema:
                      type: string
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            additionalProperties: true
                        example:
                            awb: '190123456789'
                            courier_name: 'Delhivery'
                            ndr_reason: 'customer_unavailable'
                            customer_name: 'John Doe'
                            customer_phone: '+919876543210'
                            order_id: '#1093'
            responses:
                '200':
                    description: Event queued or skipped
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    status:
                                        type: string
                                        enum: [queued, skipped]
                                    callId:
                                        type: string
                                    reason:
                                        type: string
                '400':
                    description: Assistant is not an NDR follow-up assistant, is archived, or the event cannot be processed
                '401':
                    description: Invalid webhook token
                '404':
                    description: Assistant not found

    /v2/call/abort:
        post:
            summary: Abort Call
            operationId: abortCall
            description: >
                Aborts a call that is queued or scheduled for retry.
                This operation is allowed when the call has no status (initial queue) or has a status of: 'busy', 'failed', 'no-answer', 'rescheduled', 'validation-failed'.
                It is NOT allowed if the call is 'in-progress', 'completed', 'ended', 'timeout', or already 'aborted'.
            tags:
                - Call
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/AbortCallRequest'
            responses:
                '200':
                    description: Call aborted
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/AbortCallResponse'
                '400':
                    description: Bad Request (Call already aborted, in progress, or completed)
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    code:
                                        type: integer
                                        example: 400
                                    message:
                                        type: string
                                        example: Call already aborted
                '404':
                    description: Call not found
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    code:
                                        type: integer
                                        example: 404
                                    message:
                                        type: string
                                        example: Call not found

    /v2/call/{callId}:
        put:
            summary: Update Call Payload
            operationId: updateCallPayload
            description: >
                Updates the `payload` of a queued call recipient.
                Allowed only when the call has not yet been attempted.
            tags:
                - Call
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
                - $ref: '#/components/parameters/WorkspaceHeader'
                - name: callId
                  in: path
                  required: true
                  description: The call (phone number recipient) ID.
                  schema:
                      type: string
                  example: '507f1f77bcf86cd799439011'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            type: object
                            required:
                                - payload
                            properties:
                                payload:
                                    type: object
                                    additionalProperties: true
                                    description: Replacement payload for the call.
                        example:
                            payload:
                                customer:
                                    firstName: 'Jane'
                                    phone: '+919876543210'
                                orderId: 'ORD-12345'
            responses:
                '200':
                    description: Call payload updated successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    status_code:
                                        type: integer
                                        example: 200
                                    message:
                                        type: string
                                        example: Call payload updated successfully.
                '400':
                    description: Validation error or call already in progress/completed
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    code:
                                        type: integer
                                        example: 400
                                    message:
                                        type: string
                                        example: Call already in progress or completed
                '401':
                    description: Unauthorized
                '404':
                    description: Call not found
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    code:
                                        type: integer
                                        example: 404
                                    message:
                                        type: string
                                        example: Call not found.

    /v2/webhooks/call-events:
        post:
            summary: Call Events Webhook
            operationId: callEventsWebhook
            tags:
                - Call
            description: Receives call status and action events
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/WebhookEvent'
            responses:
                '200':
                    description: Event received
                '400':
                    description: Invalid event payload

    /v1/admin/organization/archive:
        post:
            summary: Archive Organization or Workspace
            operationId: archiveOrganizationOrWorkspace
            description: >
                Archives an organization or workspace by ID. When archiving an organization,
                all associated workspaces, assistants and campaigns
                are also archived in a cascading manner. When archiving a workspace, all its
                associated assistants and campaigns are archived.
                Requires admin or organization_admin role.
            tags:
                - Organization
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/ArchiveUnarchiveRequest'
                        examples:
                            archive_organization:
                                summary: Archive an organization
                                value:
                                    type: organization
                                    id: '507f1f77bcf86cd799439011'
                            archive_workspace:
                                summary: Archive a workspace
                                value:
                                    type: workspace
                                    id: '507f1f77bcf86cd799439022'
            responses:
                '200':
                    description: Successfully archived
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ArchiveUnarchiveResponse'
                            examples:
                                organization_archived:
                                    summary: Organization archived
                                    value:
                                        status_code: 200
                                        message: Organization archived successfully.
                                        data: null
                                workspace_archived:
                                    summary: Workspace archived
                                    value:
                                        status_code: 200
                                        message: Workspace archived successfully.
                                        data: null
                '400':
                    description: Validation Error (invalid type or id)
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ErrorResponse'
                '401':
                    description: Unauthorized - missing or invalid authentication
                '403':
                    description: Forbidden - insufficient role permissions

    /v1/admin/organization/unarchive:
        post:
            summary: Unarchive Organization or Workspace
            operationId: unarchiveOrganizationOrWorkspace
            description: >
                Unarchives a previously archived organization or workspace by ID.
                When unarchiving an organization, all associated workspaces,
                assistants and campaigns are also unarchived in a cascading manner.
                When unarchiving a workspace, the parent organization must not be archived;
                if the parent organization is still archived, the request will fail with a 400 error.
                Requires admin or organization_admin role.
            tags:
                - Organization
            parameters:
                - $ref: '#/components/parameters/PublicKeyHeader'
                - $ref: '#/components/parameters/PrivateKeyHeader'
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/ArchiveUnarchiveRequest'
                        examples:
                            unarchive_organization:
                                summary: Unarchive an organization
                                value:
                                    type: organization
                                    id: '507f1f77bcf86cd799439011'
                            unarchive_workspace:
                                summary: Unarchive a workspace
                                value:
                                    type: workspace
                                    id: '507f1f77bcf86cd799439022'
            responses:
                '200':
                    description: Successfully unarchived
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ArchiveUnarchiveResponse'
                            examples:
                                organization_unarchived:
                                    summary: Organization unarchived
                                    value:
                                        status_code: 200
                                        message: Organization unarchived successfully.
                                        data: null
                                workspace_unarchived:
                                    summary: Workspace unarchived
                                    value:
                                        status_code: 200
                                        message: Workspace unarchived successfully.
                                        data:
                                            _id: '507f1f77bcf86cd799439022'
                                            organization: '507f1f77bcf86cd799439011'
                '400':
                    description: >
                        Validation Error or cannot unarchive workspace because
                        parent organization is archived
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ErrorResponse'
                            examples:
                                parent_archived:
                                    summary: Parent organization is archived
                                    value:
                                        code: 400
                                        message: Cannot unarchive workspace. Parent Organization is archived.
                '401':
                    description: Unauthorized - missing or invalid authentication
                '403':
                    description: Forbidden - insufficient role permissions

    /v1/admin/voice-gallery:
        get:
            summary: Get Voice Gallery
            operationId: getVoiceGallery
            tags:
                - Voice Gallery
            security:
                - PublicKeyAuth: []
                - PrivateKeyAuth: []
            responses:
                '200':
                    description: Voice Gallery fetched successfully
                '401':
                    description: Unauthorized - missing or invalid API keys
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    status_code:
                                        type: integer
                                        example: 200
                                    message:
                                        type: string
                                        example: Voices fetched successfully.
                                    data:
                                        type: array
                                        items:
                                            $ref: '#/components/schemas/VoiceGalleryItem'

    /v1/showcase/calls:
        get:
            summary: List real customer call recordings
            operationId: listShowcaseCalls
            description: >
                Returns real call recordings made for live stores.
                Optionally filter by call category or language.
            tags:
                - Showcase
            security: []
            parameters:
                - name: category
                  in: query
                  required: false
                  schema:
                      type: string
                      enum:
                          [
                              abandoned_cart,
                              bot_navigation,
                              uncertainty_handling,
                              bad_connection,
                              cod_confirmation,
                              all,
                          ]
                      default: all
                - name: lang
                  in: query
                  required: false
                  schema:
                      type: string
                      enum: [hi, bn, en, ta, te, all]
                      default: all
            responses:
                '200':
                    description: Calls fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    success:
                                        type: boolean
                                        example: true
                                    data:
                                        type: object
                                        properties:
                                            calls:
                                                type: array
                                                items:
                                                    $ref: '#/components/schemas/ShowcaseCall'
                                            total:
                                                type: integer
                                                example: 5

    /v1/showcase/calls/{call_id}:
        get:
            summary: Get a single real customer call
            operationId: getShowcaseCall
            tags:
                - Showcase
            security: []
            parameters:
                - name: call_id
                  in: path
                  required: true
                  schema:
                      type: string
                      pattern: '^[0-9a-fA-F]{24}$'
                  example: '507f1f77bcf86cd799439011'
            responses:
                '200':
                    description: Call fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    success:
                                        type: boolean
                                        example: true
                                    data:
                                        $ref: '#/components/schemas/ShowcaseCall'
                '404':
                    description: Call not found

    /v1/showcase/flows:
        get:
            summary: List demo flows
            operationId: listShowcaseFlows
            description: >
                Returns the product demo flows shown in the showcase page.
                These are produced demos of each use case, not real customer recordings.
            tags:
                - Showcase
            security: []
            responses:
                '200':
                    description: Flows fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    success:
                                        type: boolean
                                        example: true
                                    data:
                                        type: object
                                        properties:
                                            flows:
                                                type: array
                                                items:
                                                    $ref: '#/components/schemas/ShowcaseFlow'
                                            total:
                                                type: integer
                                                example: 5

    /v1/showcase/flows/{flow_id}:
        get:
            summary: Get a single demo flow
            operationId: getShowcaseFlow
            tags:
                - Showcase
            security: []
            parameters:
                - name: flow_id
                  in: path
                  required: true
                  schema:
                      type: string
                      pattern: '^[0-9a-fA-F]{24}$'
                  example: '507f1f77bcf86cd799439011'
            responses:
                '200':
                    description: Flow fetched successfully
                    content:
                        application/json:
                            schema:
                                type: object
                                properties:
                                    success:
                                        type: boolean
                                        example: true
                                    data:
                                        $ref: '#/components/schemas/ShowcaseFlow'
                '404':
                    description: Flow not found

components:
    securitySchemes:
        PublicKeyAuth:
            type: apiKey
            in: header
            name: x-public-key
        PrivateKeyAuth:
            type: apiKey
            in: header
            name: x-private-key
        BearerAuth:
            type: http
            scheme: bearer
            bearerFormat: JWT
            description: JWT token for admin and organization_admin authentication

    parameters:
        WorkspaceHeader:
            name: workspace
            in: header
            required: true
            schema:
                type: string
        PublicKeyHeader:
            name: x-public-key
            in: header
            required: true
            schema:
                type: string
        PrivateKeyHeader:
            name: x-private-key
            in: header
            required: true
            schema:
                type: string
        OrganizationHeader:
            name: organization
            in: header
            required: true
            schema:
                type: string

    schemas:
        # ----------------------------------------------------------------
        # RESPONSE OBJECT (Updated per requirements)
        # ----------------------------------------------------------------
        OnboardingResponse:
            type: object
            properties:
                workspace:
                    type: string
                    example: '4524239459234'
                    description: The unique key for all future API calls.

                status:
                    type: string
                    example: 'active'
                    enum: ['active', 'pending_verification', 'suspended']

                billing:
                    type: object
                    properties:
                        type:
                            type: string
                            example: 'prepaid'
                            enum: ['prepaid', 'postpaid']

                        creditBalance:
                            type: integer
                            example: 100
                            description: >
                                Current available credits in workspace

                        negativeCreditAllowance:
                            type: integer
                            example: 100
                            description: >
                                The 'Overdraft' limit. The AI will continue to make calls
                                for 100 credit even if credits hit 0 before suspending.

        CustomOnboardingRequest:
            type: object
            description: 'Payload for onboarding a custom (non-Shopify) workspace.'
            required:
                - name
                - currencyCode
                - timezone
                - supportContacts
                - trustSignals
            properties:
                name:
                    type: string
                    description: 'Display name of the workspace (a unique slug is derived from it).'
                    example: 'Acme Support Line'
                currencyCode:
                    type: string
                    minLength: 3
                    maxLength: 3
                    description: '3-letter ISO currency code (uppercased).'
                    example: USD
                timezone:
                    type: string
                    description: 'IANA timezone identifier.'
                    example: 'America/New_York'
                supportContacts:
                    type: object
                    required:
                        - phoneNumber
                    properties:
                        phoneNumber:
                            type: string
                            example: '+14155550100'
                        email:
                            type: string
                            format: email
                            example: 'support@acme.com'
                trustSignals:
                    type: object
                    required:
                        - valuePropositionOneLiner
                    properties:
                        valuePropositionOneLiner:
                            type: string
                            description: 'A one-line value proposition used to ground the assistant.'
                            example: 'Premium 24x7 customer support for Acme products.'

        Workspace:
            type: object
            description: 'A workspace belonging to an organization.'
            properties:
                _id:
                    type: string
                    example: '6690a1b2c3d4e5f600000002'
                name:
                    type: string
                    example: 'Acme Support Line'
                slug:
                    type: string
                    example: 'acme-support-line'
                organization:
                    type: string
                    example: '6690a1b2c3d4e5f600000001'
                variant:
                    type: string
                    enum: [shopify, school, custom]
                    example: custom
                currencyCode:
                    type: string
                    example: USD
                timezone:
                    type: string
                    example: 'America/New_York'
                supportContacts:
                    type: object
                    properties:
                        phoneNumber:
                            type: string
                        email:
                            type: string
                createdAt:
                    type: string
                    format: date-time
                    example: '2026-06-18T10:00:00.000Z'

        # ----------------------------------------------------------------
        # REQUEST OBJECTS (unchanged)
        # ----------------------------------------------------------------
        OnboardingRequest:
            type: object
            required:
                - name
                - currencyCode
                - timezone
                - supportContacts
                - trustSignals
                - policyFramework
            properties:
                name:
                    type: string
                    example: 'The Leather Co.'
                currencyCode:
                    type: string
                    example: 'INR'
                timezone:
                    type: string
                    example: 'Asia/Kolkata'
                supportContacts:
                    type: object
                    required:
                        - phoneNumber
                    properties:
                        phoneNumber:
                            type: string
                            example: '+91-9876543210'
                        email:
                            type: string
                            format: email
                            example: 'support@brand.com'
                trustSignals:
                    $ref: '#/components/schemas/TrustSignals'
                policyFramework:
                    $ref: '#/components/schemas/PolicyFramework'

        TrustSignals:
            type: object
            required:
                - valuePropositionOneLiner
            properties:
                customersTillDate:
                    type: integer
                    example: 15400
                totalOrdersFulfilled:
                    type: integer
                    example: 50000
                storeRating:
                    type: number
                    example: 4.8
                valuePropositionOneLiner:
                    type: string
                    example: 'Handcrafted in Jaipur using 100% sustainable vegan leather.'

        PolicyFramework:
            type: object
            required:
                - returnPolicy
                - shippingPolicy
                - codPolicy
            properties:
                returnPolicy:
                    $ref: '#/components/schemas/ReturnPolicy'
                shippingPolicy:
                    $ref: '#/components/schemas/ShippingPolicy'
                codPolicy:
                    $ref: '#/components/schemas/CodPolicy'

        ReturnPolicy:
            type: object
            properties:
                windowDays:
                    type: integer
                    example: 7
                processingFee:
                    type: object
                    properties:
                        amount:
                            type: number
                            example: 50
                refundTimelineDays:
                    type: integer
                    example: 3

        ShippingPolicy:
            type: object
            properties:
                deliveryTimeline:
                    type: object
                    properties:
                        minDays:
                            type: integer
                            example: 3
                        maxDays:
                            type: integer
                            example: 5
                freeShippingMinOrderValue:
                    type: number
                    example: 999

        CodPolicy:
            type: object
            properties:
                enabled:
                    type: boolean
                    example: true
                additionalFee:
                    type: object
                    properties:
                        amount:
                            type: number
                            example: 50

        SupportContacts:
            type: object
            properties:
                phoneNumber:
                    type: string
                    example: '+919876543210'
                email:
                    type: string
                    format: email
                    example: 'support@example.com'
        # ----------------------------------------------------------------
        # ADMIN API SCHEMAS (Internal format: variant.type, agent.identity)
        # ----------------------------------------------------------------
        AdminAssistantRequest:
            type: object
            required:
                - name
                - variant
                - agent
            properties:
                name:
                    type: string
                    maxLength: 40
                variant:
                    type: object
                    required:
                        - type
                    properties:
                        type:
                            type: string
                            enum:
                                [
                                    'abandoned_cart',
                                    'cod_to_prepaid',
                                    'address_verification',
                                    'order_confirmation',
                                    'ndr_followup',
                                    'custom',
                                ]
                            description: >
                                Preset variants use built-in flows (provide their matching `config.<variant_type>`
                                block when required) and auto-generate the prompt.
                                `custom` is fully authored by you — set `agent.systemPrompt` and declare any
                                variables in `config.inputSchema`.
                        config:
                            $ref: '#/components/schemas/VariantConfigs'
                agent:
                    type: object
                    required:
                        - identity
                    properties:
                        identity:
                            $ref: '#/components/schemas/AgentIdentity'
                        systemPrompt:
                            type: string
                            description: >
                                The assistant's instructions. For the `custom` variant, embed dynamic values
                                using the `{{variableName}}` placeholder syntax (nested values via dot-paths,
                                e.g. `{{customer.firstName}}`). Each variable should be declared in
                                `variant.config.inputSchema`; its value is supplied per call via `variableValues`
                                when initiating the call. Unmatched placeholders are left as-is.
                            example: 'Greet {{customerName}} and confirm details for order {{orderId}}.'
                        firstMessage:
                            type: string
                            description: >
                                The first message the assistant speaks when the call connects. If left empty,
                                a default greeting is generated based on the assistant identity and ICP language.
                            example: 'Hi, this is Neha calling from Acme. Am I speaking with the right person?'
                        endMessage:
                            type: string
                            description: >
                                The message the assistant speaks just before ending the call.
                            example: 'Thank you for your time. Have a great day!'
                        tools:
                            type: array
                            description: >
                                Tool `_id` values the assistant may call. Get them from the tools APIs;
                                the server determines and stores each tool's integration automatically.
                            items:
                                type: string
                            example: ['6710a1b2c3d4e5f600000020']
                telephony:
                    $ref: '#/components/schemas/AssistantTelephony'
                analysisPlan:
                    $ref: '#/components/schemas/AnalysisPlan'
                preCall:
                    allOf:
                        - $ref: '#/components/schemas/PreCall'
                    description: >
                        Configure pre-call enrichment during assistant creation. Supports templated
                        `apiPlan.headers` and `apiPlan.body` values from per-call `variableValues`.
                icpContext:
                    $ref: '#/components/schemas/ICPContext'
                callSettings:
                    $ref: '#/components/schemas/CallSettings'
                knowledgeBase:
                    $ref: '#/components/schemas/AdminKnowledgeBase'

        AdminAssistantUpdateRequest:
            type: object
            description: 'All fields are optional. Variant type cannot be changed.'
            properties:
                name:
                    type: string
                    maxLength: 40
                variant:
                    type: object
                    description: 'Only config can be updated — type cannot be changed.'
                    properties:
                        config:
                            $ref: '#/components/schemas/VariantConfigs'
                agent:
                    type: object
                    properties:
                        identity:
                            type: object
                            description: 'Partial update — only provided fields are updated.'
                            properties:
                                name:
                                    type: string
                                gender:
                                    type: string
                                    enum: ['male', 'female']
                                voice:
                                    type: string
                        systemPrompt:
                            type: string
                            description: >
                                For the `custom` variant, use `{{variableName}}` placeholders (declared in
                                `variant.config.inputSchema`, filled per call via `variableValues`).
                        firstMessage:
                            type: string
                            description: >
                                The first message the assistant speaks when the call connects. If left empty,
                                a default greeting is generated based on the assistant identity and ICP language.
                        endMessage:
                            type: string
                            description: >
                                The message the assistant speaks just before ending the call.
                        tools:
                            type: array
                            description: >
                                Replaces the assistant's tool list using tool `_id` values. The server
                                determines and stores each tool's integration automatically.
                            items:
                                type: string
                            example: ['6710a1b2c3d4e5f600000020']
                telephony:
                    $ref: '#/components/schemas/AssistantTelephony'
                analysisPlan:
                    $ref: '#/components/schemas/AnalysisPlan'
                preCall:
                    allOf:
                        - $ref: '#/components/schemas/PreCall'
                    description: >
                        Configure or replace pre-call enrichment during assistant update. Supports
                        templated `apiPlan.headers` and `apiPlan.body` values from per-call
                        `variableValues`.
                icpContext:
                    $ref: '#/components/schemas/ICPContext'
                callSettings:
                    type: object
                    properties:
                        slots:
                            type: array
                            items:
                                type: object
                                properties:
                                    startTime:
                                        type: string
                                        example: '10:00'
                                    endTime:
                                        type: string
                                        example: '17:30'
                        maxCallDuration:
                            type: number
                        concurrentCallCount:
                            type: number
                            maximum: 10
                        retryProtocol:
                            type: object
                            properties:
                                maxAttemptsNoPickup:
                                    type: number
                                maxAttemptsLowEngagement:
                                    type: number
                                reAttemptPeriod:
                                    type: number
                                maxRescheduleCount:
                                    type: number
                knowledgeBase:
                    $ref: '#/components/schemas/AdminKnowledgeBase'

        AdminKnowledgeBase:
            type: object
            description: 'Combined knowledge base containing both documents and FAQ entries.'
            properties:
                documents:
                    type: array
                    description: 'List of documents for deep knowledge retrieval.'
                    items:
                        type: object
                        required:
                            - url
                            - title
                            - type
                        properties:
                            url:
                                type: string
                                format: uri
                            title:
                                type: string
                            type:
                                type: string
                                enum: ['pdf', 'txt', 'docx', 'markdown']
                faq:
                    type: array
                    description: 'List of Question-Answer pairs.'
                    items:
                        $ref: '#/components/schemas/faq'

        # ----------------------------------------------------------------
        # AGENT CONFIG & TELEPHONY (Assistant create/update/response)
        # ----------------------------------------------------------------
        AssistantTelephony:
            type: object
            description: >
                Telephony numbers linked to the assistant. Each value is the `_id` of a telephony number
                (from `GET /v1/number-pool/{telephonyNumberId}` or `POST /v1/number-pool/purchase`).


                - `inbound` — the phone number customers call to reach this assistant. When someone dials it,
                  the assistant picks up automatically and follows its `systemPrompt`. Only one assistant can
                  hold an inbound number at a time; assigning it here removes it from any other assistant.
                - `outbound` — the caller ID shown to customers when the assistant places an outgoing call.


                **Auto-assignment**: In production, the first assistant in a new workspace automatically
                receives the workspace's default number as `outbound`. Additional assistants must be
                assigned numbers explicitly.
            properties:
                inbound:
                    type: string
                    nullable: true
                    description: >
                        `_id` of the telephony number used for inbound (incoming) calls.
                        Customers dial this number to reach the assistant.
                    example: '6700a1b2c3d4e5f600000111'
                outbound:
                    type: string
                    nullable: true
                    description: >
                        `_id` of the telephony number used as caller ID for outbound (outgoing) calls.
                    example: '6700a1b2c3d4e5f600000222'

        AgentTool:
            type: object
            description: >
                Internal response representation of tools grouped by their integration. Create and update
                requests only need the tool `_id` values; the server builds this grouping automatically.
            required:
                - integration_id
                - tools
            properties:
                integration_id:
                    type: string
                    description: 'ObjectId of the integration the tools belong to (the `integration_id` from the tool response).'
                    example: '6710a1b2c3d4e5f600000010'
                tools:
                    type: array
                    description: 'ObjectIds of the tools to enable (each is a tool `_id`, e.g. from `POST /v1/admin/tool/api`).'
                    items:
                        type: string
                    example: ['6710a1b2c3d4e5f600000020']

        # ----------------------------------------------------------------
        # TELEPHONY / NUMBER POOL
        # ----------------------------------------------------------------
        AvailableNumber:
            type: object
            description: 'A phone number available to purchase from the telephony provider.'
            properties:
                number:
                    type: string
                    example: '+14155550101'
                countryCode:
                    type: string
                    example: IN
                numberType:
                    type: string
                    enum: [local]
                    example: local
                monthlyRateCents:
                    type: integer
                    description: 'Recurring monthly rate in cents.'
                    example: 100
                setupFeeCents:
                    type: integer
                    description: 'One-time setup fee in cents.'
                    example: 0

        TelephonyNumber:
            type: object
            description: 'A telephony number owned by the organization.'
            properties:
                _id:
                    type: string
                    example: '6700a1b2c3d4e5f600000222'
                number:
                    type: string
                    example: '+918155550101'
                provider:
                    type: string
                    example: miraiminds
                organization:
                    type: string
                    example: '6690a1b2c3d4e5f600000001'
                workspace:
                    type: string
                    nullable: true
                    example: null
                status:
                    type: string
                    enum: [active, released]
                    example: active
                providerNumberId:
                    type: string
                    example: '6690a1b2c3d4e5f600000090'
                monthlyRateCents:
                    type: integer
                    example: 100
                setupFeeCents:
                    type: integer
                    example: 0
                countryCode:
                    type: string
                    example: IN
                numberType:
                    type: string
                    enum: [local]
                    example: local
                createdAt:
                    type: string
                    format: date-time
                    example: '2026-06-17T10:00:00.000Z'
                updatedAt:
                    type: string
                    format: date-time
                    example: '2026-06-17T10:00:00.000Z'

        PurchaseNumberRequest:
            type: object
            required:
                - number
                - countryCode
                - numberType
            properties:
                number:
                    type: string
                    minLength: 7
                    description: 'The phone number to purchase.'
                    example: '+918155550101'
                provider:
                    type: string
                    default: miraiminds
                    example: miraiminds
                countryCode:
                    type: string
                    minLength: 2
                    maxLength: 2
                    description: '2-letter ISO country code.'
                    example: IN
                numberType:
                    type: string
                    enum: [local]
                    example: local
                setupFeeCents:
                    type: integer
                    minimum: 0
                    default: 0
                    description: 'One-time setup fee in cents.'

        # ----------------------------------------------------------------
        # TOOLS
        # ----------------------------------------------------------------
        ToolProperty:
            type: object
            description: 'A parameter definition for an API tool. Supports nested object/array structures.'
            required:
                - name
            properties:
                name:
                    type: string
                description:
                    type: string
                type:
                    type: string
                    enum: ['string', 'number', 'boolean', 'object', 'array']
                    default: 'string'
                value: {}
                enum:
                    type: array
                    items: {}
                required:
                    type: array
                    description: 'Required nested property names (for `object` type).'
                    items:
                        type: string
                properties:
                    type: array
                    description: 'Nested properties (for `object` type).'
                    items:
                        $ref: '#/components/schemas/ToolProperty'
                items: {}

        ToolHeader:
            type: object
            required:
                - key
                - value
            properties:
                key:
                    type: string
                    example: Authorization
                value:
                    type: string
                    example: 'Bearer <token>'

        ToolParameters:
            type: object
            properties:
                required:
                    type: array
                    items:
                        type: string
                properties:
                    type: array
                    items:
                        $ref: '#/components/schemas/ToolProperty'

        ApiTool:
            type: object
            description: 'A user-defined API tool the assistant can invoke.'
            properties:
                _id:
                    type: string
                    example: '6710a1b2c3d4e5f600000020'
                name:
                    type: string
                    example: Check Order Status
                slug:
                    type: string
                    description: 'Auto-generated from the name; unique per workspace.'
                    example: check-order-status
                integration_id:
                    type: string
                    example: '6710a1b2c3d4e5f600000010'
                workspace:
                    type: string
                    example: '6690a1b2c3d4e5f600000002'
                isActive:
                    type: boolean
                    example: true
                isPayloadPass:
                    type: boolean
                    example: true
                config:
                    type: object
                    properties:
                        description:
                            type: string
                        url:
                            type: string
                            format: uri
                        method:
                            type: string
                            enum: ['get', 'post', 'put', 'patch', 'delete']
                        headers:
                            type: array
                            items:
                                $ref: '#/components/schemas/ToolHeader'
                        body:
                            $ref: '#/components/schemas/ToolParameters'
                deletedAt:
                    type: string
                    format: date-time
                    nullable: true
                    example: null
                createdAt:
                    type: string
                    format: date-time
                    example: '2026-06-17T10:00:00.000Z'
                updatedAt:
                    type: string
                    format: date-time
                    example: '2026-06-17T10:00:00.000Z'

        CreateApiToolRequest:
            type: object
            required:
                - name
                - description
                - url
                - method
            properties:
                name:
                    type: string
                    minLength: 1
                    example: Check Order Status
                description:
                    type: string
                    minLength: 1
                    description: 'Tells the agent when to trigger this tool.'
                    example: 'Look up the current status of a customer order by its ID.'
                url:
                    type: string
                    format: uri
                    example: 'https://api.example.com/orders/status'
                method:
                    type: string
                    enum: ['get', 'post', 'put', 'patch', 'delete']
                    example: post
                headers:
                    type: array
                    items:
                        $ref: '#/components/schemas/ToolHeader'
                parameters:
                    $ref: '#/components/schemas/ToolParameters'
                isActive:
                    type: boolean
                    default: true

        UpdateApiToolRequest:
            type: object
            description: 'All fields are optional — only provided fields are updated.'
            properties:
                name:
                    type: string
                    minLength: 1
                description:
                    type: string
                url:
                    type: string
                    format: uri
                method:
                    type: string
                    enum: ['get', 'post', 'put', 'patch', 'delete']
                headers:
                    type: array
                    items:
                        $ref: '#/components/schemas/ToolHeader'
                parameters:
                    $ref: '#/components/schemas/ToolParameters'
                isActive:
                    type: boolean

        AssistantAdminGetResponse:
            type: object
            properties:
                message:
                    type: string
                    example: Assistant fetched successfully
                data:
                    $ref: '#/components/schemas/AssistantDetailResponse'

        AssistantDetailResponse:
            type: object
            properties:
                _id:
                    type: string
                    example: '69b954f86ee9a7796fa57891'
                name:
                    type: string
                    example: 'My Assistant'
                variant:
                    type: object
                    properties:
                        type:
                            type: string
                            enum:
                                [
                                    'abandoned_cart',
                                    'cod_to_prepaid',
                                    'address_verification',
                                    'order_confirmation',
                                    'ndr_followup',
                                    'custom',
                                ]
                            example: abandoned_cart
                        config:
                            $ref: '#/components/schemas/VariantConfigs'
                agent:
                    type: object
                    properties:
                        identity:
                            $ref: '#/components/schemas/AgentIdentity'
                        systemPrompt:
                            type: string
                        firstMessage:
                            type: string
                            description: 'The first message the assistant speaks when the call connects.'
                        endMessage:
                            type: string
                            description: 'The message the assistant speaks just before ending the call.'
                        tools:
                            type: array
                            items:
                                $ref: '#/components/schemas/AgentTool'
                telephony:
                    $ref: '#/components/schemas/AssistantTelephony'
                icpContext:
                    $ref: '#/components/schemas/ICPContext'
                callSettings:
                    $ref: '#/components/schemas/CallSettings'
                analysisPlan:
                    $ref: '#/components/schemas/AnalysisPlan'
                knowledgeBase:
                    $ref: '#/components/schemas/AdminKnowledgeBase'
                archivedAt:
                    type: string
                    format: date-time
                    nullable: true
                    example: null
                createdAt:
                    type: string
                    format: date-time
                    example: '2026-03-17T13:19:52.297Z'
                timezone:
                    type: string
                    example: 'UTC'

        AdditionalField:
            type: object
            required:
                - name
            properties:
                name:
                    type: string
                type:
                    type: string
                    enum: ['string', 'number', 'boolean', 'object', 'array']
                    default: 'string'
                isRequired:
                    type: boolean
                fields:
                    type: array
                    items:
                        $ref: '#/components/schemas/AdditionalField'

        VariantConfigs:
            type: object
            description: >
                Variant-specific configuration. For the **custom** variant, declare the
                dynamic variables your `agent.systemPrompt` references via `inputSchema`.
                For preset variants, provide the matching block under the variant type when
                that variant requires config.
            properties:
                inputSchema:
                    type: array
                    description: >
                        **Used by the `custom` variant.** Declares the dynamic variables the
                        assistant expects for a call. Each variable declared here can be referenced
                        inside `agent.systemPrompt` using the `{{variableName}}` placeholder syntax
                        (nested values via dot-paths, e.g. `{{customer.firstName}}`), and its value
                        is supplied per call through `variableValues` when initiating the call.
                    items:
                        $ref: '#/components/schemas/AdditionalField'
                variableSchema:
                    type: object
                    description: 'Optional JSON-schema-style declaration of variables (alternative to `inputSchema`).'
                    properties:
                        properties:
                            type: object
                            additionalProperties:
                                type: object
                                properties:
                                    type:
                                        type: string
                                    description:
                                        type: string
                        required:
                            type: array
                            items:
                                type: string
                abandoned_cart:
                    type: object
                    description: 'Required when variant type is `abandoned_cart`.'
                    properties:
                        paymentPlan:
                            type: object
                            description: 'Payment plan configuration for the assistant.'
                            properties:
                                mode:
                                    type: string
                                    enum: [online, cod, both]
                                    description: 'Payment mode accepted by the store for this assistant.'
                                    example: online
                                additionalFee:
                                    type: object
                                    properties:
                                        cod:
                                            type: number
                                            description: 'Additional COD fee amount.'
                                            example: 50
                cod_to_prepaid:
                    type: object
                    description: 'Required when variant type is `cod_to_prepaid`.'
                    required:
                        - paymentLinkValidity
                        - codFee
                        - supportContacts
                    properties:
                        paymentLinkValidity:
                            type: number
                            description: 'How long the prepaid payment link remains valid, in minutes.'
                            example: 30
                        codFee:
                            type: number
                            description: 'COD fee amount the assistant can mention as the prepaid-saving incentive.'
                            example: 50
                        supportContacts:
                            $ref: '#/components/schemas/SupportContacts'
                address_verification:
                    type: object
                    description: 'Required when variant type is `address_verification`.'
                    required:
                        - minDays
                        - maxDays
                        - supportContacts
                    properties:
                        minDays:
                            type: number
                            description: 'Minimum expected delivery timeline in days.'
                            example: 3
                        maxDays:
                            type: number
                            description: 'Maximum expected delivery timeline in days.'
                            example: 5
                        supportContacts:
                            $ref: '#/components/schemas/SupportContacts'
                order_confirmation:
                    type: object
                    description: 'Optional when variant type is `order_confirmation`.'
                    properties:
                        supportContacts:
                            $ref: '#/components/schemas/SupportContacts'
                ndr_followup:
                    type: object
                    description: 'Optional when variant type is `ndr_followup`.'
                    properties:
                        maxRescheduleDays:
                            type: number
                            minimum: 1
                            maximum: 7
                            description: 'Maximum number of days ahead the customer can reschedule delivery.'
                            example: 3
                        webhookToken:
                            type: string
                            description: 'Shared secret expected in the `x-api-key` header for Shiprocket NDR webhooks.'
                            example: 'shiprocket-secret'
                        supportContacts:
                            $ref: '#/components/schemas/SupportContacts'

        RetryProtocol:
            type: object
            description: 'Smart logic based on why the call failed.'
            properties:
                maxAttemptsNoPickup:
                    type: integer
                    default: 2
                    description: 'Phone rang, no answer. Call back twice.'

                maxAttemptsLowEngagement:
                    type: integer
                    default: 1
                    description: "User picked up but said 'busy' or cut immediately. Call back once."

                reAttemptPeriod:
                    type: integer
                    default: 300
                    description: 'Delay between second reattempt of call to same person in seconds'

                maxRescheduleCount:
                    type: integer
                    default: 1
                    maximum: 5
                    description: 'How many times we can reschedule a call when user ask to callback'

        CallSettings:
            type: object
            required:
                - slots
                - retryProtocol
            properties:
                slots:
                    type: array
                    description: 'Array of time slots for call execution'
                    minItems: 1
                    items:
                        type: object
                        properties:
                            startTime:
                                type: string
                                example: '10:00'
                            endTime:
                                type: string
                                example: '13:00'

                maxCallDuration:
                    type: number
                    example: 200

                concurrentCallCount:
                    type: number
                    maximum: 10
                    example: 5

                retryProtocol:
                    $ref: '#/components/schemas/RetryProtocol'

        # ================================================================
        # SHARED COMPONENT: IDENTITY & ICP
        # ================================================================
        AgentIdentity:
            type: object
            properties:
                name:
                    type: string
                gender:
                    type: string
                    enum: ['male', 'female']
                voice:
                    type: string

        AnalysisPlan:
            type: object
            description: >
                Post-call AI evaluation configuration. After each call ends, the platform runs these prompts
                against the call recording and transcript. Results are returned in the `end-of-call` webhook event
                and visible in the call dashboard.
            properties:
                successCriteriaPlan:
                    type: string
                    description: >
                        A prompt instructing the AI to return `true` or `false` based on whether the call
                        objective was achieved. Write it as a precise instruction with explicit conditions.
                        The AI evaluates the call recording and returns only `true` or `false`.
                    example: 'Return true ONLY if the customer issue was fully resolved and they expressed satisfaction before ending the call. Return false if they were still confused, frustrated, or requested escalation.'
                summaryPlan:
                    type: string
                    description: >
                        A prompt instructing the AI to produce a plain-English summary of the call.
                        Tell it what aspects to cover (e.g. issue, resolution, sentiment, next steps).
                    example: 'Summarize: (1) the customer issue, (2) the solution provided, (3) customer sentiment (positive/neutral/negative), and (4) any follow-up action needed.'
                callInsightPlan:
                    $ref: '#/components/schemas/CallInsightPlan'

        PreCall:
            type: object
            description: >
                Pre-call enrichment. Before a call connects (inbound **or** outbound), if `apiPlan.url`
                is set the platform calls your endpoint and merges the data it returns into the call's
                `variableValues` — so your `systemPrompt` / `firstMessage` `{{placeholders}}` can use it
                (e.g. greet the caller by name, mention their latest order).


                Create and update assistant requests both accept this `preCall` shape. Existing
                configs with only `method` and `url` continue to work.


                **What the platform SENDS to your endpoint** — for `method: get` these are query
                parameters, for `method: post` a JSON body:


                ```json
                {
                  "number": "15551234567",
                  "assistantId": "69a57cdba3f3ab7e07cca1e4",
                  "callDirection": "inbound",
                  "orderId": "AC-1042"
                }
                ```

                `number` is the customer's phone number, `assistantId` the assistant handling the call,
                and `callDirection` is `"inbound"` or `"outbound"`. `apiPlan.headers` and
                `apiPlan.body` support templates from `variableValues`, `metadata`, `number`,
                `assistantId`, and `callDirection`, for example `{{variableValues.orderId}}` or
                `{{metadata.campaignId}}`.


                **What the platform EXPECTS back** — an HTTP `2xx` JSON response. If the response
                is a JSON object, its keys are spread into call variables. The older wrapped shape
                with a `data` object is also supported; in that case `data` is spread. The full
                response body is kept under `preCallData`.


                Direct object response:
                ```json
                {
                  "customerName": "Alice",
                  "orderId": "AC-1042",
                  "lastOrderStatus": "shipped"
                }
                ```

                Wrapped response:
                ```json
                {
                  "data": {
                    "customerName": "Alice",
                    "orderId": "AC-1042",
                    "lastOrderStatus": "shipped"
                  }
                }
                ```

                Both examples above produce `customerName`, `orderId`, and `lastOrderStatus` call
                variables available to the prompt. The full response body is also available as
                `preCallData`, so the wrapped example produces:
                ```json
                {
                  "preCallData": {
                    "data": {
                      "customerName": "Alice",
                      "orderId": "AC-1042",
                      "lastOrderStatus": "shipped"
                    }
                  }
                }
                ```


                If the endpoint returns an array, string, number, or boolean, only `preCallData`
                is set because there are no object keys to spread into top-level variables.


                **Failure handling** — the call is never blocked. If your endpoint is unreachable,
                times out, returns a non-2xx status, or returns an empty body, enrichment is skipped
                and the call proceeds without it.
            properties:
                apiPlan:
                    type: object
                    description: 'The external API to call before the conversation starts.'
                    properties:
                        method:
                            type: string
                            enum: ['get', 'post']
                            default: 'post'
                            description: >
                                HTTP method used to call your endpoint. `get` sends the request fields as
                                query parameters; `post` sends them as a JSON body.
                        url:
                            type: string
                            format: uri
                            description: 'Your HTTPS endpoint. Leave empty to disable pre-call enrichment.'
                            example: 'https://crm.acme.com/api/voice/lookup'
                        headers:
                            type: object
                            description: >
                                Optional HTTP headers. String values can use templates such as
                                `Bearer {{variableValues.token}}`.
                            additionalProperties:
                                oneOf:
                                    - type: string
                                    - type: number
                                    - type: boolean
                            example:
                                Authorization: 'Bearer {{variableValues.token}}'
                        body:
                            type: object
                            description: >
                                Optional JSON fields merged into the POST body after `number`,
                                `assistantId`, and `callDirection`. Ignored for GET.
                            additionalProperties: true
                            example:
                                orderId: '{{variableValues.orderId}}'
                                phone: '{{number}}'
                    example:
                        method: 'post'
                        url: 'https://crm.acme.com/api/voice/lookup'
                        headers:
                            Authorization: 'Bearer {{variableValues.token}}'
                        body:
                            orderId: '{{variableValues.orderId}}'
                            phone: '{{number}}'

        ICPContext:
            type: object
            properties:
                targetAgeGroups:
                    type: array
                    items:
                        type: string
                        enum: ['gen_z', 'millennials', 'gen_x', 'boomers']
                    description: "Affects slang usage. Gen Z = 'Vibe'; Boomers = 'Quality'."

                locationTiers:
                    type: array
                    items:
                        type: string
                        enum: ['metro_urban', 'tier1', 'tier2', 'tier3', 'rural']
                    description: 'Affects language complexity and speed.'

                # add language string with preference
                language:
                    type: string
                    enum:
                        [
                            'hinglish',
                            'english',
                            'hindi',
                            'telugu',
                            'tamil',
                            'kannada',
                            'malayalam',
                            'gujarati',
                            'punjabi',
                            'odia',
                            'marathi',
                        ]
                    description: 'Affects language complexity and speed.'

                # male or female or child focus brand add array of enum
                targetAudience:
                    type: array
                    items:
                        type: string
                        enum: ['male', 'female', 'children']
                    description: 'Affects language complexity and speed.'

        # ----------------------------------------------------------------
        # KNOWLEDGE BASE SCHEMAS
        # ----------------------------------------------------------------
        KnowledgeBaseFile:
            type: object
            description: 'A knowledge base document uploaded to the workspace.'
            properties:
                _id:
                    type: string
                    example: '6701a1b2c3d4e5f600000050'
                fileName:
                    type: string
                    example: 'product-catalog.pdf'
                collectionName:
                    type: string
                    description: 'Internal collection name used by the RAG search engine.'
                    example: 'rag_acme_product_catalog_v1'
                type:
                    type: string
                    description: 'MIME type of the uploaded file.'
                    example: 'application/pdf'
                size:
                    type: integer
                    description: 'File size in bytes.'
                    example: 524288
                status:
                    type: string
                    enum: ['processing', 'ready', 'failed']
                    description: '`processing` — indexing in progress; `ready` — available for use; `failed` — indexing failed.'
                    example: 'ready'
                processingPercentage:
                    type: integer
                    minimum: 0
                    maximum: 100
                    description: 'Indexing progress (0–100). Meaningful only when `status` is `processing`.'
                    example: 100
                workspace:
                    type: string
                    example: '6690a1b2c3d4e5f600000002'
                createdAt:
                    type: string
                    format: date-time
                    example: '2026-06-30T10:00:00.000Z'

        StartUploadSessionRequest:
            type: object
            required:
                - fileName
                - totalChunks
                - fileSize
            properties:
                fileName:
                    type: string
                    maxLength: 255
                    description: 'Original filename including extension.'
                    example: 'product-catalog.pdf'
                totalChunks:
                    type: integer
                    minimum: 1
                    maximum: 1000
                    description: 'Total number of chunks the file will be split into. Use 10 MB per chunk as the target size.'
                    example: 1
                fileSize:
                    type: integer
                    minimum: 1
                    description: 'Total file size in bytes. Maximum: 104857600 (100 MB).'
                    example: 524288
                mimeType:
                    type: string
                    description: >
                        MIME type of the file. Supported values:
                        `application/pdf`,
                        `text/plain`,
                        `application/vnd.openxmlformats-officedocument.wordprocessingml.document`,
                        `text/markdown`.
                    example: 'application/pdf'

        CompleteUploadResponse:
            type: object
            properties:
                message:
                    type: string
                    example: 'Upload completed. Processing has started in the background.'
                sessionId:
                    type: string
                    example: 'sess_abc123xyz'
                knowledgeBaseId:
                    type: string
                    description: 'ID to use when polling `GET /v1/knowledge-base/files/{knowledgeBaseId}` for status.'
                    example: '6701a1b2c3d4e5f600000050'
                knowledgeBaseStatus:
                    type: string
                    enum: ['processing', 'ready', 'failed']
                    example: 'processing'

        CallStatus:
            type: string
            description: Current call status
            enum:
                - initiate
                - in-progress
                - ended
                - completed
                - timeout
                - failed
                - validation-failed
                - busy
                - no-answer
                - skip
                - rescheduled
                - aborted

        EventType:
            type: string
            description: Webhook event type
            enum:
                - call.initiate
                - call.in-progress
                - call.ended
                - call.completed
                - call.timeout
                - call.failed
                - call.validation-failed
                - call.busy
                - call.no-answer
                - call.skip
                - call.rescheduled
                - call.aborted
                - call.lifecycle-ended
                - end-of-call
                - action

        ActionReason:
            type: string
            enum:
                - missing_address
                - missing_first_name
                - invalid_cart_data

        InitiateCallRequest:
            type: object
            required:
                - phoneNumber
                - assistant
            properties:
                phoneNumber:
                    type: string
                    description: Phone number (E.164 recommended)
                    example: '+919876543210'
                assistant:
                    type: string
                    description: Assistant ID
                payload:
                    anyOf:
                        - $ref: '#/components/schemas/AbandonedCartPayload'
                        - $ref: '#/components/schemas/ShopifyOrderPayload'
                        - $ref: '#/components/schemas/NdrFollowupPayload'
                        - $ref: '#/components/schemas/CustomPayload'
                    description: 'Payload structure depends on the assistant variant. Use AbandonedCartPayload for abandoned_cart, ShopifyOrderPayload for cod_to_prepaid/address_verification/order_confirmation, NdrFollowupPayload for ndr_followup, and CustomPayload for custom assistants.'
                callbackUrl:
                    type: string
                    format: uri
                    description: HTTPS webhook URL
                priority:
                    type: boolean
                    description: 'Call priority level'
                    example: true
                metadata:
                    type: object
                    properties:
                        discount:
                            type: object
                            properties:
                                code:
                                    type: string
                                description:
                                    type: string
                                value:
                                    type: number
                                codeType:
                                    type: string
                                    description: '%tage or fixed'
                                applyAs:
                                    type: string
                                    enum: ['additional', 'override']
                                    description: how discount is going to be applied
                    additionalProperties: true

        InitiateWebCallRequest:
            type: object
            required:
                - assistant
            properties:
                assistant:
                    type: string
                    description: Assistant ID
                systemPrompt:
                    type: string
                    description: Optional system prompt to override the default assistant prompt.
                payload:
                    anyOf:
                        - $ref: '#/components/schemas/AbandonedCartPayload'
                        - $ref: '#/components/schemas/ShopifyOrderPayload'
                        - $ref: '#/components/schemas/NdrFollowupPayload'
                        - $ref: '#/components/schemas/CustomPayload'
                    description: 'Payload structure depends on the assistant variant.'
                metadata:
                    type: object
                    additionalProperties: true

        InitiateCallResponse:
            type: object
            properties:
                status:
                    $ref: '#/components/schemas/CallStatus'
                callId:
                    type: string

        InitiateWebCallResponse:
            type: object
            properties:
                success:
                    type: boolean
                token:
                    type: string
                    description: LiveKit token for joining the web call.
                error:
                    type: object
                    nullable: true

        AbortCallRequest:
            type: object
            required:
                - callId
            properties:
                callId:
                    type: string

        AbortCallResponse:
            type: object
            properties:
                message:
                    type: string
                    example: 'Call aborted successfully'

        WebhookEvent:
            type: object
            required:
                - event
            properties:
                event:
                    type: object
                    required:
                        - type
                        - data
                    properties:
                        type:
                            allOf:
                                - type: string
                                - $ref: '#/components/schemas/EventType'
                            description: 'The event type'
                        data:
                            oneOf:
                                - $ref: '#/components/schemas/CallEventData'
                                - $ref: '#/components/schemas/ActionEventData'
                    discriminator:
                        propertyName: type
                        mapping:
                            call.initiate: '#/components/schemas/CallEventData'
                            call.in-progress: '#/components/schemas/CallEventData'
                            call.ended: '#/components/schemas/CallEventData'
                            call.completed: '#/components/schemas/CallEventData'
                            call.timeout: '#/components/schemas/CallEventData'
                            call.failed: '#/components/schemas/CallEventData'
                            call.validation-failed: '#/components/schemas/CallEventData'
                            call.busy: '#/components/schemas/CallEventData'
                            call.no-answer: '#/components/schemas/CallEventData'
                            call.skip: '#/components/schemas/CallEventData'
                            call.rescheduled: '#/components/schemas/CallEventData'
                            call.aborted: '#/components/schemas/CallEventData'
                            call.lifecycle-ended: '#/components/schemas/CallEventData'
                            end-of-call: '#/components/schemas/CallEventData'
                            action: '#/components/schemas/ActionEventData'
                metadata:
                    type: object
                    additionalProperties: true

        CreateOrderData:
            type: object
            properties:
                email:
                    type: string
                phone:
                    type: string
                lineItems:
                    type: array
                    items:
                        type: object
                shippingAddress:
                    type: object
                    properties:
                        firstName:
                            type: string
                        lastName:
                            type: string
                        address1:
                            type: string
                        address2:
                            type: string
                        city:
                            type: string
                        province:
                            type: string
                        zip:
                            type: string
                        country:
                            type: string
                        phone:
                            type: string
                cartTotal:
                    type: number
                codCharge:
                    type: number
                discount:
                    type: object
                    properties:
                        code:
                            type: string
                        reason:
                            type: string
                note:
                    type: string
                abandonedCheckoutId:
                    type: string
                    nullable: true

        SendWhatsapp:
            type: object
            properties:
                number:
                    type: string
                    nullable: true

        CallEventData:
            type: object
            properties:
                call:
                    type: object
                    properties:
                        id:
                            type: string
                            example: 'call_123456'
                        status:
                            $ref: '#/components/schemas/CallStatus'
                        startedAt:
                            type: string
                            format: date-time
                            nullable: true
                        endedAt:
                            type: string
                            format: date-time
                            nullable: true
                        recordingUrl:
                            type: string
                            format: uri
                            nullable: true
                            description: 'Call audio recording URL'
                        detailUrl:
                            type: string
                            format: uri
                            nullable: true
                            description: 'Call details page URL'
                        durationSeconds:
                            type: number
                            description: 'Call duration in seconds'
                            example: 45
                analysis:
                    type: object
                    properties:
                        success:
                            type: boolean
                        summary:
                            type: string
                            example: 'User expressed interest but requested a callback later.'
                        requiredActions:
                            type: array
                            description: "Actions required after call eg. ['create-order', 'send-whatsapp', 'send-email']"
                            items:
                                type: string
                        insights:
                            type: object
                            additionalProperties: true
                            example: { 'interested': true, 'callback_requested': true }
                credits:
                    type: object
                    properties:
                        used:
                            type: number
                            example: 1.5
                        available:
                            type: number
                            example: 98.5
                report:
                    type: object
                    properties:
                        reAttemptCount:
                            type: number
                        rescheduledCount:
                            type: number

        ActionEventData:
            type: object
            required:
                - action
            properties:
                action:
                    type: string
                    enum:
                        [
                            'create_order',
                            'send_whatsapp',
                            'mark_prepaid',
                            'update_address',
                            'confirmed_address',
                        ]
                call:
                    type: object
                    required:
                        - id
                    properties:
                        id:
                            type: string
                reason:
                    $ref: '#/components/schemas/ActionReason'
                    nullable: true
                payload:
                    oneOf:
                        - $ref: '#/components/schemas/SendWhatsapp'
                        - $ref: '#/components/schemas/CreateOrderData'

        AbandonedCartPayload:
            type: object
            description: 'Payload structure for abandoned cart recovery calls. Based on Shopify abandoned checkout webhook.'
            additionalProperties: false
            required:
                - customer
                - totalLineItemsPriceSet
                - lineItems
                - subtotalPriceSet
                - totalDiscountSet
                - totalPriceSet
            properties:
                id:
                    type: string
                    description: 'Shopify abandoned checkout ID (e.g., gid://shopify/AbandonedCheckout/...)'
                    example: 'gid://shopify/AbandonedCheckout/66509168181329'
                abandonedCheckoutUrl:
                    type: string
                    format: uri
                    description: 'Recovery URL for the abandoned checkout'
                    example: 'https://example-store.myshopify.com/checkouts/ac/abc123xyz/recover?key=sample_recovery_key&locale=en-IN'
                customer:
                    type: object
                    additionalProperties: false
                    required:
                        - firstName
                        - phone
                    properties:
                        firstName:
                            type: string
                            example: 'John'
                        lastName:
                            type: string
                            example: 'Doe'
                        email:
                            type: string
                            format: email
                            nullable: true
                        phone:
                            type: string
                            description: 'Customer phone number (E.164 recommended)'
                            example: '+919876543210'
                discountCodes:
                    type: array
                    description: 'Array of discount codes applied to the cart'
                    items:
                        type: string
                    default: []
                totalLineItemsPriceSet:
                    type: object
                    additionalProperties: false
                    properties:
                        shopMoney:
                            type: object
                            additionalProperties: false
                            properties:
                                amount:
                                    type: string
                                    example: '1895.0'
                totalDiscountSet:
                    type: object
                    additionalProperties: false
                    properties:
                        shopMoney:
                            type: object
                            additionalProperties: false
                            properties:
                                amount:
                                    type: string
                                    example: '0.0'
                subtotalPriceSet:
                    type: object
                    additionalProperties: false
                    properties:
                        shopMoney:
                            type: object
                            additionalProperties: false
                            properties:
                                amount:
                                    type: string
                                    example: '1895.0'
                totalPriceSet:
                    type: object
                    additionalProperties: false
                    properties:
                        shopMoney:
                            type: object
                            additionalProperties: false
                            properties:
                                amount:
                                    type: string
                                    example: '1895.0'
                taxesIncluded:
                    type: boolean
                    example: true
                taxLines:
                    type: array
                    items:
                        type: object
                        additionalProperties: false
                        properties:
                            rate:
                                type: number
                                example: 0.05
                            ratePercentage:
                                type: number
                                example: 5
                            source:
                                type: string
                                nullable: true
                            title:
                                type: string
                                example: 'IGST'
                            price:
                                type: string
                                example: '90.24'
                lineItems:
                    type: array
                    description: 'Products in the abandoned cart'
                    minItems: 1
                    items:
                        type: object
                        additionalProperties: false
                        required:
                            - title
                            - quantity
                        properties:
                            title:
                                type: string
                                example: 'Sample Product Name'
                            quantity:
                                type: integer
                                minimum: 1
                                example: 1
                            variant:
                                type: object
                                additionalProperties: false
                                required:
                                    - id
                                    - title
                                properties:
                                    id:
                                        type: string
                                        example: 'gid://shopify/ProductVariant/58523289485393'
                                    title:
                                        type: string
                                        example: 'Default / Standard / Regular'
                billingAddress:
                    type: object
                    additionalProperties: false
                    properties:
                        country:
                            type: string
                            example: 'India'
                        phone:
                            type: string
                            example: '+919876543211'
                shippingAddress:
                    type: object
                    additionalProperties: false
                    properties:
                        country:
                            type: string
                            example: 'India'
                        address1:
                            type: string
                            example: '123 Sample Street, Sample Area'
                        address2:
                            type: string
                            example: 'Apt 4B'
                        city:
                            type: string
                            example: 'Delhi'
                        province:
                            type: string
                            example: 'DL'
                        provinceCode:
                            type: string
                            example: 'DL'
                        zip:
                            type: string
                            example: '110001'
                        phone:
                            type: string
                            example: '+919876543211'

        ShopifyOrderPayload:
            type: object
            description: 'Payload for cod_to_prepaid, address_verification, and order_confirmation assistants. Based on Shopify order webhook data.'
            additionalProperties: true
            required:
                - name
                - customer
                - totalPrice
                - lineItems
            properties:
                name:
                    type: string
                    description: 'Shopify order name / reference, e.g. #1093.'
                    example: '#1093'
                customer:
                    type: object
                    required:
                        - firstName
                    properties:
                        firstName:
                            type: string
                            example: 'John'
                        lastName:
                            type: string
                            example: 'Doe'
                        email:
                            type: string
                            format: email
                            example: 'john@example.com'
                        phone:
                            type: string
                            example: '+919876543210'
                totalPrice:
                    type: string
                    example: '1895.00'
                lineItems:
                    type: array
                    minItems: 1
                    items:
                        type: object
                        required:
                            - title
                            - quantity
                        properties:
                            title:
                                type: string
                                example: 'Sample Product Name'
                            quantity:
                                type: number
                                example: 1
                            variantTitle:
                                type: string
                                example: 'Default / Standard / Regular'
                discountCodes:
                    type: array
                    items:
                        type: object
                        properties:
                            code:
                                type: string
                            amount:
                                type: string
                            type:
                                type: string
                financialStatus:
                    type: string
                    description: 'Useful for order_confirmation payment-mode detection.'
                    example: 'pending'
                paymentGatewayNames:
                    type: array
                    description: 'Useful for order_confirmation payment-mode detection.'
                    items:
                        type: string
                    example: ['cash_on_delivery']
                shippingAddress:
                    type: object
                    description: 'Useful for address_verification.'
                    properties:
                        name:
                            type: string
                            example: 'John Doe'
                        firstName:
                            type: string
                            example: 'John'
                        lastName:
                            type: string
                            example: 'Doe'
                        phone:
                            type: string
                            example: '+919876543210'
                        address1:
                            type: string
                            example: '123 Sample Street'
                        address2:
                            type: string
                            example: 'Apt 4B'
                        city:
                            type: string
                            example: 'Delhi'
                        zip:
                            type: string
                            example: '110001'
                        province:
                            type: string
                            example: 'Delhi'
                        country:
                            type: string
                            example: 'India'

        NdrFollowupPayload:
            type: object
            description: 'Payload for ndr_followup assistants. You can send this directly to /v2/call/initiate or let the Shiprocket NDR webhook map courier fields into this shape.'
            additionalProperties: true
            required:
                - awb
                - ndrReason
                - customer
            properties:
                awb:
                    type: string
                    example: '190123456789'
                courierName:
                    type: string
                    example: 'Delhivery'
                ndrReason:
                    type: string
                    description: 'Courier NDR reason or normalized code.'
                    example: 'customer_unavailable'
                ndrRemark:
                    type: string
                    example: 'Customer not available'
                attemptCount:
                    type: number
                    example: 2
                orderId:
                    type: string
                    example: '#1093'
                orderItems:
                    type: string
                    example: 'one t-shirt'
                codAmount:
                    type: string
                    example: '1895.00'
                paymentMethod:
                    type: string
                    example: 'COD'
                nextAttemptDate:
                    type: string
                    example: '2026-07-30'
                customer:
                    type: object
                    required:
                        - firstName
                    properties:
                        firstName:
                            type: string
                            example: 'John'
                        lastName:
                            type: string
                            example: 'Doe'
                        email:
                            type: string
                            format: email
                            example: 'john@example.com'
                        phone:
                            type: string
                            example: '+919876543210'
                shippingAddress:
                    type: object
                    properties:
                        address1:
                            type: string
                            example: '123 Sample Street'
                        address2:
                            type: string
                            example: 'Apt 4B'
                        city:
                            type: string
                            example: 'Delhi'
                        zip:
                            type: string
                            example: '110001'
                        province:
                            type: string
                            example: 'Delhi'
                        country:
                            type: string
                            example: 'India'

        CustomPayload:
            type: object
            description: 'Flexible payload structure for custom assistant variants. Can include any fields relevant to the call.'
            additionalProperties: true
            example:
                orderId: 'ORD-12345'
                customerName: 'Jane Smith'
                orderValue: 2500
                status: 'pending'
                notes: 'Customer requested callback'

        CallInsightPlan:
            type: object
            additionalProperties:
                $ref: '#/components/schemas/InsightField'
            description: 'Map of insight names to their expected structure.'

        InsightField:
            type: object
            required:
                - type
                - description
                - required
            properties:
                type:
                    type: string
                    enum: ['number', 'boolean', 'string']
                description:
                    type: string
                required:
                    type: boolean
                enum:
                    type: array
                    items:
                        type: string

        faq:
            type: object
            required:
                - question
                - answer
            properties:
                question:
                    type: string
                    example: 'What is your return policy?'
                answer:
                    type: string
                    example: 'We offer a 7-day return policy for unused items.'

        VoiceGalleryItem:
            type: object
            properties:
                _id:
                    type: string
                    description: Unique identifier for the voice gallery item.
                slug:
                    type: string
                    description: Slug for the voice (e.g., 'sagar').
                sampleAudio:
                    type: string
                    description: URL of the sample audio file.

        # ----------------------------------------------------------------
        # ARCHIVE / UNARCHIVE SCHEMAS
        # ----------------------------------------------------------------
        ArchiveUnarchiveRequest:
            type: object
            required:
                - type
                - id
            properties:
                type:
                    type: string
                    enum:
                        - organization
                        - workspace
                    description: >
                        The entity type to archive or unarchive.
                        Use "organization" to target an organization (cascades to all workspaces, assistants, and campaigns).
                        Use "workspace" to target a single workspace (cascades to its assistants and campaigns).
                    example: organization
                id:
                    type: string
                    pattern: '^[0-9a-fA-F]{24}$'
                    description: The MongoDB ObjectId of the organization or workspace to archive/unarchive.
                    example: '507f1f77bcf86cd799439011'

        ArchiveUnarchiveResponse:
            type: object
            properties:
                status_code:
                    type: integer
                    example: 200
                message:
                    type: string
                    example: Organization archived successfully.
                data:
                    type: object
                    nullable: true
                    description: >
                        For archive operations and organization unarchive, this is null.
                        For workspace unarchive, this contains the workspace document.

        ErrorResponse:
            type: object
            properties:
                code:
                    type: integer
                    example: 400
                message:
                    type: string
                    example: Validation error

        # ----------------------------------------------------------------
        # SHOWCASE SCHEMAS
        # ----------------------------------------------------------------

        ShowcaseHighlightMoment:
            type: object
            properties:
                atSecs:
                    type: integer
                    description: Timestamp in seconds to pin within the audio.
                    example: 12
                label:
                    type: string
                    example: IVR detected
            required: [atSecs, label]

        ShowcaseCall:
            type: object
            description: A real customer call recording used for social proof on the showcase page.
            properties:
                _id:
                    type: string
                    example: '507f1f77bcf86cd799439011'
                title:
                    type: string
                    example: Cart recovery call
                language:
                    type: string
                    enum: [hi, bn, en, ta, te]
                    example: bn
                languageLabel:
                    type: string
                    example: Bengali
                category:
                    type: string
                    enum:
                        [
                            abandoned_cart,
                            bot_navigation,
                            uncertainty_handling,
                            bad_connection,
                            cod_confirmation,
                        ]
                    example: abandoned_cart
                brandName:
                    type: string
                    description: Name of the store this call was made for.
                    example: StyleKart
                brandLogoUrl:
                    type: string
                    nullable: true
                    example: 'https://cdn.example.com/stylekart_logo.png'
                description:
                    type: string
                    example: A real Bengali customer who dropped off mid-checkout. AI called back and recovered the order.
                durationSecs:
                    type: integer
                    example: 63
                audioUrl:
                    type: string
                    example: 'https://storage.miraiminds.co/voice-agents/production/call_records/abc123/recording.wav'
                waveformUrl:
                    type: string
                    nullable: true
                    example: 'https://storage.miraiminds.co/voice-agents/production/call_records/abc123/waveform.json'
                transcriptPreview:
                    type: string
                    nullable: true
                    example: 'Namaste Priya ji, aapne ek blue kurta cart mein...'
                highlightMoments:
                    type: array
                    items:
                        $ref: '#/components/schemas/ShowcaseHighlightMoment'
                whatToNotice:
                    type: string
                    nullable: true
                    example: Notice how the AI stays in Bengali throughout without switching.
                tags:
                    type: array
                    items:
                        type: string
                    example: [bengali, recovery]
                sortOrder:
                    type: integer
                    example: 1
            required:
                [
                    title,
                    language,
                    languageLabel,
                    category,
                    brandName,
                    description,
                    durationSecs,
                    audioUrl,
                    sortOrder,
                ]

        ShowcaseFlow:
            type: object
            description: A produced demo of a use case flow shown on the showcase page.
            properties:
                _id:
                    type: string
                    example: '507f1f77bcf86cd799439012'
                flowType:
                    type: string
                    enum:
                        [
                            abandoned_cart,
                            cod_to_prepaid,
                            ndr_followup,
                            address_confirmation,
                            post_delivery_feedback,
                        ]
                    example: abandoned_cart
                title:
                    type: string
                    example: Abandoned cart recovery
                tagline:
                    type: string
                    description: Short value prop shown on the card.
                    example: Avg 18% recovery
                description:
                    type: string
                    example: AI calls within 90 seconds of cart drop. Handles objections, shares the link, and recovers the order.
                iconColor:
                    type: string
                    description: Hex background color for the flow icon tile.
                    example: '#E1F5EE'
                durationSecs:
                    type: integer
                    example: 58
                audioUrl:
                    type: string
                    example: 'https://storage.miraiminds.co/voice-agents/production/flows/abandoned_cart_demo.wav'
                waveformUrl:
                    type: string
                    nullable: true
                    example: 'https://storage.miraiminds.co/voice-agents/production/flows/abandoned_cart_demo.json'
                highlightMoments:
                    type: array
                    items:
                        $ref: '#/components/schemas/ShowcaseHighlightMoment'
                whatToNotice:
                    type: string
                    nullable: true
                    example: Notice the objection handling at 0:38 — AI listens first before responding.
                tags:
                    type: array
                    items:
                        type: string
                    example: [cart_recovery, hindi]
                sortOrder:
                    type: integer
                    example: 1
                workspace:
                    type: string
                    description: ObjectId reference to the workspace this flow belongs to.
                    example: '507f1f77bcf86cd799439011'
                organization:
                    type: string
                    description: ObjectId reference to the organization this flow belongs to.
                    example: '507f1f77bcf86cd799439010'
                assistant_id:
                    type: string
                    description: ObjectId reference to the assistant used in this flow.
                    example: '507f1f77bcf86cd799439013'
            required:
                [
                    flowType,
                    title,
                    tagline,
                    description,
                    durationSecs,
                    audioUrl,
                    sortOrder,
                    workspace,
                    organization,
                    assistant_id,
                ]
