> ## Documentation Index
> Fetch the complete documentation index at: https://docs.miraiminds.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Create AI Assistant

> 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.




## OpenAPI

````yaml https://api.voice-agents.miraiminds.co/swagger.yaml post /v1/admin/assistant/create
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: []
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:
  /v1/admin/assistant/create:
    post:
      tags:
        - Assistant
      summary: Create AI Assistant
      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.
      operationId: adminCreateAssistant
      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
components:
  parameters:
    PublicKeyHeader:
      name: x-public-key
      in: header
      required: true
      schema:
        type: string
    PrivateKeyHeader:
      name: x-private-key
      in: header
      required: true
      schema:
        type: string
    WorkspaceHeader:
      name: workspace
      in: header
      required: true
      schema:
        type: string
  schemas:
    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'
    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'
    AgentIdentity:
      type: object
      properties:
        name:
          type: string
        gender:
          type: string
          enum:
            - male
            - female
        voice:
          type: string
    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
    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.
        language:
          type: string
          enum:
            - hinglish
            - english
            - hindi
            - telugu
            - tamil
            - kannada
            - malayalam
            - gujarati
            - punjabi
            - odia
            - marathi
          description: Affects language complexity and speed.
        targetAudience:
          type: array
          items:
            type: string
            enum:
              - male
              - female
              - children
          description: Affects language complexity and speed.
    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'
    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'
    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'
    SupportContacts:
      type: object
      properties:
        phoneNumber:
          type: string
          example: '+919876543210'
        email:
          type: string
          format: email
          example: support@example.com
    CallInsightPlan:
      type: object
      additionalProperties:
        $ref: '#/components/schemas/InsightField'
      description: Map of insight names to their expected structure.
    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
    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.
    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
  securitySchemes:
    PublicKeyAuth:
      type: apiKey
      in: header
      name: x-public-key
    PrivateKeyAuth:
      type: apiKey
      in: header
      name: x-private-key

````